1. Overview

In this tutorial, we’ll POST with the HttpClient 5, first using authorization, then the fluent HttpClient API.

Finally, we’ll discuss how to upload a file using HttpClient.

2. Basic POST

First, let’s go over a simple example and send a POST request using HttpClient.

We’ll do a POST with two parameters, “username” and “password“:

@Test
void whenSendPostRequestUsingHttpClient_thenCorrect() throws IOException {
    final HttpPost httpPost = new HttpPost(SAMPLE_URL);
    final List<NameValuePair> params = new ArrayList<NameValuePair>();
    params.add(new BasicNameValuePair("username", DEFAULT_USER));
    params.add(new BasicNameValuePair("password", DEFAULT_PASS));
    httpPost.setEntity(new UrlEncodedFormEntity(params));

    try (CloseableHttpClient client = HttpClients.createDefault();
        CloseableHttpResponse response = (CloseableHttpResponse) client
            .execute(httpPost, new CustomHttpClientResponseHandler())) {

        final int statusCode = response.getCode();
        assertThat(statusCode, equalTo(HttpStatus.SC_OK));
    }
}

Note how we used a List of NameValuePair to include parameters in the POST request.

3. POST With Authorization

Next, let’s see how to do a POST with Authentication credentials using the HttpClient.

In the following example, we’ll send a POST request to a URL secured with Basic Authentication:

@Test
void whenSendPostRequestWithAuthorizationUsingHttpClient_thenCorrect() throws IOException {
    final HttpPost httpPost = new HttpPost(URL_SECURED_BY_BASIC_AUTHENTICATION);
    httpPost.setEntity(new StringEntity("test post"));

    final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
    final UsernamePasswordCredentials credentials = 
        new UsernamePasswordCredentials(DEFAULT_USER, DEFAULT_PASS.toCharArray());

    credsProvider.setCredentials(new AuthScope(URL_SECURED_BY_BASIC_AUTHENTICATION, 80) ,credentials);

    try (CloseableHttpClient client = HttpClients.custom()
        .setDefaultCredentialsProvider(credsProvider)
        .build();

        CloseableHttpResponse response = (CloseableHttpResponse) client
            .execute(httpPost, new CustomHttpClientResponseHandler())) {

        final int statusCode = response.getCode();
        assertThat(statusCode, equalTo(HttpStatus.SC_OK));
    }
}

4. POST With JSON

Now let’s see how to send a POST request with a JSON body using the HttpClient.

In the following example, we’ll send some person information (id, name) as JSON:

@Test
void whenPostJsonUsingHttpClient_thenCorrect() throws IOException {
    final HttpPost httpPost = new HttpPost(SAMPLE_URL);

    final String json = "{"id":1,"name":"John"}";
    final StringEntity entity = new StringEntity(json);
    httpPost.setEntity(entity);
    httpPost.setHeader("Accept", "application/json");
    httpPost.setHeader("Content-type", "application/json");

    try (CloseableHttpClient client = HttpClients.createDefault();
        CloseableHttpResponse response = (CloseableHttpResponse) client
            .execute(httpPost, new CustomHttpClientResponseHandler())) {

        final int statusCode = response.getCode();
        assertThat(statusCode, equalTo(HttpStatus.SC_OK));
    }
}

Note how we’re using the StringEntity to set the body of the request.

We’re also setting the ContentType header to application/json to give the server the necessary information about the representation of the content we’re sending.

5. POST With the HttpClient Fluent API

Next, let’s POST with the HttpClient Fluent API.

We’ll send a request with two parameters, “username” and “password“:

@Test
void whenPostFormUsingHttpClientFluentAPI_thenCorrect() throws IOException {
    Request request = Request.post(SAMPLE_URL)
        .bodyForm(Form.form()
            .add("username", DEFAULT_USER)
            .add("password", DEFAULT_PASS)
            .build());

    HttpResponse response = request.execute()
        .returnResponse();
    assertThat(response.getCode(), equalTo(HttpStatus.SC_OK));
}

6. POST Multipart Request

Now let’s POST a Multipart Request.

We’ll post a File, username, and password using MultipartEntityBuilder:

