remote address bug

This commit is contained in:
Bill Burke
2019-10-31 15:15:35 -04:00
parent 9ed6438872
commit 086a4be688
17 changed files with 749 additions and 15 deletions

View File

@@ -1,6 +1,7 @@
package io.quarkus.amazon.lambda.http;
import java.io.ByteArrayOutputStream;
import java.net.InetSocketAddress;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
@@ -37,7 +38,14 @@ public class LambdaHttpHandler implements RequestHandler<AwsProxyRequest, AwsPro
}
public AwsProxyResponse handleRequest(AwsProxyRequest request, Context context) {
VirtualClientConnection connection = VirtualClientConnection.connect(VertxHttpRecorder.VIRTUAL_HTTP);
InetSocketAddress clientAddress = null;
if (request.getRequestContext() != null && request.getRequestContext().getIdentity() != null) {
if (request.getRequestContext().getIdentity().getSourceIp() != null) {
clientAddress = new InetSocketAddress(request.getRequestContext().getIdentity().getSourceIp(), 443);
}
}
VirtualClientConnection connection = VirtualClientConnection.connect(VertxHttpRecorder.VIRTUAL_HTTP, clientAddress);
try {
return nettyDispatch(connection, request);
} catch (Exception e) {
@@ -48,9 +56,7 @@ public class LambdaHttpHandler implements RequestHandler<AwsProxyRequest, AwsPro
}
private AwsProxyResponse nettyDispatch(VirtualClientConnection connection,
AwsProxyRequest request)
throws Exception {
private AwsProxyResponse nettyDispatch(VirtualClientConnection connection, AwsProxyRequest request) throws Exception {
String path = request.getPath();
if (request.getMultiValueQueryStringParameters() != null && !request.getMultiValueQueryStringParameters().isEmpty()) {
StringBuilder sb = new StringBuilder(path);

View File

@@ -88,7 +88,7 @@ public class VirtualChannel extends AbstractChannel {
protected volatile State state;
protected volatile VirtualAddress localAddress;
protected volatile VirtualAddress remoteAddress;
protected volatile SocketAddress remoteAddress;
protected volatile ChannelPromise connectPromise;
protected volatile boolean readInProgress;
protected volatile boolean writeInProgress;
@@ -123,8 +123,8 @@ public class VirtualChannel extends AbstractChannel {
}
@Override
public VirtualAddress remoteAddress() {
return (VirtualAddress) super.remoteAddress();
public SocketAddress remoteAddress() {
return remoteAddress;
}
@Override

View File

@@ -1,5 +1,6 @@
package io.quarkus.netty.runtime.virtual;
import java.net.SocketAddress;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
@@ -14,17 +15,17 @@ import io.netty.util.internal.PlatformDependent;
*
*/
public class VirtualClientConnection {
protected VirtualAddress address;
protected SocketAddress clientAddress;
protected BlockingQueue<Object> queue = new LinkedBlockingQueue<>();
protected boolean connected = true;
protected VirtualChannel peer;
VirtualClientConnection(VirtualAddress address) {
this.address = address;
VirtualClientConnection(SocketAddress clientAddress) {
this.clientAddress = clientAddress;
}
public VirtualAddress clientAddress() {
return address;
public SocketAddress clientAddress() {
return clientAddress;
}
/**
@@ -104,6 +105,21 @@ public class VirtualClientConnection {
* @return
*/
public static VirtualClientConnection connect(final VirtualAddress remoteAddress) {
return connect(remoteAddress, remoteAddress);
}
/**
* Establish a virtual intra-JVM connection
*
* @param remoteAddress
* @param clientAddress
* @return
*/
public static VirtualClientConnection connect(VirtualAddress remoteAddress, SocketAddress clientAddress) {
if (clientAddress == null)
clientAddress = remoteAddress;
Channel boundChannel = VirtualChannelRegistry.get(remoteAddress);
if (boundChannel == null) {
throw new RuntimeException("No virtual channel available");
@@ -113,9 +129,8 @@ public class VirtualClientConnection {
}
VirtualServerChannel serverChannel = (VirtualServerChannel) boundChannel;
VirtualClientConnection conn = new VirtualClientConnection(remoteAddress);
VirtualClientConnection conn = new VirtualClientConnection(clientAddress);
conn.peer = serverChannel.serve(conn);
return conn;
}
}

View File

@@ -24,6 +24,7 @@ import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.net.SocketAddress;
import io.vertx.ext.web.RoutingContext;
/**
@@ -95,8 +96,12 @@ public class VertxRequestHandler implements Handler<RoutingContext> {
HttpServerResponse response = request.response();
VertxHttpResponse vertxResponse = new VertxHttpResponse(request, dispatcher.getProviderFactory(),
request.method(), allocator, output);
// client address may not be available with VirtualHttp
SocketAddress socketAddress = request.remoteAddress();
String host = socketAddress != null ? socketAddress.host() : null;
VertxHttpRequest vertxRequest = new VertxHttpRequest(ctx, headers, uriInfo, request.rawMethod(),
request.remoteAddress().host(), dispatcher.getDispatcher(), vertxResponse, false);
host, dispatcher.getDispatcher(), vertxResponse, false);
vertxRequest.setInputStream(is);
try {
ResteasyContext.pushContext(SecurityContext.class, new QuarkusResteasySecurityContext(request));

View File

@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-integration-tests-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>quarkus-integration-test-amazon-lambda-http-resteasy</artifactId>
<name>Quarkus - Integration Tests - Amazon Lambda HTTP Resteasy</name>
<description>Test with Resteasy Standalone and Amazon Lambda HTTP</description>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-amazon-lambda-http</artifactId>
</dependency>
<!-- test dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-amazon-lambda</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>native-image</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<systemProperties>
<native.image.path>
${project.build.directory}/${project.build.finalName}-runner
</native.image.path>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<executions>
<execution>
<id>native-image</id>
<goals>
<goal>native-image</goal>
</goals>
<configuration>
<reportErrorsAtRuntime>false</reportErrorsAtRuntime>
<cleanupServer>true</cleanupServer>
<enableHttpUrlHandler>true</enableHttpUrlHandler>
<graalvmHome>${graalvmHome}</graalvmHome>
<enableJni>false</enableJni>
<debugBuildProcess>false</debugBuildProcess>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@@ -0,0 +1,43 @@
package io.quarkus.it.amazon.lambda;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/hello")
public class GreetingResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "hello";
}
@POST
@Produces(MediaType.TEXT_PLAIN)
@Consumes(MediaType.TEXT_PLAIN)
public String hello(String name) {
return "hello " + name;
}
@POST
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
public byte[] hello(byte[] bytes) {
if (bytes[0] != 0 || bytes[1] != 1 || bytes[2] != 2 || bytes[3] != 3) {
throw new RuntimeException("bad input");
}
byte[] rtn = { 4, 5, 6 };
return rtn;
}
@POST
@Path("empty")
public void empty() {
}
}

View File

@@ -0,0 +1,2 @@
quarkus.lambda.enable-polling-jvm-mode=true
quarkus.http.virtual=true

View File

@@ -0,0 +1,7 @@
package io.quarkus.it.amazon.lambda;
import io.quarkus.test.junit.NativeImageTest;
@NativeImageTest
public class AmazonLambdaSimpleIT extends AmazonLambdaSimpleTestCase {
}

View File

@@ -0,0 +1,99 @@
package io.quarkus.it.amazon.lambda;
import javax.ws.rs.core.MediaType;
import org.apache.commons.codec.binary.Base64;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import io.quarkus.amazon.lambda.http.model.AwsProxyRequest;
import io.quarkus.amazon.lambda.http.model.AwsProxyResponse;
import io.quarkus.amazon.lambda.http.model.Headers;
import io.quarkus.amazon.lambda.test.LambdaClient;
import io.quarkus.test.junit.QuarkusTest;
@QuarkusTest
public class AmazonLambdaSimpleTestCase {
@Test
public void testGetText() throws Exception {
testGetText("/hello");
}
private String body(AwsProxyResponse response) {
if (!response.isBase64Encoded())
return response.getBody();
return new String(Base64.decodeBase64(response.getBody()));
}
private void testGetText(String path) {
AwsProxyRequest request = new AwsProxyRequest();
request.setHttpMethod("GET");
request.setPath(path);
AwsProxyResponse out = LambdaClient.invoke(AwsProxyResponse.class, request);
Assertions.assertEquals(out.getStatusCode(), 200);
Assertions.assertEquals(body(out), "hello");
Assertions.assertTrue(out.getMultiValueHeaders().getFirst("Content-Type").startsWith("text/plain"));
}
@Test
public void test404() throws Exception {
AwsProxyRequest request = new AwsProxyRequest();
request.setHttpMethod("GET");
request.setPath("/nowhere");
AwsProxyResponse out = LambdaClient.invoke(AwsProxyResponse.class, request);
Assertions.assertEquals(out.getStatusCode(), 404);
}
@Test
public void testPostText() throws Exception {
testPostText("/hello");
}
private void testPostText(String path) {
AwsProxyRequest request = new AwsProxyRequest();
request.setHttpMethod("POST");
request.setMultiValueHeaders(new Headers());
request.getMultiValueHeaders().add("Content-Type", "text/plain");
request.setPath(path);
request.setBody("Bill");
AwsProxyResponse out = LambdaClient.invoke(AwsProxyResponse.class, request);
Assertions.assertEquals(out.getStatusCode(), 200);
Assertions.assertEquals(body(out), "hello Bill");
Assertions.assertTrue(out.getMultiValueHeaders().getFirst("Content-Type").startsWith("text/plain"));
}
@Test
public void testPostBinary() throws Exception {
AwsProxyRequest request = new AwsProxyRequest();
byte[] bytes = { 0, 1, 2, 3 };
String body = Base64.encodeBase64String(bytes);
request.setHttpMethod("POST");
request.setMultiValueHeaders(new Headers());
request.getMultiValueHeaders().add("Content-Type", MediaType.APPLICATION_OCTET_STREAM);
request.setPath("/hello");
request.setBody(body);
request.setIsBase64Encoded(true);
AwsProxyResponse out = LambdaClient.invoke(AwsProxyResponse.class, request);
Assertions.assertEquals(out.getStatusCode(), 200);
Assertions.assertEquals(out.getMultiValueHeaders().getFirst("Content-Type"), MediaType.APPLICATION_OCTET_STREAM);
Assertions.assertTrue(out.isBase64Encoded());
byte[] rtn = Base64.decodeBase64(out.getBody());
Assertions.assertEquals(rtn[0], 4);
Assertions.assertEquals(rtn[1], 5);
Assertions.assertEquals(rtn[2], 6);
}
@Test
public void testPostEmpty() throws Exception {
AwsProxyRequest request = new AwsProxyRequest();
request.setHttpMethod("POST");
request.setMultiValueHeaders(new Headers());
request.setPath("/hello/empty");
AwsProxyResponse out = LambdaClient.invoke(AwsProxyResponse.class, request);
Assertions.assertEquals(out.getStatusCode(), 204);
}
}

View File

@@ -61,6 +61,7 @@
<module>test-extension</module>
<module>amazon-lambda</module>
<module>amazon-lambda-http-it</module>
<module>amazon-lambda-http-resteasy</module>
<module>kogito</module>
<module>kogito-maven</module>
<module>kubernetes</module>
@@ -73,6 +74,7 @@
<module>resteasy-jackson</module>
<module>jgit</module>
<module>virtual-http</module>
<module>virtual-http-resteasy</module>
<module>artemis-core</module>
<module>artemis-jms</module>
<module>maven</module>

View File

@@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>quarkus-integration-tests-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<artifactId>quarkus-integration-test-virtual-http-resteasy</artifactId>
<name>Quarkus - Integration Tests - Virtual Http Resteasy Standalone</name>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-azure-functions-http</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.azure.functions</groupId>
<artifactId>azure-functions-java-library</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${project.version}</version>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>native-image</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<systemProperties>
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${project.version}</version>
<executions>
<execution>
<id>native-image</id>
<goals>
<goal>native-image</goal>
</goals>
<configuration>
<cleanupServer>true</cleanupServer>
<enableHttpUrlHandler>true</enableHttpUrlHandler>
<graalvmHome>${graalvmHome}</graalvmHome>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@@ -0,0 +1,25 @@
package io.quarkus.it.virtual;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/hello")
public class GreetingResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "hello";
}
@POST
@Produces(MediaType.TEXT_PLAIN)
@Consumes(MediaType.TEXT_PLAIN)
public String hello(String name) {
return "hello " + name;
}
}

View File

@@ -0,0 +1 @@
quarkus.http.virtual=true

View File

@@ -0,0 +1,140 @@
package io.quarkus.it.virtual;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.logging.Logger;
import javax.ws.rs.core.MediaType;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.HttpMethod;
import com.microsoft.azure.functions.HttpResponseMessage;
import com.microsoft.azure.functions.HttpStatus;
import io.quarkus.azure.functions.resteasy.runtime.Function;
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.RestAssured;
/**
* Unit test for Function class.
*/
@QuarkusTest
public class FunctionTest {
@Test
public void testJaxrs() throws Exception {
String uri = "https://foo.com/hello";
testGET(uri);
testPOST(uri);
}
@Test
public void testNotFound() {
final HttpRequestMessageMock req = new HttpRequestMessageMock();
req.setUri(URI.create("https://nowhere.com/badroute"));
req.setHttpMethod(HttpMethod.GET);
// Invoke
final HttpResponseMessage ret = new Function().run(req, new ExecutionContext() {
@Override
public Logger getLogger() {
return null;
}
@Override
public String getInvocationId() {
return null;
}
@Override
public String getFunctionName() {
return null;
}
});
// Verify
Assertions.assertEquals(ret.getStatus(), HttpStatus.NOT_FOUND);
}
@Test
public void testHttp() {
// assure that socket is created in dev/test mode
RestAssured.when().get("/hello").then()
.contentType("text/plain")
.body(equalTo("hello"));
RestAssured.given().contentType("text/plain").body("Bill").post("/hello").then()
.contentType("text/plain")
.body(containsString("hello Bill"));
}
private void testGET(String uri) {
final HttpRequestMessageMock req = new HttpRequestMessageMock();
req.setUri(URI.create(uri));
req.setHttpMethod(HttpMethod.GET);
// Invoke
final HttpResponseMessage ret = new Function().run(req, new ExecutionContext() {
@Override
public Logger getLogger() {
return null;
}
@Override
public String getInvocationId() {
return null;
}
@Override
public String getFunctionName() {
return null;
}
});
// Verify
Assertions.assertEquals(ret.getStatus(), HttpStatus.OK);
Assertions.assertEquals("hello", new String((byte[]) ret.getBody(), StandardCharsets.UTF_8));
String contentType = ret.getHeader("Content-Type");
Assertions.assertNotNull(contentType);
Assertions.assertTrue(MediaType.valueOf(contentType).isCompatible(MediaType.TEXT_PLAIN_TYPE));
}
private void testPOST(String uri) {
final HttpRequestMessageMock req = new HttpRequestMessageMock();
req.setUri(URI.create(uri));
req.setHttpMethod(HttpMethod.POST);
req.setBody("Bill".getBytes());
req.getHeaders().put("Content-Type", "text/plain");
// Invoke
final HttpResponseMessage ret = new Function().run(req, new ExecutionContext() {
@Override
public Logger getLogger() {
return null;
}
@Override
public String getInvocationId() {
return null;
}
@Override
public String getFunctionName() {
return null;
}
});
// Verify
Assertions.assertEquals(ret.getStatus(), HttpStatus.OK);
Assertions.assertEquals("hello Bill", new String((byte[]) ret.getBody(), StandardCharsets.UTF_8));
String contentType = ret.getHeader("Content-Type");
Assertions.assertNotNull(contentType);
Assertions.assertTrue(MediaType.valueOf(contentType).isCompatible(MediaType.TEXT_PLAIN_TYPE));
}
}

View File

@@ -0,0 +1,75 @@
package io.quarkus.it.virtual;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import com.microsoft.azure.functions.HttpMethod;
import com.microsoft.azure.functions.HttpRequestMessage;
import com.microsoft.azure.functions.HttpResponseMessage;
import com.microsoft.azure.functions.HttpStatus;
import com.microsoft.azure.functions.HttpStatusType;
public class HttpRequestMessageMock implements HttpRequestMessage<Optional<byte[]>> {
protected URI uri;
protected HttpMethod httpMethod;
protected Map<String, String> headers = new HashMap<>();
protected Map<String, String> queryParameters = new HashMap<>();
protected byte[] body;
@Override
public URI getUri() {
return uri;
}
@Override
public HttpMethod getHttpMethod() {
return httpMethod;
}
@Override
public Map<String, String> getHeaders() {
return headers;
}
@Override
public Map<String, String> getQueryParameters() {
return queryParameters;
}
@Override
public Optional<byte[]> getBody() {
return Optional.ofNullable(body);
}
@Override
public HttpResponseMessage.Builder createResponseBuilder(HttpStatus httpStatus) {
return new HttpResponseMessageMock.HttpResponseMessageBuilderMock().status(httpStatus);
}
@Override
public HttpResponseMessage.Builder createResponseBuilder(HttpStatusType httpStatusType) {
return new HttpResponseMessageMock.HttpResponseMessageBuilderMock().status(httpStatusType);
}
public void setUri(URI uri) {
this.uri = uri;
}
public void setHttpMethod(HttpMethod httpMethod) {
this.httpMethod = httpMethod;
}
public void setHeaders(Map<String, String> headers) {
this.headers = headers;
}
public void setQueryParameters(Map<String, String> queryParameters) {
this.queryParameters = queryParameters;
}
public void setBody(byte[] body) {
this.body = body;
}
}

View File

@@ -0,0 +1,83 @@
package io.quarkus.it.virtual;
import java.util.HashMap;
import java.util.Map;
import com.microsoft.azure.functions.HttpResponseMessage;
import com.microsoft.azure.functions.HttpStatus;
import com.microsoft.azure.functions.HttpStatusType;
/**
* The mock for HttpResponseMessage, can be used in unit tests to verify if the
* returned response by HTTP trigger function is correct or not.
*/
public class HttpResponseMessageMock implements HttpResponseMessage {
private int httpStatusCode;
private HttpStatusType httpStatus;
private Object body;
private Map<String, String> headers;
public HttpResponseMessageMock(final HttpStatusType status, final Map<String, String> headers, final Object body) {
this.httpStatus = status;
this.httpStatusCode = status.value();
this.headers = headers;
this.body = body;
}
@Override
public HttpStatusType getStatus() {
return this.httpStatus;
}
@Override
public int getStatusCode() {
return httpStatusCode;
}
@Override
public String getHeader(String key) {
return this.headers.get(key);
}
@Override
public Object getBody() {
return this.body;
}
public static class HttpResponseMessageBuilderMock implements HttpResponseMessage.Builder {
private Object body;
private int httpStatusCode;
private Map<String, String> headers = new HashMap<>();
private HttpStatusType httpStatus;
public Builder status(HttpStatus status) {
this.httpStatusCode = status.value();
this.httpStatus = status;
return this;
}
@Override
public Builder status(final HttpStatusType httpStatusType) {
this.httpStatusCode = httpStatusType.value();
this.httpStatus = httpStatusType;
return this;
}
@Override
public HttpResponseMessage.Builder header(final String key, final String value) {
this.headers.put(key, value);
return this;
}
@Override
public HttpResponseMessage.Builder body(final Object body) {
this.body = body;
return this;
}
@Override
public HttpResponseMessage build() {
return new HttpResponseMessageMock(this.httpStatus, this.headers, this.body);
}
}
}