CORS - 第一次POST请求没有服务器响应,第二次请求成功

时间:2014-06-14 19:45:24

标签: javascript jquery ajax tomcat cors

如何让第一个预先发出的POST请求成功完成并将响应发送回我的jQuery $ .ajax()方法?

问题

当我使用CORS和Tomcat时,我发送的第一个帖子请求挂起。由于我的请求是预先通知的,因此它会触发CORS。根据Chrome开发者窗口中的“网络”标签,OPTIONS预检请求成功完成,但POST请求保持待定状态。

奇怪的是,servlet收到了POST请求,servlet完成了请求。然而,servlet或其他我不知道的东西,并没有向我的客户端发回响应,因此客户端挂起,等待对原始POST请求的响应。

即使更奇怪,同一网址第二个POST 请求也会成功完成,并会为第二个POST请求返回响应。在第二个请求之前没有OPTIONS握手,因为浏览器缓存了预检请求,因为我将cors.maxAge设置为3600.第二个请求必须使用从原始预检缓存的OPTIONS。

其他类似的SO问题: 有很多关于SO的问题谈论CORS,其中一些讨论使用Tomcat和CORS。 来自Ninefingers的一个很棒,但它出现在Python上。 来自James的另一个很好,但它似乎并不适用,因为我使用了更新版本的jQuery并指定了cors.maxAge属性。

我的设置

  1. 我在一个不同于我的JS Aplication的服务器上的Tomcat容器中使用REST API作为servlet。
  2. 我在单独的域上使用WaveMaker编辑器(基于Dojo JS Framework)定义了JavaScript UI。
  3. 我在REST API servlet中使用CORS过滤器来允许跨域请求。
  4. 我正在使用jQuery 2.1.1进行AJAX调用。
  5. 我正在使用Tomcat 8作为我的REST API服务器,使用Tomcat 7作为我的WaveMaker客户端应用程序。
  6. 我正在使用Vladimir Dzhuvinov的CORS过滤器here
  7. HTTP标头

    我的请求网址:http://myRESTAPIHost:8080/myServlet/LinkObject

    1。初始OPTIONS请求(预检)

    Accept:*/*
    Accept-Encoding:gzip,deflate,sdch
    Accept-Language:en-US,en;q=0.8
    Access-Control-Request-Headers:accept, content-type
    Access-Control-Request-Method:POST
    Connection:keep-alive
    Host:myRESTAPIHost:8080
    Origin:http://myClientUIHost:8080
    Referer:http://myClientUIHost:8080/myClientServlet/
    User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36
    Response Headersview source
    

    2。对OPTIONS请求的响应(预检)

    Access-Control-Allow-Headers:accept, content-type
    Access-Control-Allow-Methods:PUT, DELETE, GET, POST, OPTIONS, HEAD
    Access-Control-Allow-Origin:http://myClientUIHost:8080
    Access-Control-Max-Age:3600
    Content-Length:0
    Date:Fri, 13 Jun 2014 19:11:01 GMT
    Server:Apache-Coyote/1.1
    Vary:Origin
    

    3。初始POST请求(挂起 - 无响应)

    Accept:application/json, text/javascript, */*; q=0.01
    Content-Type:application/json;
    Origin:http://myClientUIHost:8080
    Referer:http://myClientUIHost:8080/myClientServlet/
    User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36
    

    4。 (缺少答复)

    5。对同一URL的第二个POST请求

    Accept:application/json, text/javascript, */*; q=0.01
    Accept-Encoding:gzip,deflate,sdch
    Accept-Language:en-US,en;q=0.8
    Connection:keep-alive
    Content-Length:52
    Content-Type:application/json;
    Host:myRESTAPIHost:8080
    Origin:http://myClientUIHost:8080
    Referer:http://myClientUIHost:8080/ubmPrototype/
    User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36
    

    6。响应第二个POST

    Access-Control-Allow-Origin:http://myClientUIHost:8080
    Access-Control-Expose-Headers:X-Custom-1, X-Custom-2
    Content-Type:application/json;charset=UTF-8
    Date:Fri, 13 Jun 2014 19:16:57 GMT
    Server:Apache-Coyote/1.1
    Transfer-Encoding:chunked
    Vary:Origin
    

    jQuery ajax call

    objSave: function(restfulUrl, obj, opType, error, gridVar, dialog) {        
        $.ajax({
            type : opType,
            crossDomain : true,
            url : "http://myRESTAPIHost/myServlet/" + restfulUrl,
            data : JSON.stringify(obj),
            contentType : "application/json;",
            dataType : "json"
        }).done(function(data) {
            if(gridVar !== undefined && gridVar !== null)
                gridVar.update();
            if(dialog !== undefined && dialog !== null)
                dialog.hide();
        }).fail(function(){
            console.log(error);
        });
    },
    

    的web.xml

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
    <display-name>MyCORSfilter</display-name>
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
    <listener>
        <listener-class>
            org.springframework.web.context.request.RequestContextListener
        </listener-class>
    </listener>
    <filter>
        <description>generated-persistence-filter</description>
        <filter-name>CORSFilter</filter-name>
        <filter-class>
            org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
        </filter-class>
        <init-param>
            <param-name>entityManagerFactoryBeanName</param-name>
            <param-value>myServlet</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>MyCORSFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter>
        <!-- The CORS filter with parameters -->
        <filter-name>CORS</filter-name>
        <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
    
        <!-- Note: All parameters are options, if omitted the CORS 
             Filter will fall back to the respective default values.
          -->
        <init-param>
            <param-name>cors.allowGenericHttpRequests</param-name>
            <param-value>true</param-value>
        </init-param>
    
        <init-param>
            <param-name>cors.allowOrigin</param-name>
            <param-value>__all of my other hosts__, http://myClientUIHost:8080, http://myRESTAPIHost:8080</param-value>
        </init-param>
    
        <init-param>
            <param-name>cors.allowSubdomains</param-name>
            <param-value>false</param-value>
        </init-param>
    
        <init-param>
            <param-name>cors.supportedMethods</param-name>
            <param-value>GET, HEAD, POST, PUT, DELETE, OPTIONS</param-value>
        </init-param>
    
        <init-param>
            <param-name>cors.supportedHeaders</param-name>
            <param-value>*</param-value>
        </init-param>
    
        <init-param>
            <param-name>cors.exposedHeaders</param-name>
            <param-value>X-Custom-1, X-Custom-2</param-value>
        </init-param>
    
        <init-param>
            <param-name>cors.supportsCredentials</param-name>
            <param-value>false</param-value>
        </init-param>
    
        <init-param>
            <param-name>cors.maxAge</param-name>
            <param-value>3600</param-value>
        </init-param>
    
    </filter>
    <filter-mapping>
            <filter-name>CORS</filter-name>
            <url-pattern>/*</url-pattern>
    </filter-mapping>
    <servlet>
        <description>generated-servlet</description>
        <servlet-name>myServlet</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:myServlet-web-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet>
        <description>generated-resources-servlet</description>
        <servlet-name>Resource Servlet</servlet-name>
        <servlet-class>
            org.springframework.js.resource.ResourceServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Resource Servlet</servlet-name>
        <url-pattern>/resources/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>myServlet Servlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    

1 个答案:

答案 0 :(得分:3)

这可能会让你们中的一些人大笑。

解决方案是在我的防病毒程序Sophos AV中关闭Web Protection。

请参阅论坛上的链接,了解发生在我身上的具体信息: http://community.sophos.com/t5/Sophos-EndUser-Protection/Sophos-9-0-7-breaks-browser-AJAX-CORS-support-in-Chrome-Firefox/m-p/46923/highlight/false#M17046

以下是来自rghazarianDominik的两个SO链接,但问题和解决方案相同。

捂脸!