[JAVA-15024] Upgraded multipart functionality to apache client 5 (#13378)

Co-authored-by: panagiotiskakos <panagiotis.kakos@libra-is.com>
This commit is contained in:
panos-kakos 2023-02-02 17:04:40 +00:00 committed by GitHub
parent 695546987f
commit 7fa5e1159b
3 changed files with 152 additions and 106 deletions

View File

@ -54,6 +54,42 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>org.apache.httpcomponents.core5</groupId>
<artifactId>httpcore5</artifactId>
<version>${httpcore5.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5-fluent</artifactId>
<version>${httpclient5-fluent.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>${httpclient5.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency> <dependency>
<groupId>com.github.tomakehurst</groupId> <groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId> <artifactId>wiremock</artifactId>
@ -78,6 +114,10 @@
<!-- testing --> <!-- testing -->
<wiremock.version>2.5.1</wiremock.version> <wiremock.version>2.5.1</wiremock.version>
<httpclient.version>4.5.8</httpclient.version> <!-- 4.3.6 --> <!-- 4.4-beta1 --> <httpclient.version>4.5.8</httpclient.version> <!-- 4.3.6 --> <!-- 4.4-beta1 -->
<!-- http client & core 5 -->
<httpcore5.version>5.2</httpcore5.version>
<httpclient5.version>5.2</httpclient5.version>
<httpclient5-fluent.version>5.2</httpclient5-fluent.version>
</properties> </properties>
</project> </project>

View File

@ -1,19 +1,24 @@
package com.baeldung.httpclient; package com.baeldung.httpclient;
import org.apache.http.HttpEntity; import static org.hamcrest.MatcherAssert.assertThat;
import org.apache.http.HttpStatus; import static org.hamcrest.Matchers.equalTo;
import org.apache.http.client.methods.CloseableHttpResponse; import static org.junit.jupiter.api.Assertions.assertTrue;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType; import org.junit.jupiter.api.BeforeEach;
import org.apache.http.entity.mime.HttpMultipartMode; import org.junit.jupiter.api.Test;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody; import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.http.entity.mime.content.StringBody; import org.apache.hc.client5.http.entity.mime.FileBody;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
import org.apache.http.impl.client.HttpClientBuilder; import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
import org.junit.After; import org.apache.hc.client5.http.entity.mime.StringBody;
import org.junit.Before; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.junit.Test; import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpStatus;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
@ -22,14 +27,10 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.URL; import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import static org.hamcrest.Matchers.equalTo; import com.baeldung.httpclient.handler.CustomHttpClientResponseHandler;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
public class HttpClientMultipartLiveTest { class HttpClientMultipartLiveTest {
// No longer available // No longer available
// private static final String SERVER = "http://echo.200please.com"; // private static final String SERVER = "http://echo.200please.com";
@ -38,41 +39,16 @@ public class HttpClientMultipartLiveTest {
private static final String TEXTFILENAME = "temp.txt"; private static final String TEXTFILENAME = "temp.txt";
private static final String IMAGEFILENAME = "image.jpg"; private static final String IMAGEFILENAME = "image.jpg";
private static final String ZIPFILENAME = "zipFile.zip"; private static final String ZIPFILENAME = "zipFile.zip";
private static final Logger LOGGER = Logger.getLogger("com.baeldung.httpclient.HttpClientMultipartLiveTest");
private CloseableHttpClient client;
private HttpPost post; private HttpPost post;
private BufferedReader rd; private BufferedReader rd;
private CloseableHttpResponse response;
@Before @BeforeEach
public final void before() { public void before() {
client = HttpClientBuilder.create()
.build();
post = new HttpPost(SERVER); post = new HttpPost(SERVER);
} }
@After
public final void after() throws IllegalStateException, IOException {
post.completed();
try {
client.close();
} catch (final IOException e1) {
LOGGER.log(Level.SEVERE, e1.getMessage(), e1);
throw e1;
}
try {
rd.close();
} catch (final IOException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
throw e;
}
ResponseUtil.closeResponse(response);
}
// tests
@Test @Test
public final void givenFileandMultipleTextParts_whenUploadwithAddPart_thenNoExceptions() throws IOException { void givenFileandMultipleTextParts_whenUploadwithAddPart_thenNoExceptions() throws IOException {
final URL url = Thread.currentThread() final URL url = Thread.currentThread()
.getContextClassLoader() .getContextClassLoader()
.getResource("uploads/" + TEXTFILENAME); .getResource("uploads/" + TEXTFILENAME);
@ -83,53 +59,61 @@ public class HttpClientMultipartLiveTest {
final StringBody stringBody2 = new StringBody("This is message 2", ContentType.MULTIPART_FORM_DATA); final StringBody stringBody2 = new StringBody("This is message 2", ContentType.MULTIPART_FORM_DATA);
// //
final MultipartEntityBuilder builder = MultipartEntityBuilder.create(); final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); builder.setMode(HttpMultipartMode.LEGACY);
builder.addPart("file", fileBody); builder.addPart("file", fileBody);
builder.addPart("text1", stringBody1); builder.addPart("text1", stringBody1);
builder.addPart("text2", stringBody2); builder.addPart("text2", stringBody2);
final HttpEntity entity = builder.build(); final HttpEntity entity = builder.build();
//
post.setEntity(entity);
response = client.execute(post);
final int statusCode = response.getStatusLine() post.setEntity(entity);
.getStatusCode(); try(CloseableHttpClient client = HttpClientBuilder.create()
final String responseString = getContent(); .build();
final String contentTypeInHeader = getContentTypeHeader();
assertThat(statusCode, equalTo(HttpStatus.SC_OK)); CloseableHttpResponse response = (CloseableHttpResponse) client
// assertTrue(responseString.contains("Content-Type: multipart/form-data;")); .execute(post, new CustomHttpClientResponseHandler())){
assertTrue(contentTypeInHeader.contains("Content-Type: multipart/form-data;")); final int statusCode = response.getCode();
System.out.println(responseString); final String responseString = getContent(response.getEntity());
System.out.println("POST Content Type: " + contentTypeInHeader); final String contentTypeInHeader = getContentTypeHeader();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));
assertTrue(contentTypeInHeader.contains("Content-Type: multipart/form-data;"));
System.out.println(responseString);
System.out.println("POST Content Type: " + contentTypeInHeader);
}
} }
@Test @Test
public final void givenFileandTextPart_whenUploadwithAddBinaryBodyandAddTextBody_ThenNoExeption() throws IOException { void givenFileandTextPart_whenUploadwithAddBinaryBodyandAddTextBody_ThenNoExeption() throws IOException {
final URL url = Thread.currentThread() final URL url = Thread.currentThread()
.getContextClassLoader() .getContextClassLoader()
.getResource("uploads/" + TEXTFILENAME); .getResource("uploads/" + TEXTFILENAME);
final File file = new File(url.getPath()); final File file = new File(url.getPath());
final String message = "This is a multipart post"; final String message = "This is a multipart post";
final MultipartEntityBuilder builder = MultipartEntityBuilder.create(); final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); builder.setMode(HttpMultipartMode.LEGACY);
builder.addBinaryBody("file", file, ContentType.DEFAULT_BINARY, TEXTFILENAME); builder.addBinaryBody("file", file, ContentType.DEFAULT_BINARY, TEXTFILENAME);
builder.addTextBody("text", message, ContentType.DEFAULT_BINARY); builder.addTextBody("text", message, ContentType.DEFAULT_BINARY);
final HttpEntity entity = builder.build(); final HttpEntity entity = builder.build();
post.setEntity(entity); post.setEntity(entity);
response = client.execute(post);
final int statusCode = response.getStatusLine() try(CloseableHttpClient client = HttpClientBuilder.create()
.getStatusCode(); .build();
final String responseString = getContent();
final String contentTypeInHeader = getContentTypeHeader(); CloseableHttpResponse response = (CloseableHttpResponse) client
assertThat(statusCode, equalTo(HttpStatus.SC_OK)); .execute(post, new CustomHttpClientResponseHandler())){
// assertTrue(responseString.contains("Content-Type: multipart/form-data;"));
assertTrue(contentTypeInHeader.contains("Content-Type: multipart/form-data;")); final int statusCode = response.getCode();
System.out.println(responseString); final String responseString = getContent(response.getEntity());
System.out.println("POST Content Type: " + contentTypeInHeader); final String contentTypeInHeader = getContentTypeHeader();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));
assertTrue(contentTypeInHeader.contains("Content-Type: multipart/form-data;"));
System.out.println(responseString);
System.out.println("POST Content Type: " + contentTypeInHeader);
}
} }
@Test @Test
public final void givenFileAndInputStreamandText_whenUploadwithAddBinaryBodyandAddTextBody_ThenNoException() throws IOException { void givenFileAndInputStreamandText_whenUploadwithAddBinaryBodyandAddTextBody_ThenNoException() throws IOException {
final URL url = Thread.currentThread() final URL url = Thread.currentThread()
.getContextClassLoader() .getContextClassLoader()
.getResource("uploads/" + ZIPFILENAME); .getResource("uploads/" + ZIPFILENAME);
@ -140,64 +124,75 @@ public class HttpClientMultipartLiveTest {
final File file = new File(url2.getPath()); final File file = new File(url2.getPath());
final String message = "This is a multipart post"; final String message = "This is a multipart post";
final MultipartEntityBuilder builder = MultipartEntityBuilder.create(); final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); builder.setMode(HttpMultipartMode.STRICT);
builder.addBinaryBody("file", file, ContentType.DEFAULT_BINARY, IMAGEFILENAME); builder.addBinaryBody("file", file, ContentType.DEFAULT_BINARY, IMAGEFILENAME);
builder.addBinaryBody("upstream", inputStream, ContentType.create("application/zip"), ZIPFILENAME); builder.addBinaryBody("upstream", inputStream, ContentType.create("application/zip"), ZIPFILENAME);
builder.addTextBody("text", message, ContentType.TEXT_PLAIN); builder.addTextBody("text", message, ContentType.TEXT_PLAIN);
final HttpEntity entity = builder.build(); final HttpEntity entity = builder.build();
post.setEntity(entity); post.setEntity(entity);
response = client.execute(post);
final int statusCode = response.getStatusLine() try(CloseableHttpClient client = HttpClientBuilder.create()
.getStatusCode(); .build();
final String responseString = getContent();
final String contentTypeInHeader = getContentTypeHeader(); CloseableHttpResponse response = (CloseableHttpResponse) client
assertThat(statusCode, equalTo(HttpStatus.SC_OK)); .execute(post, new CustomHttpClientResponseHandler())){
// assertTrue(responseString.contains("Content-Type: multipart/form-data;"));
assertTrue(contentTypeInHeader.contains("Content-Type: multipart/form-data;")); final int statusCode = response.getCode();
System.out.println(responseString); final String responseString = getContent(response.getEntity());
System.out.println("POST Content Type: " + contentTypeInHeader); final String contentTypeInHeader = getContentTypeHeader();
inputStream.close(); assertThat(statusCode, equalTo(HttpStatus.SC_OK));
assertTrue(contentTypeInHeader.contains("Content-Type: multipart/form-data;"));
System.out.println(responseString);
System.out.println("POST Content Type: " + contentTypeInHeader);
inputStream.close();
}
} }
@Test @Test
public final void givenCharArrayandText_whenUploadwithAddBinaryBodyandAddTextBody_ThenNoException() throws IOException { void givenCharArrayandText_whenUploadwithAddBinaryBodyandAddTextBody_ThenNoException() throws IOException {
final String message = "This is a multipart post"; final String message = "This is a multipart post";
final byte[] bytes = "binary code".getBytes(); final byte[] bytes = "binary code".getBytes();
final MultipartEntityBuilder builder = MultipartEntityBuilder.create(); final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); builder.setMode(HttpMultipartMode.STRICT);
builder.addBinaryBody("file", bytes, ContentType.DEFAULT_BINARY, TEXTFILENAME); builder.addBinaryBody("file", bytes, ContentType.DEFAULT_BINARY, TEXTFILENAME);
builder.addTextBody("text", message, ContentType.TEXT_PLAIN); builder.addTextBody("text", message, ContentType.TEXT_PLAIN);
final HttpEntity entity = builder.build(); final HttpEntity entity = builder.build();
post.setEntity(entity); post.setEntity(entity);
response = client.execute(post);
final int statusCode = response.getStatusLine() try(CloseableHttpClient client = HttpClientBuilder.create()
.getStatusCode(); .build();
final String responseString = getContent();
final String contentTypeInHeader = getContentTypeHeader(); CloseableHttpResponse response = (CloseableHttpResponse) client
assertThat(statusCode, equalTo(HttpStatus.SC_OK)); .execute(post, new CustomHttpClientResponseHandler())){
// assertTrue(responseString.contains("Content-Type: multipart/form-data;"));
assertTrue(contentTypeInHeader.contains("Content-Type: multipart/form-data;")); final int statusCode = response.getCode();
System.out.println(responseString); final String responseString = getContent(response.getEntity());
System.out.println("POST Content Type: " + contentTypeInHeader); final String contentTypeInHeader = getContentTypeHeader();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));
assertTrue(contentTypeInHeader.contains("Content-Type: multipart/form-data;"));
System.out.println(responseString);
System.out.println("POST Content Type: " + contentTypeInHeader);
}
} }
// UTIL // UTIL
private String getContent() throws IOException { private String getContent(HttpEntity httpEntity) throws IOException {
rd = new BufferedReader(new InputStreamReader(response.getEntity() rd = new BufferedReader(new InputStreamReader(httpEntity.getContent()));
.getContent()));
String body = ""; String body = "";
StringBuilder content = new StringBuilder(); StringBuilder content = new StringBuilder();
while ((body = rd.readLine()) != null) { while ((body = rd.readLine()) != null) {
content.append(body).append("\n"); content.append(body)
.append("\n");
} }
return content.toString().trim(); return content.toString()
.trim();
} }
private String getContentTypeHeader() throws IOException { private String getContentTypeHeader() {
return post.getEntity() return post.getEntity()
.getContentType() .getContentType();
.toString();
} }
} }

View File

@ -0,0 +1,11 @@
package com.baeldung.httpclient.handler;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.io.HttpClientResponseHandler;
public class CustomHttpClientResponseHandler implements HttpClientResponseHandler<ClassicHttpResponse> {
@Override
public ClassicHttpResponse handleResponse(ClassicHttpResponse response) {
return response;
}
}