mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-08-29 03:06:45 +08:00
Migrate CLI to Apache HttpClient 5
Closes gh-33534
This commit is contained in:
parent
1588f9d881
commit
0b6dade142
@ -25,9 +25,7 @@ dependencies {
|
|||||||
implementation("com.vaadin.external.google:android-json")
|
implementation("com.vaadin.external.google:android-json")
|
||||||
implementation("jline:jline")
|
implementation("jline:jline")
|
||||||
implementation("net.sf.jopt-simple:jopt-simple")
|
implementation("net.sf.jopt-simple:jopt-simple")
|
||||||
implementation("org.apache.httpcomponents:httpclient") {
|
implementation("org.apache.httpcomponents.client5:httpclient5")
|
||||||
exclude group: "commons-logging", module: "commons-logging"
|
|
||||||
}
|
|
||||||
implementation("org.slf4j:slf4j-simple")
|
implementation("org.slf4j:slf4j-simple")
|
||||||
implementation("org.springframework:spring-core")
|
implementation("org.springframework:spring-core")
|
||||||
implementation("org.springframework.security:spring-security-crypto")
|
implementation("org.springframework.security:spring-security-crypto")
|
||||||
|
@ -21,16 +21,18 @@ import java.net.URI;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import org.apache.http.Header;
|
import org.apache.hc.client5.http.classic.HttpClient;
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
||||||
import org.apache.http.HttpHeaders;
|
import org.apache.hc.client5.http.classic.methods.HttpUriRequest;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.hc.core5.http.ClassicHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpUriRequest;
|
import org.apache.hc.core5.http.ContentType;
|
||||||
import org.apache.http.entity.ContentType;
|
import org.apache.hc.core5.http.Header;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.hc.core5.http.HttpEntity;
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
import org.apache.hc.core5.http.HttpHeaders;
|
||||||
import org.apache.http.message.BasicHeader;
|
import org.apache.hc.core5.http.HttpHost;
|
||||||
|
import org.apache.hc.core5.http.message.BasicHeader;
|
||||||
|
import org.apache.hc.core5.http.message.StatusLine;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
@ -62,16 +64,16 @@ class InitializrService {
|
|||||||
/**
|
/**
|
||||||
* Late binding HTTP client.
|
* Late binding HTTP client.
|
||||||
*/
|
*/
|
||||||
private CloseableHttpClient http;
|
private HttpClient http;
|
||||||
|
|
||||||
InitializrService() {
|
InitializrService() {
|
||||||
}
|
}
|
||||||
|
|
||||||
InitializrService(CloseableHttpClient http) {
|
InitializrService(HttpClient http) {
|
||||||
this.http = http;
|
this.http = http;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CloseableHttpClient getHttp() {
|
protected HttpClient getHttp() {
|
||||||
if (this.http == null) {
|
if (this.http == null) {
|
||||||
this.http = HttpClientBuilder.create().useSystemProperties().build();
|
this.http = HttpClientBuilder.create().useSystemProperties().build();
|
||||||
}
|
}
|
||||||
@ -88,7 +90,7 @@ class InitializrService {
|
|||||||
Log.info("Using service at " + request.getServiceUrl());
|
Log.info("Using service at " + request.getServiceUrl());
|
||||||
InitializrServiceMetadata metadata = loadMetadata(request.getServiceUrl());
|
InitializrServiceMetadata metadata = loadMetadata(request.getServiceUrl());
|
||||||
URI url = request.generateUrl(metadata);
|
URI url = request.generateUrl(metadata);
|
||||||
CloseableHttpResponse httpResponse = executeProjectGenerationRequest(url);
|
ClassicHttpResponse httpResponse = executeProjectGenerationRequest(url);
|
||||||
HttpEntity httpEntity = httpResponse.getEntity();
|
HttpEntity httpEntity = httpResponse.getEntity();
|
||||||
validateResponse(httpResponse, request.getServiceUrl());
|
validateResponse(httpResponse, request.getServiceUrl());
|
||||||
return createResponse(httpResponse, httpEntity);
|
return createResponse(httpResponse, httpEntity);
|
||||||
@ -101,7 +103,7 @@ class InitializrService {
|
|||||||
* @throws IOException if the service's metadata cannot be loaded
|
* @throws IOException if the service's metadata cannot be loaded
|
||||||
*/
|
*/
|
||||||
InitializrServiceMetadata loadMetadata(String serviceUrl) throws IOException {
|
InitializrServiceMetadata loadMetadata(String serviceUrl) throws IOException {
|
||||||
CloseableHttpResponse httpResponse = executeInitializrMetadataRetrieval(serviceUrl);
|
ClassicHttpResponse httpResponse = executeInitializrMetadataRetrieval(serviceUrl);
|
||||||
validateResponse(httpResponse, serviceUrl);
|
validateResponse(httpResponse, serviceUrl);
|
||||||
return parseJsonMetadata(httpResponse.getEntity());
|
return parseJsonMetadata(httpResponse.getEntity());
|
||||||
}
|
}
|
||||||
@ -118,10 +120,10 @@ class InitializrService {
|
|||||||
Object loadServiceCapabilities(String serviceUrl) throws IOException {
|
Object loadServiceCapabilities(String serviceUrl) throws IOException {
|
||||||
HttpGet request = new HttpGet(serviceUrl);
|
HttpGet request = new HttpGet(serviceUrl);
|
||||||
request.setHeader(new BasicHeader(HttpHeaders.ACCEPT, ACCEPT_SERVICE_CAPABILITIES));
|
request.setHeader(new BasicHeader(HttpHeaders.ACCEPT, ACCEPT_SERVICE_CAPABILITIES));
|
||||||
CloseableHttpResponse httpResponse = execute(request, serviceUrl, "retrieve help");
|
ClassicHttpResponse httpResponse = execute(request, URI.create(serviceUrl), "retrieve help");
|
||||||
validateResponse(httpResponse, serviceUrl);
|
validateResponse(httpResponse, serviceUrl);
|
||||||
HttpEntity httpEntity = httpResponse.getEntity();
|
HttpEntity httpEntity = httpResponse.getEntity();
|
||||||
ContentType contentType = ContentType.getOrDefault(httpEntity);
|
ContentType contentType = ContentType.create(httpEntity.getContentType());
|
||||||
if (contentType.getMimeType().equals("text/plain")) {
|
if (contentType.getMimeType().equals("text/plain")) {
|
||||||
return getContent(httpEntity);
|
return getContent(httpEntity);
|
||||||
}
|
}
|
||||||
@ -137,18 +139,19 @@ class InitializrService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateResponse(CloseableHttpResponse httpResponse, String serviceUrl) {
|
private void validateResponse(ClassicHttpResponse httpResponse, String serviceUrl) {
|
||||||
if (httpResponse.getEntity() == null) {
|
if (httpResponse.getEntity() == null) {
|
||||||
throw new ReportableException("No content received from server '" + serviceUrl + "'");
|
throw new ReportableException("No content received from server '" + serviceUrl + "'");
|
||||||
}
|
}
|
||||||
if (httpResponse.getStatusLine().getStatusCode() != 200) {
|
if (httpResponse.getCode() != 200) {
|
||||||
throw createException(serviceUrl, httpResponse);
|
throw createException(serviceUrl, httpResponse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ProjectGenerationResponse createResponse(CloseableHttpResponse httpResponse, HttpEntity httpEntity)
|
private ProjectGenerationResponse createResponse(ClassicHttpResponse httpResponse, HttpEntity httpEntity)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
ProjectGenerationResponse response = new ProjectGenerationResponse(ContentType.getOrDefault(httpEntity));
|
ProjectGenerationResponse response = new ProjectGenerationResponse(
|
||||||
|
ContentType.create(httpEntity.getContentType()));
|
||||||
response.setContent(FileCopyUtils.copyToByteArray(httpEntity.getContent()));
|
response.setContent(FileCopyUtils.copyToByteArray(httpEntity.getContent()));
|
||||||
String fileName = extractFileName(httpResponse.getFirstHeader("Content-Disposition"));
|
String fileName = extractFileName(httpResponse.getFirstHeader("Content-Disposition"));
|
||||||
if (fileName != null) {
|
if (fileName != null) {
|
||||||
@ -162,7 +165,7 @@ class InitializrService {
|
|||||||
* @param url the URL
|
* @param url the URL
|
||||||
* @return the response
|
* @return the response
|
||||||
*/
|
*/
|
||||||
private CloseableHttpResponse executeProjectGenerationRequest(URI url) {
|
private ClassicHttpResponse executeProjectGenerationRequest(URI url) {
|
||||||
return execute(new HttpGet(url), url, "generate project");
|
return execute(new HttpGet(url), url, "generate project");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,16 +174,17 @@ class InitializrService {
|
|||||||
* @param url the URL
|
* @param url the URL
|
||||||
* @return the response
|
* @return the response
|
||||||
*/
|
*/
|
||||||
private CloseableHttpResponse executeInitializrMetadataRetrieval(String url) {
|
private ClassicHttpResponse executeInitializrMetadataRetrieval(String url) {
|
||||||
HttpGet request = new HttpGet(url);
|
HttpGet request = new HttpGet(url);
|
||||||
request.setHeader(new BasicHeader(HttpHeaders.ACCEPT, ACCEPT_META_DATA));
|
request.setHeader(new BasicHeader(HttpHeaders.ACCEPT, ACCEPT_META_DATA));
|
||||||
return execute(request, url, "retrieve metadata");
|
return execute(request, URI.create(url), "retrieve metadata");
|
||||||
}
|
}
|
||||||
|
|
||||||
private CloseableHttpResponse execute(HttpUriRequest request, Object url, String description) {
|
private ClassicHttpResponse execute(HttpUriRequest request, URI url, String description) {
|
||||||
try {
|
try {
|
||||||
|
HttpHost host = HttpHost.create(url);
|
||||||
request.addHeader("User-Agent", "SpringBootCli/" + getClass().getPackage().getImplementationVersion());
|
request.addHeader("User-Agent", "SpringBootCli/" + getClass().getPackage().getImplementationVersion());
|
||||||
return getHttp().execute(request);
|
return getHttp().execute(host, request);
|
||||||
}
|
}
|
||||||
catch (IOException ex) {
|
catch (IOException ex) {
|
||||||
throw new ReportableException(
|
throw new ReportableException(
|
||||||
@ -188,15 +192,16 @@ class InitializrService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ReportableException createException(String url, CloseableHttpResponse httpResponse) {
|
private ReportableException createException(String url, ClassicHttpResponse httpResponse) {
|
||||||
|
StatusLine statusLine = new StatusLine(httpResponse);
|
||||||
String message = "Initializr service call failed using '" + url + "' - service returned "
|
String message = "Initializr service call failed using '" + url + "' - service returned "
|
||||||
+ httpResponse.getStatusLine().getReasonPhrase();
|
+ statusLine.getReasonPhrase();
|
||||||
String error = extractMessage(httpResponse.getEntity());
|
String error = extractMessage(httpResponse.getEntity());
|
||||||
if (StringUtils.hasText(error)) {
|
if (StringUtils.hasText(error)) {
|
||||||
message += ": '" + error + "'";
|
message += ": '" + error + "'";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int statusCode = httpResponse.getStatusLine().getStatusCode();
|
int statusCode = statusLine.getStatusCode();
|
||||||
message += " (unexpected " + statusCode + " error)";
|
message += " (unexpected " + statusCode + " error)";
|
||||||
}
|
}
|
||||||
throw new ReportableException(message);
|
throw new ReportableException(message);
|
||||||
@ -222,7 +227,7 @@ class InitializrService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getContent(HttpEntity entity) throws IOException {
|
private String getContent(HttpEntity entity) throws IOException {
|
||||||
ContentType contentType = ContentType.getOrDefault(entity);
|
ContentType contentType = ContentType.create(entity.getContentType());
|
||||||
Charset charset = contentType.getCharset();
|
Charset charset = contentType.getCharset();
|
||||||
charset = (charset != null) ? charset : StandardCharsets.UTF_8;
|
charset = (charset != null) ? charset : StandardCharsets.UTF_8;
|
||||||
byte[] content = FileCopyUtils.copyToByteArray(entity.getContent());
|
byte[] content = FileCopyUtils.copyToByteArray(entity.getContent());
|
||||||
|
@ -23,7 +23,7 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.http.client.utils.URIBuilder;
|
import org.apache.hc.core5.net.URIBuilder;
|
||||||
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package org.springframework.boot.cli.command.init;
|
package org.springframework.boot.cli.command.init;
|
||||||
|
|
||||||
import org.apache.http.entity.ContentType;
|
import org.apache.hc.core5.http.ContentType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represent the response of a {@link ProjectGenerationRequest}.
|
* Represent the response of a {@link ProjectGenerationRequest}.
|
||||||
|
@ -19,14 +19,14 @@ package org.springframework.boot.cli.command.init;
|
|||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.http.Header;
|
import org.apache.hc.client5.http.classic.HttpClient;
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
||||||
import org.apache.http.HttpHeaders;
|
import org.apache.hc.core5.http.ClassicHttpResponse;
|
||||||
import org.apache.http.StatusLine;
|
import org.apache.hc.core5.http.Header;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.hc.core5.http.HttpEntity;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.hc.core5.http.HttpHeaders;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.hc.core5.http.HttpHost;
|
||||||
import org.apache.http.message.BasicHeader;
|
import org.apache.hc.core5.http.message.BasicHeader;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.mockito.ArgumentMatcher;
|
import org.mockito.ArgumentMatcher;
|
||||||
@ -35,19 +35,20 @@ import org.springframework.core.io.ClassPathResource;
|
|||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.util.StreamUtils;
|
import org.springframework.util.StreamUtils;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.argThat;
|
import static org.mockito.ArgumentMatchers.argThat;
|
||||||
import static org.mockito.ArgumentMatchers.isA;
|
import static org.mockito.ArgumentMatchers.isA;
|
||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for tests that use a mock {@link CloseableHttpClient}.
|
* Abstract base class for tests that use a mock {@link HttpClient}.
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractHttpClientMockTests {
|
public abstract class AbstractHttpClientMockTests {
|
||||||
|
|
||||||
protected final CloseableHttpClient http = mock(CloseableHttpClient.class);
|
protected final HttpClient http = mock(HttpClient.class);
|
||||||
|
|
||||||
protected void mockSuccessfulMetadataTextGet() throws IOException {
|
protected void mockSuccessfulMetadataTextGet() throws IOException {
|
||||||
mockSuccessfulMetadataGet("metadata/service-metadata-2.1.0.txt", "text/plain", true);
|
mockSuccessfulMetadataGet("metadata/service-metadata-2.1.0.txt", "text/plain", true);
|
||||||
@ -65,11 +66,12 @@ public abstract class AbstractHttpClientMockTests {
|
|||||||
|
|
||||||
protected void mockSuccessfulMetadataGet(String contentPath, String contentType, boolean serviceCapabilities)
|
protected void mockSuccessfulMetadataGet(String contentPath, String contentType, boolean serviceCapabilities)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
CloseableHttpResponse response = mock(CloseableHttpResponse.class);
|
ClassicHttpResponse response = mock(ClassicHttpResponse.class);
|
||||||
byte[] content = readClasspathResource(contentPath);
|
byte[] content = readClasspathResource(contentPath);
|
||||||
mockHttpEntity(response, content, contentType);
|
mockHttpEntity(response, content, contentType);
|
||||||
mockStatus(response, 200);
|
mockStatus(response, 200);
|
||||||
given(this.http.execute(argThat(getForMetadata(serviceCapabilities)))).willReturn(response);
|
given(this.http.execute(any(HttpHost.class), argThat(getForMetadata(serviceCapabilities))))
|
||||||
|
.willReturn(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte[] readClasspathResource(String contentPath) throws IOException {
|
protected byte[] readClasspathResource(String contentPath) throws IOException {
|
||||||
@ -80,36 +82,37 @@ public abstract class AbstractHttpClientMockTests {
|
|||||||
protected void mockSuccessfulProjectGeneration(MockHttpProjectGenerationRequest request) throws IOException {
|
protected void mockSuccessfulProjectGeneration(MockHttpProjectGenerationRequest request) throws IOException {
|
||||||
// Required for project generation as the metadata is read first
|
// Required for project generation as the metadata is read first
|
||||||
mockSuccessfulMetadataGet(false);
|
mockSuccessfulMetadataGet(false);
|
||||||
CloseableHttpResponse response = mock(CloseableHttpResponse.class);
|
ClassicHttpResponse response = mock(ClassicHttpResponse.class);
|
||||||
mockHttpEntity(response, request.content, request.contentType);
|
mockHttpEntity(response, request.content, request.contentType);
|
||||||
mockStatus(response, 200);
|
mockStatus(response, 200);
|
||||||
String header = (request.fileName != null) ? contentDispositionValue(request.fileName) : null;
|
String header = (request.fileName != null) ? contentDispositionValue(request.fileName) : null;
|
||||||
mockHttpHeader(response, "Content-Disposition", header);
|
mockHttpHeader(response, "Content-Disposition", header);
|
||||||
given(this.http.execute(argThat(getForNonMetadata()))).willReturn(response);
|
given(this.http.execute(any(HttpHost.class), argThat(getForNonMetadata()))).willReturn(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void mockProjectGenerationError(int status, String message) throws IOException, JSONException {
|
protected void mockProjectGenerationError(int status, String message) throws IOException, JSONException {
|
||||||
// Required for project generation as the metadata is read first
|
// Required for project generation as the metadata is read first
|
||||||
mockSuccessfulMetadataGet(false);
|
mockSuccessfulMetadataGet(false);
|
||||||
CloseableHttpResponse response = mock(CloseableHttpResponse.class);
|
ClassicHttpResponse response = mock(ClassicHttpResponse.class);
|
||||||
mockHttpEntity(response, createJsonError(status, message).getBytes(), "application/json");
|
mockHttpEntity(response, createJsonError(status, message).getBytes(), "application/json");
|
||||||
mockStatus(response, status);
|
mockStatus(response, status);
|
||||||
given(this.http.execute(isA(HttpGet.class))).willReturn(response);
|
given(this.http.execute(any(HttpHost.class), isA(HttpGet.class))).willReturn(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void mockMetadataGetError(int status, String message) throws IOException, JSONException {
|
protected void mockMetadataGetError(int status, String message) throws IOException, JSONException {
|
||||||
CloseableHttpResponse response = mock(CloseableHttpResponse.class);
|
ClassicHttpResponse response = mock(ClassicHttpResponse.class);
|
||||||
mockHttpEntity(response, createJsonError(status, message).getBytes(), "application/json");
|
mockHttpEntity(response, createJsonError(status, message).getBytes(), "application/json");
|
||||||
mockStatus(response, status);
|
mockStatus(response, status);
|
||||||
given(this.http.execute(isA(HttpGet.class))).willReturn(response);
|
given(this.http.execute(any(HttpHost.class), isA(HttpGet.class))).willReturn(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected HttpEntity mockHttpEntity(CloseableHttpResponse response, byte[] content, String contentType) {
|
protected HttpEntity mockHttpEntity(ClassicHttpResponse response, byte[] content, String contentType) {
|
||||||
try {
|
try {
|
||||||
HttpEntity entity = mock(HttpEntity.class);
|
HttpEntity entity = mock(HttpEntity.class);
|
||||||
given(entity.getContent()).willReturn(new ByteArrayInputStream(content));
|
given(entity.getContent()).willReturn(new ByteArrayInputStream(content));
|
||||||
Header contentTypeHeader = (contentType != null) ? new BasicHeader("Content-Type", contentType) : null;
|
Header contentTypeHeader = (contentType != null) ? new BasicHeader("Content-Type", contentType) : null;
|
||||||
given(entity.getContentType()).willReturn(contentTypeHeader);
|
given(entity.getContentType())
|
||||||
|
.willReturn((contentTypeHeader != null) ? contentTypeHeader.getValue() : null);
|
||||||
given(response.getEntity()).willReturn(entity);
|
given(response.getEntity()).willReturn(entity);
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
@ -118,13 +121,11 @@ public abstract class AbstractHttpClientMockTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void mockStatus(CloseableHttpResponse response, int status) {
|
protected void mockStatus(ClassicHttpResponse response, int status) {
|
||||||
StatusLine statusLine = mock(StatusLine.class);
|
given(response.getCode()).willReturn(status);
|
||||||
given(statusLine.getStatusCode()).willReturn(status);
|
|
||||||
given(response.getStatusLine()).willReturn(statusLine);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void mockHttpHeader(CloseableHttpResponse response, String headerName, String value) {
|
protected void mockHttpHeader(ClassicHttpResponse response, String headerName, String value) {
|
||||||
Header header = (value != null) ? new BasicHeader(headerName, value) : null;
|
Header header = (value != null) ? new BasicHeader(headerName, value) : null;
|
||||||
given(response.getFirstHeader(headerName)).willReturn(header);
|
given(response.getFirstHeader(headerName)).willReturn(header);
|
||||||
}
|
}
|
||||||
@ -166,7 +167,7 @@ public abstract class AbstractHttpClientMockTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MockHttpProjectGenerationRequest(String contentType, String fileName, byte[] content) {
|
MockHttpProjectGenerationRequest(String contentType, String fileName, byte[] content) {
|
||||||
this.contentType = contentType;
|
this.contentType = (contentType != null) ? contentType : "application/text";
|
||||||
this.fileName = fileName;
|
this.fileName = fileName;
|
||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,9 @@ import java.util.zip.ZipEntry;
|
|||||||
import java.util.zip.ZipOutputStream;
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
import joptsimple.OptionSet;
|
import joptsimple.OptionSet;
|
||||||
import org.apache.http.Header;
|
import org.apache.hc.client5.http.classic.methods.HttpUriRequest;
|
||||||
import org.apache.http.client.methods.HttpUriRequest;
|
import org.apache.hc.core5.http.Header;
|
||||||
|
import org.apache.hc.core5.http.HttpHost;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
@ -37,6 +38,8 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
|||||||
import org.springframework.boot.cli.command.status.ExitStatus;
|
import org.springframework.boot.cli.command.status.ExitStatus;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.BDDMockito.then;
|
import static org.mockito.BDDMockito.then;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -205,6 +208,9 @@ class InitCommandTests extends AbstractHttpClientMockTests {
|
|||||||
assertThat(this.command.run("--extract", tempDir.getAbsolutePath())).isEqualTo(ExitStatus.OK);
|
assertThat(this.command.run("--extract", tempDir.getAbsolutePath())).isEqualTo(ExitStatus.OK);
|
||||||
assertThat(file).as("file should have been saved instead").exists();
|
assertThat(file).as("file should have been saved instead").exists();
|
||||||
}
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
fail(ex);
|
||||||
|
}
|
||||||
finally {
|
finally {
|
||||||
assertThat(file.delete()).as("failed to delete test file").isTrue();
|
assertThat(file.delete()).as("failed to delete test file").isTrue();
|
||||||
}
|
}
|
||||||
@ -393,7 +399,7 @@ class InitCommandTests extends AbstractHttpClientMockTests {
|
|||||||
@Test
|
@Test
|
||||||
void userAgent() throws Exception {
|
void userAgent() throws Exception {
|
||||||
this.command.run("--list", "--target=https://fake-service");
|
this.command.run("--list", "--target=https://fake-service");
|
||||||
then(this.http).should().execute(this.requestCaptor.capture());
|
then(this.http).should().execute(any(HttpHost.class), this.requestCaptor.capture());
|
||||||
Header agent = this.requestCaptor.getValue().getHeaders("User-Agent")[0];
|
Header agent = this.requestCaptor.getValue().getHeaders("User-Agent")[0];
|
||||||
assertThat(agent.getValue()).startsWith("SpringBootCli/");
|
assertThat(agent.getValue()).startsWith("SpringBootCli/");
|
||||||
}
|
}
|
||||||
|
@ -16,12 +16,14 @@
|
|||||||
|
|
||||||
package org.springframework.boot.cli.command.init;
|
package org.springframework.boot.cli.command.init;
|
||||||
|
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.hc.core5.http.ClassicHttpResponse;
|
||||||
|
import org.apache.hc.core5.http.HttpHost;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.isA;
|
import static org.mockito.ArgumentMatchers.isA;
|
||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
@ -91,9 +93,9 @@ class InitializrServiceTests extends AbstractHttpClientMockTests {
|
|||||||
@Test
|
@Test
|
||||||
void generateProjectNoContent() throws Exception {
|
void generateProjectNoContent() throws Exception {
|
||||||
mockSuccessfulMetadataGet(false);
|
mockSuccessfulMetadataGet(false);
|
||||||
CloseableHttpResponse response = mock(CloseableHttpResponse.class);
|
ClassicHttpResponse response = mock(ClassicHttpResponse.class);
|
||||||
mockStatus(response, 500);
|
mockStatus(response, 500);
|
||||||
given(this.http.execute(isA(HttpGet.class))).willReturn(response);
|
given(this.http.execute(any(HttpHost.class), isA(HttpGet.class))).willReturn(response);
|
||||||
ProjectGenerationRequest request = new ProjectGenerationRequest();
|
ProjectGenerationRequest request = new ProjectGenerationRequest();
|
||||||
assertThatExceptionOfType(ReportableException.class).isThrownBy(() -> this.invoker.generate(request))
|
assertThatExceptionOfType(ReportableException.class).isThrownBy(() -> this.invoker.generate(request))
|
||||||
.withMessageContaining("No content received from server");
|
.withMessageContaining("No content received from server");
|
||||||
@ -110,10 +112,10 @@ class InitializrServiceTests extends AbstractHttpClientMockTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void loadMetadataInvalidJson() throws Exception {
|
void loadMetadataInvalidJson() throws Exception {
|
||||||
CloseableHttpResponse response = mock(CloseableHttpResponse.class);
|
ClassicHttpResponse response = mock(ClassicHttpResponse.class);
|
||||||
mockHttpEntity(response, "Foo-Bar-Not-JSON".getBytes(), "application/json");
|
mockHttpEntity(response, "Foo-Bar-Not-JSON".getBytes(), "application/json");
|
||||||
mockStatus(response, 200);
|
mockStatus(response, 200);
|
||||||
given(this.http.execute(isA(HttpGet.class))).willReturn(response);
|
given(this.http.execute(any(HttpHost.class), isA(HttpGet.class))).willReturn(response);
|
||||||
ProjectGenerationRequest request = new ProjectGenerationRequest();
|
ProjectGenerationRequest request = new ProjectGenerationRequest();
|
||||||
assertThatExceptionOfType(ReportableException.class).isThrownBy(() -> this.invoker.generate(request))
|
assertThatExceptionOfType(ReportableException.class).isThrownBy(() -> this.invoker.generate(request))
|
||||||
.withMessageContaining("Invalid content received from server");
|
.withMessageContaining("Invalid content received from server");
|
||||||
@ -121,9 +123,9 @@ class InitializrServiceTests extends AbstractHttpClientMockTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void loadMetadataNoContent() throws Exception {
|
void loadMetadataNoContent() throws Exception {
|
||||||
CloseableHttpResponse response = mock(CloseableHttpResponse.class);
|
ClassicHttpResponse response = mock(ClassicHttpResponse.class);
|
||||||
mockStatus(response, 500);
|
mockStatus(response, 500);
|
||||||
given(this.http.execute(isA(HttpGet.class))).willReturn(response);
|
given(this.http.execute(any(HttpHost.class), isA(HttpGet.class))).willReturn(response);
|
||||||
ProjectGenerationRequest request = new ProjectGenerationRequest();
|
ProjectGenerationRequest request = new ProjectGenerationRequest();
|
||||||
assertThatExceptionOfType(ReportableException.class).isThrownBy(() -> this.invoker.generate(request))
|
assertThatExceptionOfType(ReportableException.class).isThrownBy(() -> this.invoker.generate(request))
|
||||||
.withMessageContaining("No content received from server");
|
.withMessageContaining("No content received from server");
|
||||||
|
@ -128,7 +128,7 @@ class ProjectGenerationRequestTests {
|
|||||||
this.request.setDescription("Spring Boot Test");
|
this.request.setDescription("Spring Boot Test");
|
||||||
assertThat(this.request.generateUrl(createDefaultMetadata()))
|
assertThat(this.request.generateUrl(createDefaultMetadata()))
|
||||||
.isEqualTo(createDefaultUrl("?groupId=org.acme&artifactId=sample&version=1.0.1-SNAPSHOT"
|
.isEqualTo(createDefaultUrl("?groupId=org.acme&artifactId=sample&version=1.0.1-SNAPSHOT"
|
||||||
+ "&description=Spring+Boot+Test&type=test-type"));
|
+ "&description=Spring%20Boot%20Test&type=test-type"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
Reference in New Issue
Block a user