问题场景:

在程序后端调用外部接口时,通过域名代理访问接口能正常调用返回,通过ip端口直连访问报ProtocolException: Invalid header: Server异常。

问题原因:

外部接口可能考虑安全因素,将响应头中的服务器信息给隐藏,但是这个隐藏做的不太规范,比如本应该保留冒号的,但是没有保留,导致外部直接调用解析响应体时报错。

解决方案:

方案一:接口提供方改动,将响应头隐藏服务器信息的写法写规范,确保响应头里是Server: 而不是Server。

方案二:接口提供方不改动,调用方将通过ip访问的接口使用代理服务器进行转发,比如nginx代理,通过转发访问的方式对响应体进行包装,会自动把响应头里的Server附加上Nginx服务器信息。

方案三:后端发送请求换其他不校验响应头的http请求客户端。

问题详述:

比如接口的请求url是/appContext/area/getInfo, 提供这个接口服务的ip和端口分别为157.123.22.6,端口8085,然后也用nginx配置了一个域名www.test123.com.cn转发请求,网络都是正常的。

现在通过http://www.test123.com.cn/appContext/area/getInfo这个url调用时接口能正常返回,通过

http://157.123.22.6:8085/appContext/area/getInfo这个url调用时,发送请求的客户端直接报org.apache.http.ProtocolException: Invalid header: Server 异常了。

异常关键信息如下:

Caused by: org.apache.http.ProtocolException: Invalid header: Server

at org.apache.http.impl.io.AbstractMessageParser.parseHeaders(AbstractMessageParser.java:230)

at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:266)

at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:163)

at org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:167)

at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:273)

at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)

at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:271)

at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)

at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)

at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)

at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)

... 151 common frames omitted

问题分析:

分析

at org.apache.http.impl.io.AbstractMessageParser.parseHeaders(AbstractMessageParser.java:230)

这个地方对应的源码,会发现最终它校验了header.indexOf(":")这个,如果等于-1就会抛出ProtocolException: Invalid header: xxx异常。

可以通过浏览器访问不同的url,直接访问ip和端口的方式查看响应头情况如下:

这里面的响应头Server不带冒号,在后端调用解析时会报错。

通过域名转发的方式访问,查看响应头情况如下:

这里的Server响应头为Server:在后端解析就是正常的。

对于这类问题,除了Server头,其他的头也可以尝试类似的处理方法。

参考阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: