spring集成出站网关的动态https URL有问题

时间:2018-12-06 14:35:41

标签: spring-integration

我想构建一个软网关,所以我将为我的内部系统提供一些spring集成的url,然后我的系统将其发送到实际目标的url。 这是我的代码。这是一个出站网关,我已经在inputchannel标头中设置了https url。

<int:channel id="inputChannel"/>
<int:channel id="outputChannel">
    <int:queue capacity="100"/>
</int:channel>

<int-http:outbound-gateway   request-channel="inputChannel"
                            url-expression="headers.dynamicUrl"
                           http-method-expression="POST"
                           expected-response-type="java.lang.String"
                            reply-channel="outputChannel"

                           charset="UTF-8">
</int-http:outbound-gateway>

我的Java代码就是这样

MessageChannel inputChannel = context.getBean("inputChannel", MessageChannel.class);
    PollableChannel outputChannel = context.getBean("outputChannel", PollableChannel.class);
    inputChannel.send(msgWithHTTPsUrl);//msg with https Url https://www.example.net
    Message<?> replyMesg = outputChannel.receive();
    Message<?> toSend = MessageBuilder.withPayload(replyMesg.getPayload()).copyHeadersIfAbsent(replyMesg.getHeaders()).build();
    System.out.println(toSend);
    return toSend;

,程序可以打印以发送味精。但浏览器无法获得回复。它显示ERR_CONTENT_DECODING_FAILED。 也许https://www.example.net使用gzip压缩。 那么我该如何处理,以便为公司的内部系统建立一个软网关? 谢谢!


现在,我添加了一个休息模板来解决此错误

<int-http:outbound-gateway   request-channel="inputChannel"
                        url-expression="headers.dynamicUrl"
                       http-method-expression="POST"
                       expected-response-type="java.lang.String"
                        reply-channel="outputChannel"
                        rest-template="restTemplate"
                       charset="UTF-8">

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
    <constructor-arg ref="sslFactory" />
</bean>
<bean id="sslFactory" class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
    <constructor-arg ref="httpClient"/>
</bean>

,我设置了忽略服务器端证书的验证,这是我的httpclient的Java代码

        @Component("httpClient")
    public class HttpClientFactory extends AbstractFactoryBean<HttpClient> {

        @Override
        public Class<?> getObjectType() {
            return HttpClient.class;
        }
        public HttpClient getInstance() throws Exception {
            return createInstance();
        }
        @Override
        protected HttpClient createInstance() throws Exception {

            RequestConfig defaultRequestConfig = RequestConfig.custom()
                    .setSocketTimeout(3000)
                    .setConnectTimeout(3000)
                    .setConnectionRequestTimeout(3000)
                    .setStaleConnectionCheckEnabled(true)
                    .build();

            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            TrustStrategy allTrust = new TrustStrategy() {
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }
            };

            SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(trustStore, allTrust).build();

            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
                    .setDefaultRequestConfig(defaultRequestConfig).build();
            return httpClient;
        }

但是当我使用此httpclient时,outbund-gateway会收到4xx / 5xx响应, 我写了一个HttpPost来测试这个httpclient,响应正常。 是我误解了外向网关吗?还是我错过了什么?


我编写测试用例来测试我的Spring集成应用程序,以及我注入到Spring集成中的httpclient。 spring集成应用收到错误回复:

org.springframework.messaging.MessageHandlingException: HTTP request execution failed for URI [https://www.npr.org/]; nested exception is org.springframework.web.client.HttpClientErrorException: 400 Bad Request, failedMessage=GenericMessage [payload=byte[0], headers={content-length=0, http_requestMethod=POST, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@3afa4833, httpMethod=POST, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@3afa4833, respUrl=https://www.npr.org/, host=localhost:8080, http_requestUrl=http://localhost:8080/sihttp/mytest, connection=Keep-Alive, id=256ed96e-9c00-ecf4-9d1b-63f37635fb4a, contentType=application/json;charset=UTF-8, accept-encoding=gzip,deflate, user-agent=Apache-HttpClient/4.5.6 (Java/1.8.0_131), timestamp=1544368429831}]

和httpClient访问https://www.npr.org/直接返回成功。测试代码如下:

CloseableHttpClient httpClient = HttpClients.createDefault(); // same httpclinet I inject in outbound gateway's rest-template
    HttpPost post=null;
    post = new HttpPost("http://localhost:8080/sihttp/mytest"); // this post will goto my spring integration app, in spring integration app, I will map this  url to https://www.npr.ogr, and send out in outbound gateway
//   post = new HttpPost("https://www.npr.org/"); // npr.org can successful visit in this post
        post.setHeader("Content-Type", "application/json;charset=UTF-8");
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(6000).setConnectionRequestTimeout(6000)
                .setSocketTimeout(6000).build();
        post.setConfig(requestConfig);
        CloseableHttpResponse httpResponse = httpClient.execute(post);
        HttpEntity httpEntity = httpResponse.getEntity();
        if (httpEntity != null) {
            System.out.println(EntityUtils.toString(httpEntity));
        }

        httpResponse.close();

在春季集成中,httpclient与httpContext执行

HttpResponse httpResponse = this.httpClient.execute(this.httpRequest, this.httpContext);

并在HttpClient中直接执行。

httpClient.execute(post);

这是两个结果不同的原因吗?

1 个答案:

答案 0 :(得分:1)

如果故事是关于GZIP的,则应考虑向您的<int-http:outbound-gateway>注入其他内容:

<xsd:attribute name="request-factory" type="xsd:string">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
Reference to a ClientHttpRequestFactory to be used by the underlying RestTemplate.
                ]]></xsd:documentation>
            <xsd:appinfo>
                <tool:annotation kind="ref">
                    <tool:expected-type type="org.springframework.http.client.ClientHttpRequestFactory" />
                </tool:annotation>
            </xsd:appinfo>
        </xsd:annotation>
    </xsd:attribute>

我的建议是使用HttpComponentsClientHttpRequestFactory

如果仍然无法解决问题,请与我们分享整个堆栈跟踪以确定可能遗漏的内容。