AngularJS performs an OPTIONS HTTP request for a cross-origin resource

For Angular 1.2.0rc1+ you need to add a resourceUrlWhitelist.

1.2: release version they added a escapeForRegexp function so you no longer have to escape the strings. You can just add the url directly

'http://sub*.assets.example.com/**' 

make sure to add ** for sub folders. Here is a working jsbin for 1.2: http://jsbin.com/olavok/145/edit


1.2.0rc: If you are still on a rc version, the Angular 1.2.0rc1 the solution looks like:

.config(['$sceDelegateProvider', function($sceDelegateProvider) {
     $sceDelegateProvider.resourceUrlWhitelist(['self', /^https?:\/\/(cdn\.)?yourdomain.com/]);
 }])

Here is a jsbin example where it works for 1.2.0rc1: http://jsbin.com/olavok/144/edit


Pre 1.2: For older versions (ref http://better-inter.net/enabling-cors-in-angular-js/) you need to add the following 2 lines to your config:

$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];

Here is a jsbin example where it works for pre 1.2 versions: http://jsbin.com/olavok/11/edit


OPTIONS request are by no means an AngularJS bug, this is how Cross-Origin Resource Sharing standard mandates browsers to behave. Please refer to this document: https://developer.mozilla.org/en-US/docs/HTTP_access_control, where in the "Overview" section it says:

The Cross-Origin Resource Sharing standard works by adding new HTTP headers that allow servers to describe the set of origins that are permitted to read that information using a web browser. Additionally, for HTTP request methods that can cause side-effects on user data (in particular; for HTTP methods other than GET, or for POST usage with certain MIME types). The specification mandates that browsers "preflight" the request, soliciting supported methods from the server with an HTTP OPTIONS request header, and then, upon "approval" from the server, sending the actual request with the actual HTTP request method. Servers can also notify clients whether "credentials" (including Cookies and HTTP Authentication data) should be sent with requests.

It is very hard to provide a generic solution that would work for all the WWW servers as setup will vary depending on the server itself and HTTP verbs that you intend to support. I would encourage you to get over this excellent article (http://www.html5rocks.com/en/tutorials/cors/) that has much more details on the exact headers that needs to be sent by a server.


NOTE: Not sure it works with the latest version of Angular.

ORIGINAL:

It's also possible to override the OPTIONS request (was only tested in Chrome):

app.config(['$httpProvider', function ($httpProvider) {
  //Reset headers to avoid OPTIONS request (aka preflight)
  $httpProvider.defaults.headers.common = {};
  $httpProvider.defaults.headers.post = {};
  $httpProvider.defaults.headers.put = {};
  $httpProvider.defaults.headers.patch = {};
}]);

Your service must answer an OPTIONS request with headers like these:

Access-Control-Allow-Origin: [the same origin from the request]
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: [the same ACCESS-CONTROL-REQUEST-HEADERS from request]

Here is a good doc: http://www.html5rocks.com/en/tutorials/cors/#toc-adding-cors-support-to-the-server