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.
Look up how CORS works -- this is the expected "preflight" request
https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS#Preflighted_requests
How can I avoid this reflight request?
Only be sending a "simple request" as defined here: https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS#Simple_requests
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...
Regardless, this isn't a Backbone issue, so I suggest asking on Stackoverflow or IRC.
Can you explain me why this is not a backbone issue?
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.
@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.
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: "[email protected]",
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..
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...
Many tanks! :D
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.
Ye, thanks anyway, you helped a lot!
@inf3rno Thanks so much for the comment about Chrome giving better error messages than Firebug! That helped us solve the problem.
You're welcome! :-)
Can someone please help on this issue? http://stackoverflow.com/questions/32725249/cors-filter-issue-for-authentrypoint
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
Most helpful comment
@inf3rno try this one.
This isn't Backbone issue at all.