AngularJS $resource makes HTTP OPTIONS request instead of HTTP POST for $save method
I know it may be in bad taste to answer my own question but I figured out the problem a few days after posting this.
It all comes down to how browsers manage CORS. When making a cross-domain request in JavaScript that is not "simple" (i.e. a GET request - which explains why the query()
function worked), the browser will automatically make a HTTP OPTIONS request to the specified URL/URI, called a "pre-flight" request or "promise". As long as the remote source returns a HTTP status code of 200 and relevant details about what it will accept in the response headers, then the browser will go ahead with the original JavaScript call.
Here's a brief jQuery example:
function makeRequest() { // browser makes HTTP OPTIONS request to www.myotherwebsite.com/api/test // and if it receives a HTTP status code of 200 and relevant details about // what it will accept in HTTP headers, then it will make this POST request... $.post( "www.myotherwebsite.com/api/test", function(data) { alert(data); }); // ...if not then it won't - it's that simple.}
All I had to do was add the details of what the server will accept in the response headers:
// apply this rule to all requests accessing any URL/URIapp.all('*', function(req, res, next) { // add details of what is allowed in HTTP request headers to the response headers res.header('Access-Control-Allow-Origin', req.headers.origin); res.header('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS'); res.header('Access-Control-Allow-Credentials', false); res.header('Access-Control-Max-Age', '86400'); res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept'); // the next() function continues execution and will move onto the requested URL/URI next();});
And then insert these few lines before the Express routing to simply return a HTTP 200 status code for every OPTIONS request:
// fulfils pre-flight/promise requestapp.options('*', function(req, res) { res.send(200);});
Hopefully this will help anyone who stumbles on this page suffering from the same problem.
I didn´t actually try this, but wouldn´t it be enough to tell the Ressource how to handle the $save request?
$resource('http://mywebserver\\:1337/books/:bookId', { bookId: '@bookId' }, {save: {method: 'POST'});