@Test
void whenSendMultipartRequestUsingHttpClient_thenCorrect() throws IOException {
    final HttpPost httpPost = new HttpPost(SAMPLE_URL);

    final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    builder.addTextBody("username", DEFAULT_USER);
    builder.addTextBody("password", DEFAULT_PASS);
    builder.addBinaryBody(
        "file", new File("src/test/resources/test.in"), ContentType.APPLICATION_OCTET_STREAM, "file.ext");

    final HttpEntity multipart = builder.build();
    httpPost.setEntity(multipart);

    try (CloseableHttpClient client = HttpClients.createDefault();
        CloseableHttpResponse response = (CloseableHttpResponse) client
            .execute(httpPost, new CustomHttpClientResponseHandler())) {

        final int statusCode = response.getCode();
        assertThat(statusCode, equalTo(HttpStatus.SC_OK));
    }
}

7. Upload a File Using HttpClient

Next, let’s see how to upload a File using the HttpClient.

We’ll upload the “test.txt” file using MultipartEntityBuilder:

@Test
void whenUploadFileUsingHttpClient_thenCorrect() throws IOException {
    final HttpPost httpPost = new HttpPost(SAMPLE_URL);

    final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    builder.addBinaryBody(
        "file", new File("src/test/resources/test.in"), ContentType.APPLICATION_OCTET_STREAM, "file.ext");
    final HttpEntity multipart = builder.build();

    httpPost.setEntity(multipart);

    try (CloseableHttpClient client = HttpClients.createDefault();
        CloseableHttpResponse response = (CloseableHttpResponse) client
            .execute(httpPost, new CustomHttpClientResponseHandler())) {

        final int statusCode = response.getCode();
        assertThat(statusCode, equalTo(HttpStatus.SC_OK));
    }
}

8. Get File Upload Progress

Finally, let’s see how to get the progress of File upload using HttpClient.

In the following example, we’ll extend the HttpEntityWrapper to gain visibility into the upload process.

First, here’s the upload method:

@Test
void whenGetUploadFileProgressUsingHttpClient_thenCorrect() throws IOException {
    final HttpPost httpPost = new HttpPost(SAMPLE_URL);

    final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    builder.addBinaryBody(
        "file", new File("src/test/resources/test.in"), ContentType.APPLICATION_OCTET_STREAM, "file.ext");
    final HttpEntity multipart = builder.build();

    final ProgressEntityWrapper.ProgressListener pListener = 
        percentage -> assertFalse(Float.compare(percentage, 100) > 0);

    httpPost.setEntity(new ProgressEntityWrapper(multipart, pListener));

    try (CloseableHttpClient client = HttpClients.createDefault();
        CloseableHttpResponse response = (CloseableHttpResponse) client
            .execute(httpPost, new CustomHttpClientResponseHandler())) {

        final int statusCode = response.getCode();
        assertThat(statusCode, equalTo(HttpStatus.SC_OK));
    }
}

We’ll also add the interface ProgressListener that enables us to observe the upload progress:

public static interface ProgressListener {
    void progress(float percentage);
}

Here’s our extended version of HttpEntityWrapper,ProgressEntityWrapper“:

public class ProgressEntityWrapper extends HttpEntityWrapper {
    private ProgressListener listener;

    public ProgressEntityWrapper(HttpEntity entity, ProgressListener listener) {
        super(entity);
        this.listener = listener;
    }

    @Override
    public void writeTo(OutputStream outstream) throws IOException {
        super.writeTo(new CountingOutputStream(outstream, listener, getContentLength()));
    }
}

And here’s the extended version of FilterOutputStream,CountingOutputStream“:

public static class CountingOutputStream extends FilterOutputStream {
    private ProgressListener listener;
    private long transferred;
    private long totalBytes;

    public CountingOutputStream(
      OutputStream out, ProgressListener listener, long totalBytes) {
        super(out);
        this.listener = listener;
        transferred = 0;
        this.totalBytes = totalBytes;
    }

    @Override
    public void write(byte[] b, int off, int len) throws IOException {
        out.write(b, off, len);
        transferred += len;
        listener.progress(getCurrentProgress());
    }

    @Override
    public void write(int b) throws IOException {
        out.write(b);
        transferred++;
        listener.progress(getCurrentProgress());
    }

    private float getCurrentProgress() {
        return ((float) transferred / totalBytes) * 100;
    }
}

Note that:

  • When extending FilterOutputStream to “CountingOutputStream,” we’re overriding the write() method to count the written (transferred) bytes
  • When extending HttpEntityWrapper to “ProgressEntityWrapper,” we’re overriding the writeTo() method to use our “CountingOutputStream”

9. Conclusion

In this article, we illustrated the most common ways to send POST HTTP Requests with the Apache HttpClient 5.

We learned how to send a POST request with Authorization, how to post using HttpClient fluent API, and how to upload a file and track its progress.

The implementation of all these examples and code snippets can be found in the github project.