CORS - How do 'preflight' an httprequest?
Asked Answered
C

2

119

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!

Crowl answered 31/12, 2011 at 1:36 Comment(0)
B
177

During the preflight request, you should see the following two headers: Access-Control-Request-Method and Access-Control-Request-Headers. These request headers are asking the server for permissions to make the actual request. Your preflight response needs to acknowledge these headers in order for the actual request to work.

For example, suppose the browser makes a request with the following headers:

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

Your server should then respond with the following headers:

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

Pay special attention to the Access-Control-Allow-Headers response header. The value of this header should be the same headers in the Access-Control-Request-Headers request header, and it can not be '*'.

Once you send this response to the preflight request, the browser will make the actual request. You can learn more about CORS here: http://www.html5rocks.com/en/tutorials/cors/

Beggarly answered 31/12, 2011 at 16:55 Comment(10)
could you add multiple domains to Access-Control-Allow-Origin?Lippmann
@Lippmann You probably worked this out by now but in case others are wondering can do Access-Control-Allow-Origin: *Rhythmist
I possibly missed something. So should I send two XMLHttp requests? One for the preflight; check the response on success and then send the actual query?Sociability
@Sociability you don't need to worry about sending the preflight request. If the request needs a preflight, the browser will send it for you.Beggarly
THANK YOU for the 'pay special attention' bit... that solved my issue with node/expressjs I was able to add a filter to catch these preflight requests //cors and preflight filtering app.all('*', function(req, res, next){.. //preflight needs to return exact request-header res.set('Access-Control-Allow-Headers', req.headers['access-control-request-headers']); if ('OPTIONS' == req.method) return res.send(204);next(); });Geomancer
Sorry , a bit late , But the Cross domain server I am trying to access works fine when I try a Soap client like boomerang , But doesnt work when I try from localhost . Why is that ?Wernerwernerite
That's what I was looking for. Thanks for such a lucid explanationGeotaxis
@monsur, Why not just have the server check the Origin/Referer header? In fact, the server will have to do that anyway, so what's the point of these extra headers?Pris
unfortunately in my case after preflight POST request is emptyGrivation
This answer is a bit outdated. All modern browsers now support the wildcard (*) as a valid value for the Access-Control-Allow-Headers header. Access-Control-Allow-Headers: * means that all request headers (other than Authorization and forbidden request-header names) are allowed.Triangulation
P
1

Although this thread dates back to 2014, the issue can still be current to many of us. Here is how I dealt with it in a jQuery 1.12 /PHP 5.6 context:

  • jQuery sent its XHR request using only limited headers; only 'Origin' was sent.
  • No preflight request was needed.
  • The server only had to detect such a request, and add the "Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN'] header, after detecting that this was a cross-origin XHR.

PHP Code sample:

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
}

In particular, don't add an exit; as no preflight is needed.

Platinize answered 24/8, 2017 at 5:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.