Tomcat 8 未响应来自 CriOS 的 OPTIONS 请求

Posted

技术标签:

【中文标题】Tomcat 8 未响应来自 CriOS 的 OPTIONS 请求【英文标题】:Tomcat 8 not responding to OPTIONS request from CriOS 【发布时间】:2015-12-10 21:25:04 【问题描述】:

我有一个应用程序将 POST 请求与 CORS 一起用于后端服务(从 www.mydomain.comapi.mydomain.com)。后端由Tomact8服务器提供,CORSResponseFilter已实现如下:

public class CORSResponseFilter implements ContainerResponseFilter 

   public void filter( ContainerRequestContext requestContext, ContainerResponseContext responseContext ) throws IOException 

       MultivaluedMap< String, Object > headers = responseContext.getHeaders();

       headers.add( "Access-Control-Allow-Origin", "*" );
       headers.add( "Access-Control-Allow-Methods", "POST" );
       headers.add( "Access-Control-Allow-Headers", "X-Requested-With, Content-Type" );
    

一切正常,除了 ios 上的 Chrome(android 上的 Chrome 工作正常!)。对于这个特定的客户端,Tomcat 似乎拒绝响应飞行前的OPTION 请求。下面显示了来自 Tomcat 的访问日志:

10.10.10.9 - - [14/Sep/2015:20:55:45 +0200] "OPTIONS /api HTTP/1.1" 200 - "Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/600.1.4 (Khtml, like Gecko) CriOS/45.0.2454.68 Mobile/13B5110e Safari/600.1.4"
10.10.10.1 - - [14/Sep/2015:20:56:29 +0200] "OPTIONS /api HTTP/1.1" 200 561 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36"

第二行显示了应有的请求,可以看到在第一种情况下响应没有大小,因此我认为根本没有发送任何内容,第二次调用正在接收 561 字节的响应。

我不知道有更好的方法然后 weinre 在 iOS 上调试 Chrome,它只显示POST 请求开始但从未收到响应(尽管 Tomcat 只收到OPTIONS 请求并且没有后续POST )

在客户端,superagent 库用于HTTP 调用。 我不知道这个问题是由 Tomcat 服务器本身还是由客户端/浏览器引起的,因为它只发生在特定设备/浏览器组合(iOS 上的 Chrome)上

有没有人遇到过类似的行为并能指出我缺少的部分?

PS:是的,iPhone 运行的是预发布的 iOS,但普通 iOS 版本也是如此

更新:使用 WireShark,我可以从桌面和移动设备中提取 OPTIONS 请求的标头。

来自 CriOS:

Connection: keep-alive
Access-Control-Request-Headers: accept, origin, content-type
Access-Control-Request-Method: POST
Accept: */*,image/webp
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/45.0.2454.89 Mobile/13B5110e Safari/600.1.4
Accept-Encoding: gzip, deflate, sdch
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4

从桌面:

Connection: keep-alive
Access-Control-Request-Method: POST
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36
Access-Control-Request-Headers: accept, content-type
Accept: */*
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,de-DE;q=0.6,de;q=0.4,ru;q=0.2

我注意到 ACCEPT 标头中的 image/webp 媒体类型,但它也有 */*,所以我不确定这是否是相关...

【问题讨论】:

希望我们能看到请求标头。 很乐意向您展示。知道如何在移动版 chrome @bayu.io 上收集它们吗? @bayou.io 找到了使用 WireShark 的方法,将更新我的问题 鉴于新的见解,我可以确定:***.com/questions/32287347/… 可能是相关的。 【参考方案1】:

参考Why does Chrome for iOS insert image/webp content-type?,我可以通过操作服务器本身的请求标头来解决这个问题:

public class CroISRequestFilter implements ContainerRequestFilter 

    @Override
    public void filter( final ContainerRequestContext requestContext ) throws IOException 

        if (requestContext.getHeaders().getFirst( "accept" ).equals( "*/*,image/webp" )) requestContext.getHeaders().putSingle( "accept", "*/*" );
    

此过滤器只是将任何 */*,image/webp 内容类型覆盖为直接 */*,允许服务器以 text/ 响应plain 在客户端 (CriOS) 上启用 CORS。

【讨论】:

以上是关于Tomcat 8 未响应来自 CriOS 的 OPTIONS 请求的主要内容,如果未能解决你的问题,请参考以下文章

Tomcat 7:RequestDumperFilter 未记录 HTTP 请求/响应正文

是否可以将 CORS 标头添加到来自 Tomcat 容器中 j_security_check 的响应

修改服务器Tomcat响应头 暴露Server:Apache-Coyote/1.1信息

来自 Guzzle 响应的条件未设置

Ubuntu 配置Tomcat环境(转载)

已为此响应调用 Tomcat 8.5 response.getWriter()