Tomcat 8没有响应来自CriOS的OPTIONS请求

Tomcat 8 not responding to OPTIONS request from CriOS

本文关键字:CriOS OPTIONS 请求 响应 Tomcat      更新时间:2023-09-26

我有一个应用程序,它使用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" );
    }
}

一切都很好,除了Chrome在iOS上(Chrome在Android上工作!)。对于这个特定的客户端,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字节的响应。

我不知道更好的方法,然后在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 for iOS插入图像/webp内容类型?我可以通过操作服务器本身的请求头来解决这个问题:

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", "*/*" );
    }
}

此过滤器简单地将任何*/*,图像/webp内容类型覆盖为直接的*/*,允许服务器响应文本/明文,从而在客户端(CriOS)上启用CORS。