CORS - How do 'preflight' an httprequest?

I am trying to make a cross domain HTTP request to WCF service (that I own). I have read several techniques for working with the cross domain scripting limitations. Because my service must accommodate both GET and POST requests I cannot implement some dynamic script tag whose src is the URL of a GET request. Since I am free to make changes at the server I have begun to try to implement a workaround that involves configuring the server responses to include the "Access-Control-Allow-Origin" header and 'preflight' requests with and OPTIONS request. I got the idea from this post : Getting CORS working

At the server side, my web method is adding 'Access-Control-Allow-Origin: *' to the HTTP response. I can see that responses do include this header now. My question is: How do I 'preflight' a request (OPTIONS)? I am using jQuery.getJSON to make the GET request but the browser cancels the request right away with the infamous:

Origin http://localhost is not allowed by Access-Control-Allow-Origin

Is anyone familiar with this CORS technique? What changes need to be made at the client to preflight my request?

Thanks!

205412 次浏览

在飞行前请求期间,您应该看到以下两个头: Access-Control-Request-Method 和 Access-Control-Request-Header。这些请求标头要求服务器提供发出实际请求的权限。您的飞行前响应需要确认这些标头,以便实际请求能够正常工作。

例如,假设浏览器使用以下标题发出请求:

Origin: http://yourdomain.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-Custom-Header

然后,您的服务器应该响应以下标题:

Access-Control-Allow-Origin: http://yourdomain.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: X-Custom-Header

请特别注意 Access-Control-allow-Header 响应标头。此标头的值应该是 Access-Control-Request-Header 请求标头中的相同标头,并且不能是“ *”。

一旦您将这个响应发送到飞行前请求,浏览器将发出实际请求。你可以在这里了解更多关于 CORS 的信息: http://www.html5rocks.com/en/tutorials/cors/

尽管这个问题可以追溯到2014年,但是对于我们中的很多人来说,这个问题仍然存在。下面是我在 jQuery 1.12/PHP 5.6上下文中处理它的方法:

  • JQuery 只使用有限的头发送了它的 XHR 请求; 只发送了“ Origin”。
  • 不需要飞行前的请求。
  • 服务器只需检测到这样的请求,并添加“ Access-Control-allow-Origin:”。$_ SERVER [‘ HTTP _ ORIGIN’]头,在检测到这是一个跨源 XHR 之后。

PHP 代码示例:

if (!empty($_SERVER['HTTP_ORIGIN'])) {
// Uh oh, this XHR comes from outer space...
// Use this opportunity to filter out referers that shouldn't be allowed to see this request
if (!preg_match('@\.partner\.domain\.net$@'))
die("End of the road if you're not my business partner.");


// otherwise oblige
header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
}
else {
// local request, no need to send a specific header for CORS
}

特别是,不要添加一个 exit;,因为没有飞行前需要。

通过使用以下简单步骤在 Node.js中编写自定义中间件来解决 CORS 问题。

don't need to set anything from the client, just a little change on the Node.js server will fix the problem.

创建一个中间件:

// in middleware/corsResolver.js


function corsResolver(req, res, next) {
// Website you wish to allow to connect
// running front-end application on port 3000
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,Authorization');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
}


module.exports = corsResolver;


现在编辑 server.js (index.js 或任何启动节点服务器的主文件)并添加这个中间件:

// server.js or indes.js


const corsResolver = require('path/to/resolver-middleware')


app.use(corsResolver)  // -----------> applied middleware here




// other stuff