Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CORS sync sends OPTIONS request instead of POST #2542

Closed
ghost opened this issue May 17, 2013 · 17 comments
Closed

CORS sync sends OPTIONS request instead of POST #2542

ghost opened this issue May 17, 2013 · 17 comments

Comments

@ghost
Copy link

ghost commented May 17, 2013

I'm trying to use the model.save() with a rest service on another subdomain. I got the following request headers which are far from my expectations:

OPTIONS /user HTTP/1.1
Host: not.public
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:20.0) Gecko/20100101 Firefox/20.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: http://not.public
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

How to fix this?

Ofc. my REST server responds 404 not found for an OPTIONS call...

To avoid unwanted questions: the server is ok, it handles REST calls and CORS calls well, tested with $.ajax and a REST interface tester application too.

@philfreo
Copy link
Contributor

Look up how CORS works -- this is the expected "preflight" request

https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS#Preflighted_requests

@ghost
Copy link
Author

ghost commented May 17, 2013

How can I avoid this reflight request?

@philfreo
Copy link
Contributor

Only be sending a "simple request" as defined here: https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS#Simple_requests

@ghost
Copy link
Author

ghost commented May 17, 2013

I tried this on server side to handle preflight calls:

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: X-Requested-With');
header('Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS');

but did not work, the browser does not send another request after the preflight...

So you say that it is not possible with backbone.sync?
Then it is a bug I think...

@philfreo
Copy link
Contributor

Regardless, this isn't a Backbone issue, so I suggest asking on Stackoverflow or IRC.

@ghost
Copy link
Author

ghost commented May 17, 2013

Can you explain me why this is not a backbone issue?

@philfreo
Copy link
Contributor

Read through the source of Backbone.sync ( http://backbonejs.org/docs/backbone.html#section-134 ) and you'll see Backbone simply passes everything through to $.ajax.

@smagch
Copy link

smagch commented May 17, 2013

@Inf3rno try this one.

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: Content-Type');
header('Access-Control-Allow-Methods: POST');

This isn't Backbone issue at all.

@ghost
Copy link
Author

ghost commented May 17, 2013

These are my original headers without php:

HTTP/1.1 200 OK
Cache-Control: max-age=0, no-cache, no-store, must-revalidate
Pragma: no-cache
Content-Type: text/html
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Server: Microsoft-IIS/7.5
X-Powered-By: PHP/5.3.8, ASP.NET
access-control-allow-origin: http://x.y.loc
Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS
Date: Fri, 17 May 2013 01:33:02 GMT
Content-Length: 0

I think my server is well configured, but I tried out the headers you gave, and they did not work...

Simple $.ajax calls work well, for example I load json files from the service with this:

define(function (require, exports, module) {
    var $ = require("jquery");

    module.exports = {
        load: function (name, _require, load, config) {
            var params = name.split("|");
            var method, url;
            if (params.length == 1) {
                method = "GET";
                url = params[0];
            }
            else {
                method = params[0];
                url = params[1];
            }
            $.ajax({
                url: url,
                type: method,
                dataType: "json"
            }).success(load).error(function (xhr, status, error) {
                    throw error;
                });
        }
    };

});

I tried out this with any request method, and they responded well...

The collection.fetch() works well too, I have problems only with the model.save() ...

I tried it this way, maybe I'm doing something wrong:

        var User = Backbone.Model.extend({
            urlRoot: Application.service.Authorization.User.create.url
        });
        var form = new UserForm({
            model: new User({
                email: "a@b.com",
                name: "test"
            })
        }).render();
        form.on("submit", function (user) {
            console.log(user.attributes);
            user.save(null, {
                success: function (model, response, options) {
                    console.log("success");
                },
                error: function (model, xhr, options) {
                    console.log("error");
                }
            });
        });

I got the attributes and "error" in console. I'll check what kind of error is..

@ghost
Copy link
Author

ghost commented May 17, 2013

You were right, thanks! I added to server config the allow content-type, and it works now. Firebug is not the best, the Chrome console printed that the content-type is not allowed...

@ghost
Copy link
Author

ghost commented May 17, 2013

Many tanks! :D

@ghost ghost closed this as completed May 17, 2013
@smagch
Copy link

smagch commented May 17, 2013

GET and POST requests requires quite different headers. When the API server uses cookies for authentication, the server should have Access-Control-Allow-Credentials: true header. And off course you need to make a XHR request with withCredentials: true on client-side. When the API server uses Authorization header for BasicAuth request, you don't need withCredential. Instead, the Access-Control-Allow-Headers need to include Authorization in this case, just like

header('Access-Control-Allow-Headers: Authorization, Content-Type');

Ah, it seems you solved the issue while I'm writing this.

@ghost
Copy link
Author

ghost commented May 17, 2013

Ye, thanks anyway, you helped a lot!

@wxmiked
Copy link

wxmiked commented Aug 26, 2014

@Inf3rno Thanks so much for the comment about Chrome giving better error messages than Firebug! That helped us solve the problem.

@ghost
Copy link
Author

ghost commented Aug 26, 2014

You're welcome! :-)

@ghost
Copy link

ghost commented Sep 23, 2015

Can someone please help on this issue? http://stackoverflow.com/questions/32725249/cors-filter-issue-for-authentrypoint

@amanos1022
Copy link

In case anyone else is having this problem I had to add "x-http-method-override" to my list of Access-Control-Allow-Methods which is used when you set Backbone.emulateHTTP = true

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants