带有预检的 POST 请求包含允许的来源,但错误是不允许来源

Posted

技术标签:

【中文标题】带有预检的 POST 请求包含允许的来源,但错误是不允许来源【英文标题】:POST request with preflight contains allowed origin but errors that origin is not allowed 【发布时间】:2017-11-29 08:17:53 【问题描述】:

我正在向我拥有并有权访问的服务器发送 POST 请求。

这会使用 OPTIONS 方法触发 CORS 预检请求并返回以下响应标头:

HTTP/1.1 200
Allow: HEAD,POST,GET,OPTIONS
Last-modified: Mon, 26 Jun 2017 13:57:08 BST
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: POST, GET
Access-Control-Allow-Headers: origin, content-type, accept, authorization
Access-Control-Expose-Headers: Set-Cookie
Content-Type: application/vnd.sun.wadl+xml
Content-Length: 1126

随后的POST请求然后报告

Fetch API cannot load http://localhost:8080/api/reservation. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 500. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

使用 javascript fetch.

如上所述,对我的/reservation 端点的 POST 会导致此类错误。但是,对我服务器上其他端点的 POST 请求是成功的,并且不会失败报告不允许来源。两者都执行相同的fetch 代码;发出 OPTIONS 预检,然后 POST。

var RestRequest = 

    post: function(endpoint, payload, callback, secondCallback) 

        fetch('http://localhost:8080/api' + endpoint, 
            headers: 
                'Accept': 'application/json',
                'Content-Type': 'application/json',
            ,
            method: 'post',
            credentials: 'include',
            body: payload
        )
        .then(function (response) 
            return response.json()
        )
        .then( function (result) 
            callback(result)
            if (secondCallback != null) 
                secondCallback()
            
        )
    
;

当 CORS 预检明确允许访问此特定来源时,为什么我的浏览器会抱怨发出请求的来源不被允许访问?

修改我的服务器 CORS 响应过滤器以允许所有来源导致相同的错误消息。从 Postman 插件发出相同的请求成功。

【问题讨论】:

【参考方案1】:

它表示响应的 HTTP 状态代码为 500,因此它与您发布的响应(即 HTTP 200)不同。

您很可能遇到了服务器错误,导致无法将 CORS 标头添加到响应中。

【讨论】:

状态码 200 来自 CORS preflight OPTIONS 请求。 对,对不起,我没有注意到,但问题仍然是一样的。如果您的服务器上出现 500 错误,则不会发送标头。因此,您遇到的问题不在于 CORS,而在于您服务器上的其他一些错误。 服务器没有错误,因为使用 Postman 发出完全相同的请求成功。似乎这可能是 javascript 的 fetch api 的问题,因为使用 unirest 处理 REST 请求也成功了。 500 代码似乎来自一个不完整的 POST 请求,导致服务器在事后抛出一个 500,因为它期望 POST 请求中有一个主体,并且没有收到一个主体,因为浏览器在意识到来源时切断了程序。允许。在这种情况下,如果不允许,我不确定为什么任何类型的 POST 请求都会发送到服务器。 @Shiri,您能否发布有效的邮递员请求和无效的 fetch 请求?我假设fetch 工作正常,但您需要正确设置它。您可能仍想查看 500,因为如果 fetch 发出不完整的请求,服务器应该响应 400(用户错误)而不是 500(服务器错误)。这也可能会告诉您获取请求的问题所在。 我已经更新了我的问题以包含代码和关于此的重要缺失信息。 fetch 块的其他用途完全成功,但仅因我的一个端点不允许原始访问而失败。您对服务器不正确的响应代码是正确的,我会寻求更好地处理它,但是客户端在报告 some 请求不允许来源后发出不完整请求的根本问题仍然是非常奇怪的不一致。

以上是关于带有预检的 POST 请求包含允许的来源,但错误是不允许来源的主要内容,如果未能解决你的问题,请参考以下文章

使用 fetch api 调用带有 keepalive 的 POST 请求时,预检请求失败

带有预检的 Node.JS 中的跨域 POST 请求?

Angular CORS 简单请求在 POST 中触发带有 Authorization 标头的预检

对预检请求的响应未通过访问控制检查错误

带有 Windows 身份验证预检问题的 Angular 4 HTTP POST [重复]

ArcGIS Server REST API - POST OPTIONS 预检请求:405 方法不允许