Bob Santos
Bob Santos

Reputation: 55

Spring Integration Wrong Host Header

We've been experiencing this weird problem with the request Host header being set as the application's URL. This results to the external system to not handle our requests.

Here's the DEBUG log of apache of the Spring Integration application hosted on localhost:8082. Don't mind the content for now but the Content-Type will be a problem subsequently:

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]"

and here's the request done with 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)

So with Spring Integration org.apache.http.wire - http-outgoing-0 >> "host: localhost:8082[\r][\n]"

and with curl > Host: localhost:9292

We can easily solve the host problem in Spring Integration by setting the header mapper of the outgate: 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"

So we were able to solve the problem with the Host header, unfortunately, it seems that the Content-Type set through an enricher has been ignored and has been set to text/plain instead of application/xml.

What seems to be the problem here? I'm assuming this has to do with just using a basic DefaultHttpHeaderMapper.

Here's the flow configuration snippet:

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());
    }
}

Upvotes: 0

Views: 627

Answers (1)

Gary Russell
Gary Russell

Reputation: 174584

Use

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

Upvotes: 1

Related Questions