Adds a RibbonRequestCustomizer.
This allows developers to customize the request builders for zuul requests to inject headers or modify the request in general. Each zuul request type (RestClient, Apache HttpClient and OkHttp) is supported. fixes gh-1141
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.netflix.ribbon.apache;
|
||||
|
||||
import static org.springframework.cloud.netflix.ribbon.support.RibbonRequestCustomizer.Runner.customize;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
@@ -69,6 +71,8 @@ public class RibbonApacheHttpRequest extends ContextAwareRequest implements Clon
|
||||
builder.setEntity(entity);
|
||||
}
|
||||
|
||||
customize(this.context.getRequestCustomizers(), builder);
|
||||
|
||||
builder.setConfig(requestConfig);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.netflix.ribbon.okhttp;
|
||||
|
||||
import static org.springframework.cloud.netflix.ribbon.support.RibbonRequestCustomizer.Runner.customize;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
@@ -72,11 +74,14 @@ public class OkHttpRibbonRequest extends ContextAwareRequest implements Cloneabl
|
||||
requestBody = new InputStreamRequestBody(this.context.getRequestEntity(), mediaType, this.context.getContentLength());
|
||||
}
|
||||
|
||||
return new Request.Builder()
|
||||
Request.Builder builder = new Request.Builder()
|
||||
.url(url.build())
|
||||
.headers(headers.build())
|
||||
.method(this.context.getMethod(), requestBody)
|
||||
.build();
|
||||
.method(this.context.getMethod(), requestBody);
|
||||
|
||||
customize(this.context.getRequestCustomizers(), builder);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public OkHttpRibbonRequest withNewUri(final URI uri) {
|
||||
|
||||
@@ -41,8 +41,8 @@ public abstract class ContextAwareRequest extends ClientRequest {
|
||||
protected RibbonCommandContext newContext(URI uri) {
|
||||
RibbonCommandContext commandContext = new RibbonCommandContext(this.context.getServiceId(),
|
||||
this.context.getMethod(), uri.toString(), this.context.getRetryable(),
|
||||
this.context.getHeaders(), this.context.getParams(), this.context.getRequestEntity());
|
||||
commandContext.setContentLength(this.context.getContentLength());
|
||||
this.context.getHeaders(), this.context.getParams(), this.context.getRequestEntity(),
|
||||
this.context.getRequestCustomizers(), this.context.getContentLength());
|
||||
return commandContext;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.netflix.ribbon.support;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public interface RibbonRequestCustomizer<B> {
|
||||
boolean accepts(Class builderClass);
|
||||
void customize(B builder);
|
||||
|
||||
class Runner {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void customize(List<RibbonRequestCustomizer> customizers, Object builder) {
|
||||
for (RibbonRequestCustomizer customizer : customizers) {
|
||||
if (customizer.accepts(builder.getClass())) {
|
||||
customizer.customize(builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.cloud.netflix.zuul;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.trace.TraceRepository;
|
||||
@@ -30,6 +33,7 @@ import org.springframework.cloud.client.discovery.event.HeartbeatMonitor;
|
||||
import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent;
|
||||
import org.springframework.cloud.client.discovery.event.ParentHeartbeatEvent;
|
||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
||||
import org.springframework.cloud.netflix.ribbon.support.RibbonRequestCustomizer;
|
||||
import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper;
|
||||
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
|
||||
import org.springframework.cloud.netflix.zuul.filters.TraceProxyRequestHelper;
|
||||
@@ -38,12 +42,12 @@ import org.springframework.cloud.netflix.zuul.filters.discovery.DiscoveryClientR
|
||||
import org.springframework.cloud.netflix.zuul.filters.discovery.ServiceRouteMapper;
|
||||
import org.springframework.cloud.netflix.zuul.filters.discovery.SimpleServiceRouteMapper;
|
||||
import org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter;
|
||||
import org.springframework.cloud.netflix.zuul.filters.route.okhttp.OkHttpRibbonCommandFactory;
|
||||
import org.springframework.cloud.netflix.zuul.filters.route.RestClientRibbonCommandFactory;
|
||||
import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory;
|
||||
import org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter;
|
||||
import org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter;
|
||||
import org.springframework.cloud.netflix.zuul.filters.route.apache.HttpClientRibbonCommandFactory;
|
||||
import org.springframework.cloud.netflix.zuul.filters.route.okhttp.OkHttpRibbonCommandFactory;
|
||||
import org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
@@ -57,6 +61,9 @@ import org.springframework.context.annotation.Configuration;
|
||||
@Configuration
|
||||
public class ZuulProxyConfiguration extends ZuulConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<RibbonRequestCustomizer> requestCustomizers = Collections.emptyList();
|
||||
|
||||
@Autowired
|
||||
private DiscoveryClient discovery;
|
||||
|
||||
@@ -122,7 +129,7 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
|
||||
public RibbonRoutingFilter ribbonRoutingFilter(ProxyRequestHelper helper,
|
||||
RibbonCommandFactory<?> ribbonCommandFactory) {
|
||||
RibbonRoutingFilter filter = new RibbonRoutingFilter(helper,
|
||||
ribbonCommandFactory);
|
||||
ribbonCommandFactory, this.requestCustomizers);
|
||||
return filter;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,16 +17,19 @@
|
||||
|
||||
package org.springframework.cloud.netflix.zuul.filters.route;
|
||||
|
||||
import com.netflix.client.http.HttpRequest;
|
||||
import com.netflix.client.http.HttpResponse;
|
||||
import com.netflix.niws.client.http.RestClient;
|
||||
import org.springframework.cloud.netflix.zuul.filters.route.support.AbstractRibbonCommand;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import static org.springframework.cloud.netflix.ribbon.support.RibbonRequestCustomizer.Runner.customize;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.cloud.netflix.zuul.filters.route.support.AbstractRibbonCommand;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import com.netflix.client.http.HttpRequest;
|
||||
import com.netflix.client.http.HttpResponse;
|
||||
import com.netflix.niws.client.http.RestClient;
|
||||
|
||||
/**
|
||||
* Hystrix wrapper around Eureka Ribbon command
|
||||
*
|
||||
@@ -79,7 +82,7 @@ public class RestClientRibbonCommand extends AbstractRibbonCommand<RestClient, H
|
||||
}
|
||||
|
||||
protected void customizeRequest(HttpRequest.Builder requestBuilder) {
|
||||
// noop
|
||||
customize(this.context.getRequestCustomizers(), requestBuilder);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
|
||||
@@ -19,26 +19,48 @@ package org.springframework.cloud.netflix.zuul.filters.route;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.cloud.netflix.ribbon.support.RibbonRequestCustomizer;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Data
|
||||
@RequiredArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class RibbonCommandContext {
|
||||
@NonNull
|
||||
private final String serviceId;
|
||||
@NonNull
|
||||
private final String method;
|
||||
@NonNull
|
||||
private final String uri;
|
||||
private final Boolean retryable;
|
||||
@NonNull
|
||||
private final MultiValueMap<String, String> headers;
|
||||
@NonNull
|
||||
private final MultiValueMap<String, String> params;
|
||||
private final InputStream requestEntity;
|
||||
@NonNull
|
||||
private final List<RibbonRequestCustomizer> requestCustomizers;
|
||||
private Long contentLength;
|
||||
|
||||
public RibbonCommandContext(String serviceId, String method, String uri, Boolean retryable,
|
||||
MultiValueMap<String, String> headers, MultiValueMap<String, String> params,
|
||||
InputStream requestEntity) {
|
||||
this(serviceId, method, uri, retryable, headers, params, requestEntity,
|
||||
new ArrayList<RibbonRequestCustomizer>(), null);
|
||||
}
|
||||
|
||||
public URI uri() {
|
||||
try {
|
||||
return new URI(this.uri);
|
||||
|
||||
@@ -18,11 +18,13 @@ package org.springframework.cloud.netflix.zuul.filters.route;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.cloud.netflix.ribbon.support.RibbonRequestCustomizer;
|
||||
import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
@@ -42,15 +44,18 @@ public class RibbonRoutingFilter extends ZuulFilter {
|
||||
private static final String ERROR_STATUS_CODE = "error.status_code";
|
||||
protected ProxyRequestHelper helper;
|
||||
protected RibbonCommandFactory<?> ribbonCommandFactory;
|
||||
protected List<RibbonRequestCustomizer> requestCustomizers;
|
||||
|
||||
public RibbonRoutingFilter(ProxyRequestHelper helper,
|
||||
RibbonCommandFactory<?> ribbonCommandFactory) {
|
||||
RibbonCommandFactory<?> ribbonCommandFactory,
|
||||
List<RibbonRequestCustomizer> requestCustomizers) {
|
||||
this.helper = helper;
|
||||
this.ribbonCommandFactory = ribbonCommandFactory;
|
||||
this.requestCustomizers = requestCustomizers;
|
||||
}
|
||||
|
||||
public RibbonRoutingFilter(RibbonCommandFactory<?> ribbonCommandFactory) {
|
||||
this(new ProxyRequestHelper(), ribbonCommandFactory);
|
||||
this(new ProxyRequestHelper(), ribbonCommandFactory, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -115,7 +120,7 @@ public class RibbonRoutingFilter extends ZuulFilter {
|
||||
uri = uri.replace("//", "/");
|
||||
|
||||
return new RibbonCommandContext(serviceId, verb, uri, retryable, headers, params,
|
||||
requestEntity);
|
||||
requestEntity, this.requestCustomizers);
|
||||
}
|
||||
|
||||
protected ClientHttpResponse forward(RibbonCommandContext context) throws Exception {
|
||||
|
||||
@@ -29,12 +29,15 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpEntityEnclosingRequest;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.client.methods.RequestBuilder;
|
||||
import org.junit.Test;
|
||||
import org.springframework.cloud.netflix.ribbon.support.RibbonRequestCustomizer;
|
||||
import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandContext;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.StreamUtils;
|
||||
@@ -85,7 +88,21 @@ public class RibbonApacheHttpRequestTests {
|
||||
headers.add("Content-Length", lengthString);
|
||||
length = (long) entityValue.length();
|
||||
}
|
||||
RibbonCommandContext context = new RibbonCommandContext("example", method, uri.toString(), false, headers, new LinkedMultiValueMap<String, String>(), requestEntity);
|
||||
|
||||
RibbonRequestCustomizer requestCustomizer = new RibbonRequestCustomizer<RequestBuilder>() {
|
||||
@Override
|
||||
public boolean accepts(Class builderClass) {
|
||||
return builderClass == RequestBuilder.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(RequestBuilder builder) {
|
||||
builder.addHeader("from-customizer", "foo");
|
||||
}
|
||||
};
|
||||
RibbonCommandContext context = new RibbonCommandContext("example", method,
|
||||
uri.toString(), false, headers, new LinkedMultiValueMap<String, String>(),
|
||||
requestEntity, Collections.singletonList(requestCustomizer));
|
||||
context.setContentLength(length);
|
||||
RibbonApacheHttpRequest httpRequest = new RibbonApacheHttpRequest(context);
|
||||
|
||||
@@ -98,6 +115,9 @@ public class RibbonApacheHttpRequestTests {
|
||||
assertThat("Content-Length is wrong", request.getFirstHeader("Content-Length").getValue(),
|
||||
is(equalTo(lengthString)));
|
||||
}
|
||||
assertThat("from-customizer is missing", request.getFirstHeader("from-customizer"), is(notNullValue()));
|
||||
assertThat("from-customizer is wrong", request.getFirstHeader("from-customizer").getValue(),
|
||||
is(equalTo("foo")));
|
||||
|
||||
HttpEntityEnclosingRequest entityRequest = (HttpEntityEnclosingRequest) request;
|
||||
assertThat("entity is missing", entityRequest.getEntity(), is(notNullValue()));
|
||||
@@ -108,3 +128,4 @@ public class RibbonApacheHttpRequestTests {
|
||||
assertThat("content is wrong", string, is(equalTo(entityValue)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,10 @@ import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.cloud.netflix.ribbon.support.RibbonRequestCustomizer;
|
||||
import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandContext;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
|
||||
@@ -80,8 +82,20 @@ public class OkHttpRibbonRequestTests {
|
||||
headers.add("Content-Length", lengthString);
|
||||
length = (long) entityValue.length();
|
||||
}
|
||||
|
||||
RibbonRequestCustomizer requestCustomizer = new RibbonRequestCustomizer<Request.Builder>() {
|
||||
@Override
|
||||
public boolean accepts(Class builderClass) {
|
||||
return builderClass == Request.Builder.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(Request.Builder builder) {
|
||||
builder.addHeader("from-customizer", "foo");
|
||||
}
|
||||
};
|
||||
RibbonCommandContext context = new RibbonCommandContext("example", method, uri, false,
|
||||
headers, new LinkedMultiValueMap<String, String>(), requestEntity);
|
||||
headers, new LinkedMultiValueMap<String, String>(), requestEntity, Collections.singletonList(requestCustomizer));
|
||||
context.setContentLength(length);
|
||||
OkHttpRibbonRequest httpRequest = new OkHttpRibbonRequest(context);
|
||||
|
||||
@@ -92,6 +106,8 @@ public class OkHttpRibbonRequestTests {
|
||||
assertThat("Content-Length is wrong", request.header("Content-Length"),
|
||||
is(equalTo(lengthString)));
|
||||
}
|
||||
assertThat("from-customizer is wrong", request.header("from-customizer"),
|
||||
is(equalTo("foo")));
|
||||
|
||||
if (!method.equalsIgnoreCase("get")) {
|
||||
assertThat("body is null", request.body(), is(notNullValue()));
|
||||
@@ -104,3 +120,4 @@ public class OkHttpRibbonRequestTests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.netflix.zuul.filters.route;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.cloud.netflix.ribbon.support.RibbonRequestCustomizer;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
import com.netflix.client.http.HttpRequest;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class RestClientRibbonCommandTests {
|
||||
|
||||
@Test
|
||||
public void testNullEntity() throws Exception {
|
||||
String uri = "http://example.com";
|
||||
LinkedMultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
|
||||
headers.add("my-header", "my-value");
|
||||
LinkedMultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("myparam", "myparamval");
|
||||
RestClientRibbonCommand command = new RestClientRibbonCommand("cmd", null, new RibbonCommandContext("example", "GET", uri, false,
|
||||
headers, params, null));
|
||||
|
||||
HttpRequest request = command.createRequest();
|
||||
|
||||
assertThat("uri is wrong", request.getUri().toString(), startsWith(uri));
|
||||
assertThat("my-header is wrong", request.getHttpHeaders().getFirstValue("my-header"), is(equalTo("my-value")));
|
||||
assertThat("myparam is missing", request.getQueryParams().get("myparam").iterator().next(), is(equalTo("myparamval")));
|
||||
}
|
||||
|
||||
@Test
|
||||
// this situation happens, see https://github.com/spring-cloud/spring-cloud-netflix/issues/1042#issuecomment-227723877
|
||||
public void testEmptyEntityGet() throws Exception {
|
||||
String entityValue = "";
|
||||
testEntity(entityValue, new ByteArrayInputStream(entityValue.getBytes()), false, "GET");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonEmptyEntityPost() throws Exception {
|
||||
String entityValue = "abcd";
|
||||
testEntity(entityValue, new ByteArrayInputStream(entityValue.getBytes()), true, "POST");
|
||||
}
|
||||
|
||||
void testEntity(String entityValue, ByteArrayInputStream requestEntity, boolean addContentLengthHeader, String method) throws Exception {
|
||||
String lengthString = String.valueOf(entityValue.length());
|
||||
Long length = null;
|
||||
URI uri = URI.create("http://example.com");
|
||||
LinkedMultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
|
||||
if (addContentLengthHeader) {
|
||||
headers.add("Content-Length", lengthString);
|
||||
length = (long) entityValue.length();
|
||||
}
|
||||
|
||||
RibbonRequestCustomizer requestCustomizer = new RibbonRequestCustomizer<HttpRequest.Builder>() {
|
||||
@Override
|
||||
public boolean accepts(Class builderClass) {
|
||||
return builderClass == HttpRequest.Builder.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(HttpRequest.Builder builder) {
|
||||
builder.header("from-customizer", "foo");
|
||||
}
|
||||
};
|
||||
RibbonCommandContext context = new RibbonCommandContext("example", method,
|
||||
uri.toString(), false, headers, new LinkedMultiValueMap<String, String>(),
|
||||
requestEntity, Collections.singletonList(requestCustomizer));
|
||||
context.setContentLength(length);
|
||||
RestClientRibbonCommand command = new RestClientRibbonCommand("cmd", null, context);
|
||||
|
||||
HttpRequest request = command.createRequest();
|
||||
|
||||
assertThat("uri is wrong", request.getUri().toString(), startsWith(uri.toString()));
|
||||
if (addContentLengthHeader) {
|
||||
assertThat("Content-Length is wrong", request.getHttpHeaders().getFirstValue("Content-Length"),
|
||||
is(equalTo(lengthString)));
|
||||
}
|
||||
assertThat("from-customizer is wrong", request.getHttpHeaders().getFirstValue("from-customizer"),
|
||||
is(equalTo("foo")));
|
||||
|
||||
|
||||
assertThat("entity is missing", request.getEntity(), is(notNullValue()));
|
||||
assertThat("entity is wrong type", InputStream.class.isAssignableFrom(request.getEntity().getClass()), is(true));
|
||||
InputStream entity = (InputStream) request.getEntity();
|
||||
String string = StreamUtils.copyToString(entity, Charset.forName("UTF-8"));
|
||||
assertThat("content is wrong", string, is(equalTo(entityValue)));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user