protected String setupHttpEntityEnclosingRequestData()

in src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java [1537:1677]


    protected String setupHttpEntityEnclosingRequestData(HttpEntityEnclosingRequestBase entityEnclosingRequest)  throws IOException {
        // Buffer to hold the post body, except file content
        StringBuilder postedBody = new StringBuilder(1000);
        HTTPFileArg[] files = getHTTPFiles();

        final String contentEncoding = getContentEncoding();
        Charset charset = Charset.forName(contentEncoding);
        final boolean haveContentEncoding = true;

        // Check if we should do a multipart/form-data or an
        // application/x-www-form-urlencoded post request
        if(getUseMultipart()) {
            if (entityEnclosingRequest.getHeaders(HTTPConstants.HEADER_CONTENT_TYPE).length > 0) {
                log.info(
                        "Content-Header is set already on the request! Will be replaced by a Multipart-Header. Old headers: {}",
                        Arrays.asList(entityEnclosingRequest.getHeaders(HTTPConstants.HEADER_CONTENT_TYPE)));
                entityEnclosingRequest.removeHeaders(HTTPConstants.HEADER_CONTENT_TYPE);
            }

            // doBrowserCompatibleMultipart means "use charset for encoding MIME headers",
            // while RFC6532 means "use UTF-8 for encoding MIME headers"
            boolean doBrowserCompatibleMultipart = getDoBrowserCompatibleMultipart();
            if(log.isDebugEnabled()) {
                log.debug("Building multipart with:getDoBrowserCompatibleMultipart(): {}, with charset:{}, haveContentEncoding:{}",
                        doBrowserCompatibleMultipart, charset, haveContentEncoding);
            }
            // Write the request to our own stream
            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
            multipartEntityBuilder.setCharset(charset);
            if (doBrowserCompatibleMultipart) {
                multipartEntityBuilder.setLaxMode();
            } else {
                // Use UTF-8 for encoding header names and values
                multipartEntityBuilder.setMode(HttpMultipartMode.RFC6532);
            }
            // Create the parts
            // Add any parameters
            for (JMeterProperty jMeterProperty : getArguments()) {
                HTTPArgument arg = (HTTPArgument) jMeterProperty.getObjectValue();
                String parameterName = arg.getName();
                if (arg.isSkippable(parameterName)) {
                    continue;
                }
                ContentType contentType;
                if (arg.getContentType().indexOf(';') >= 0) {
                    // assume, that the content type contains charset info
                    // don't add another charset and use parse to cope with the semicolon
                    contentType = ContentType.parse(arg.getContentType());
                } else {
                    contentType = ContentType.create(arg.getContentType(), charset);
                }
                StringBody stringBody = new StringBody(arg.getValue(), contentType);
                FormBodyPart formPart = FormBodyPartBuilder.create(
                        parameterName, stringBody).build();
                multipartEntityBuilder.addPart(formPart);
            }

            // Add any files
            // Cannot retrieve parts once added to the MultiPartEntity, so have to save them here.
            ViewableFileBody[] fileBodies = new ViewableFileBody[files.length];
            for (int i=0; i < files.length; i++) {
                HTTPFileArg file = files[i];

                File reservedFile = FileServer.getFileServer().getResolvedFile(file.getPath());
                Charset filenameCharset = doBrowserCompatibleMultipart ? charset : StandardCharsets.UTF_8;
                fileBodies[i] = new ViewableFileBody(reservedFile, ContentType.parse(file.getMimeType()), filenameCharset);
                multipartEntityBuilder.addPart(file.getParamName(), fileBodies[i] );
            }

            HttpEntity entity = multipartEntityBuilder.build();
            entityEnclosingRequest.setEntity(entity);
            writeEntityToSB(postedBody, entity, fileBodies, contentEncoding);
        } else { // not multipart
            // Check if the header manager had a content type header
            // This allows the user to specify their own content-type for a POST request
            Header contentTypeHeader = entityEnclosingRequest.getFirstHeader(HTTPConstants.HEADER_CONTENT_TYPE);
            boolean hasContentTypeHeader = contentTypeHeader != null && contentTypeHeader.getValue() != null && contentTypeHeader.getValue().length() > 0;
            // If there are no arguments, we can send a file as the body of the request
            // TODO: needs a multiple file upload scenario
            if(!hasArguments() && getSendFileAsPostBody()) {
                // If getSendFileAsPostBody returned true, it's sure that file is not null
                HTTPFileArg file = files[0];
                if(!hasContentTypeHeader) {
                    // Allow the mimetype of the file to control the content type
                    if(file.getMimeType() != null && file.getMimeType().length() > 0) {
                        entityEnclosingRequest.setHeader(HTTPConstants.HEADER_CONTENT_TYPE, file.getMimeType());
                    }
                    else if(ADD_CONTENT_TYPE_TO_POST_IF_MISSING) {
                        entityEnclosingRequest.setHeader(HTTPConstants.HEADER_CONTENT_TYPE, HTTPConstants.APPLICATION_X_WWW_FORM_URLENCODED);
                    }
                }
                FileEntity fileRequestEntity = new FileEntity(FileServer.getFileServer().getResolvedFile(file.getPath()), (ContentType) null);
                entityEnclosingRequest.setEntity(fileRequestEntity);

                // We just add placeholder text for file content
                postedBody.append("<actual file content, not shown here>");
            } else {
                // In a post request which is not multipart, we only support
                // parameters, no file upload is allowed

                // If none of the arguments have a name specified, we
                // just send all the values as the post body
                if(getSendParameterValuesAsPostBody()) {
                    // Allow the mimetype of the file to control the content type
                    // This is not obvious in GUI if you are not uploading any files,
                    // but just sending the content of nameless parameters
                    // TODO: needs a multiple file upload scenario
                    if(!hasContentTypeHeader) {
                        HTTPFileArg file = files.length > 0? files[0] : null;
                        if(file != null && file.getMimeType() != null && file.getMimeType().length() > 0) {
                            entityEnclosingRequest.setHeader(HTTPConstants.HEADER_CONTENT_TYPE, file.getMimeType());
                        }
                        else if(ADD_CONTENT_TYPE_TO_POST_IF_MISSING) {
                            entityEnclosingRequest.setHeader(HTTPConstants.HEADER_CONTENT_TYPE, HTTPConstants.APPLICATION_X_WWW_FORM_URLENCODED);
                        }
                    }

                    // Just append all the parameter values, and use that as the post body
                    StringBuilder postBody = new StringBuilder();
                    for (JMeterProperty jMeterProperty : getArguments()) {
                        HTTPArgument arg = (HTTPArgument) jMeterProperty.getObjectValue();
                        postBody.append(arg.getEncodedValue(contentEncoding));
                    }
                    // Let StringEntity perform the encoding
                    StringEntity requestEntity = new StringEntity(postBody.toString(), contentEncoding);
                    entityEnclosingRequest.setEntity(requestEntity);
                    postedBody.append(postBody.toString());
                } else {
                    // It is a normal post request, with parameter names and values
                    // Set the content type
                    if(!hasContentTypeHeader && ADD_CONTENT_TYPE_TO_POST_IF_MISSING) {
                        entityEnclosingRequest.setHeader(HTTPConstants.HEADER_CONTENT_TYPE, HTTPConstants.APPLICATION_X_WWW_FORM_URLENCODED);
                    }
                    UrlEncodedFormEntity entity = createUrlEncodedFormEntity(contentEncoding);
                    entityEnclosingRequest.setEntity(entity);
                    writeEntityToSB(postedBody, entity, EMPTY_FILE_BODIES, contentEncoding);
                }
            }
        }
        return postedBody.toString();
    }