我们遇到了这个奇怪的问题,请求主机标头被设置为应用程序的URL。这导致外部系统无法处理我们的请求。
这是Spring Integration application
上托管的localhost:8082
的apache的DEBUG日志。暂时不要介意内容,但Content-Type随后会出现问题:
org.apache.http.wire - http-outgoing-0 >> "POST /health HTTP/1.1[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "Accept: */*[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "cookie: PHPSESSID=ost897ibh0j7rovf2rudr33c22[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "host: localhost:8082[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "connection: keep-alive[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "Cache-Control: no-cache[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "Content-Type: application/xml[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "accept-encoding: gzip, deflate[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "user-agent: PostmanRuntime/6.1.6[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "Content-Length: 4[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "test"
org.apache.http.wire - http-outgoing-0 << "HTTP/1.1 200 OK[\r][\n]"
org.apache.http.wire - http-outgoing-0 << "Content-Type: application/json[\r][\n]"
org.apache.http.wire - http-outgoing-0 << "Transfer-Encoding: chunked[\r][\n]"
org.apache.http.wire - http-outgoing-0 << "Server: Jetty(9.2.z-SNAPSHOT)[\r][\n]"
org.apache.http.wire - http-outgoing-0 << "[\r][\n]"
org.apache.http.wire - http-outgoing-0 << "27[\r][\n]"
org.apache.http.wire - http-outgoing-0 << "{"success":true,"message":"Service up"}"
org.apache.http.headers - http-outgoing-0 << HTTP/1.1 200 OK
org.apache.http.headers - http-outgoing-0 << Content-Type: application/json
org.apache.http.headers - http-outgoing-0 << Transfer-Encoding: chunked
org.apache.http.headers - http-outgoing-0 << Server: Jetty(9.2.z-SNAPSHOT)
org.apache.http.wire - http-outgoing-0 << "[\r][\n]"
org.apache.http.wire - http-outgoing-0 << "0[\r][\n]"
org.apache.http.wire - http-outgoing-0 << "[\r][\n]"
以及curl的请求:
curl -v -X POST http://localhost:9292/health
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9292 (#0)
> POST /health HTTP/1.1
> Host: localhost:9292
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Transfer-Encoding: chunked
< Server: Jetty(9.2.z-SNAPSHOT)
使用Spring Integration
org.apache.http.wire - http-outgoing-0 >> "host: localhost:8082[\r][\n]"
和curl
> Host: localhost:9292
我们可以通过设置outgate的标头映射器轻松解决Spring Integration中的host
问题:
handler.setHeaderMapper(new DefaultHttpHeaderMapper());
org.apache.http.wire - http-outgoing-0 >> "POST /health HTTP/1.1[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "Accept: application/json, application/*+json[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "Content-Type: text/plain;charset=UTF-8[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "Content-Length: 4[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "Host: localhost:9292[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "Connection: Keep-Alive[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "User-Agent: Apache-HttpClient/4.5.2 (Java/1.8.0_112)[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "Accept-Encoding: gzip,deflate[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "[\r][\n]"
org.apache.http.wire - http-outgoing-0 >> "test"
所以我们能够使用Host
标头来解决问题,遗憾的是,似乎已忽略通过限定符设置的Content-Type
并将其设置为text/plain
而不是application/xml
。
这里似乎有什么问题?我假设这与使用基本的DefaultHttpHeaderMapper有关。
这是流量配置代码段:
public class BasicIntegrationConfig {
@Bean
public MessageChannel basicRequestChannel() {
return MessageChannels.publishSubscribe().get();
}
@Bean
public MessageChannel basicResponseChannel() {
return MessageChannels.publishSubscribe().get();
}
@Bean
public MessagingGatewaySupport basicInGate() {
HttpRequestHandlingMessagingGateway handler = new HttpRequestHandlingMessagingGateway();
RequestMapping mapping = new RequestMapping();
mapping.setPathPatterns("api/v1/basic");
mapping.setMethods(HttpMethod.GET);
mapping.setProduces(MediaType.APPLICATION_JSON_UTF8_VALUE);
handler.setRequestMapping(mapping);
handler.setRequestChannel(basicRequestChannel());
handler.setReplyChannel(basicResponseChannel());
return handler;
}
@Bean
public MessageHandler basicOutGate() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler("http://localhost:9292/health");
handler.setHttpMethod(HttpMethod.POST);
handler.setExpectedResponseType(BaseResponse.class);
handler.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
handler.setHeaderMapper(new DefaultHttpHeaderMapper());
return handler;
}
@Bean
public IntegrationFlow basicFlow() {
return (IntegrationFlowDefinition<?> f) -> f
.channel(basicRequestChannel())
.log("basic")
.handle((GenericHandler<Object>) (o, map) -> "test")
.enrichHeaders(e -> e.header(MessageHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE, true))
.log("basic")
.handle(basicOutGate())
.log("basic")
.enrichHeaders(e -> e.header(MessageHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE, true))
.channel(basicResponseChannel());
}
}
答案 0 :(得分:0)
使用
DefaultHttpHeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper();
mapper.setExcludedOutboundStandardRequestHeaderNames(new String[] { "Host" });
handler.setHeaderMapper(mapper);