Search code examples
jqueryapacheruby-on-rails-3xmlhttprequesthttp-method

XHR doesn't work because "Origin is not allowed by Access-Control-Allow-Origin"


I'm working on a API-Server with Rails 3 which is pretty handy so far but I'm running across a error all the time and I'm not sure whether it is because of my Apache Setup or the Rails App.

When I try to do a HTTP DELETE or PUT request on http://sample.domain/uri/id via XHR, curl or HTTP-Client.app Rails or Apache responds with 404 or 403 (depends on the client. I think because of cors) and the Safari developer console responds with

XMLHttpRequest cannot load http://sample.domain/uri/id. Origin http://web.client/ is not allowed by Access-Control-Allow-Origin.

I'm using mod_rack aka mod_rails on a Apache2 and my vhost actually contains this:

Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods POST,GET,DELETE,PUT,OPTIONS
Header set Access-Control-Allow-Headers X-Requested-With

The Apache error_log responds with the following error:

[Sat Oct 30 01:37:34 2010] [error] [client 22.222.222.22] client denied by server configuration: /path/to/rails/folder/public, referrer: http://web.client/

Rails development.log responds with

Started OPTIONS "/uri/id" for 84.190.123.140 at 2010-10-30 03:18:42 +0200
ActionController::RoutingError (No route matches "/uri/id"):

And here I'm nor sure why the OPTIONS call comes through because I thought this would only be the preflight and for sure there is no route for OPTIONS because I want to respond to DELETE

If you have any idea on how to fix this problem please share it with me.

Thank you very much


Solution

  • You need to respond to the OPTIONS method. It is sent before the actual DELETE method to determine if sending a DELETE command is allowed - known as preflighting. You can control how long the permissions are valid with a Access-Control-Max-Age header.

    In your response to OPTIONS is where you send the Access-Control-Allow-Origin, etc.

    Imagine if that wasn't the case. You'd be sending ACAO after you've already deleted the object. Which may or may not have been allowed.

    For the origin server it is often best to either create an actual white list of servers that can post/delete, or parrot back the requesting server's domain name. A "*" essentially disables CORS and opens up the user to all sorts of attacks.