Reputation: 4367
This script (executed in browser):
$(function(){
$.ajax("http://localhost:3000/rest/room/7", {
type: "DELETE",
success: function(data, statusText, jqXHR){
$("p").text("complete, " + statusText + ", " + data.status + " data=" + JSON.stringify(data) + " jqXHR=" + JSON.stringify(jqXHR));
},
complete: function(data, statusText, jqXHR){
$("p").text("complete, " + statusText + ", " + data.status + " data=" + JSON.stringify(data) + " jqXHR=" + JSON.stringify(jqXHR));
}
});
});
and this Express route def:
app.delete('/rest/room/:id', function(req, res){
res.json(JSON.stringify(findings[0]));
});
just gets me this in the browser:
complete, error, 404 data={"readyState":4,"status":404,"statusText":"error"} jqXHR=undefined
and this console output (using PhpStorm IDE):
OPTIONS /rest/room/7 200 1ms - 4.51kb
Why does a 'DELETE' request become an 'OPTIONS' request? What am I missing?
Upvotes: 3
Views: 2118
Reputation: 161457
This is because you are attempting to do a cross-domain DELETE
request. In older browsers this is not supported, but newer browsers support CORS which enables easy cross-domain requests as long as the destination server and the browser both support it.
In CORS, the server sends it's data along with special headers that let the browser know what is and is not allowed. In the case of GET
, HEAD
, and POST
requests it simple expects the Access-Control-Allow-Origin
header to be sent with the request data and with a value of the hostname of the page requesting the resource.
In the case of DELETE
requests, it will first send an OPTIONS
request to confirm if DELETE
is allowed over CORS. In that case, you need to return a second header, Access-Control-Allow-Methods
with a value of DELETE
(and any other methods you want to support that aren't in my list above).
So in your case, you should have something like this:
app.options('/rest/room/:id', function(req, res){
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'DELETE');
res.end();
});
Depending on the usecase, you may not want '*'
and instead you should list the actual domains that are allowed to access your API.
Another option would be to avoid cross-domain requests entirely. Currently you are accessing Node on port 3000 but the HTML is loaded via (I assume Apache?) on port 80, which means they are loaded via totally separate servers. You could consider proxying your traffic through an intermediary so that both requests go to the same server.
Upvotes: 8