Spring Integration错误的主机标题

时间:2017-07-04 14:07:50

标签: spring-integration spring-integration-dsl

我们遇到了这个奇怪的问题,请求主机标头被设置为应用程序的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());
    }
}

1 个答案:

答案 0 :(得分:0)

使用

DefaultHttpHeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper();
mapper.setExcludedOutboundStandardRequestHeaderNames(new String[] { "Host" });
handler.setHeaderMapper(mapper);