3

此脚本(在浏览器中执行):

$(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));
        }
    });
});

而这条 Express 路线定义:

app.delete('/rest/room/:id', function(req, res){
    res.json(JSON.stringify(findings[0]));
});

只是在浏览器中得到这个:

complete, error, 404 data={"readyState":4,"status":404,"statusText":"error"} jqXHR=undefined

和这个控制台输出(使用 PhpStorm IDE):

OPTIONS /rest/room/7 200 1ms - 4.51kb

为什么“DELETE”请求会变成“OPTIONS”请求?我错过了什么?

4

1 回答 1

8

这是因为您正在尝试执行跨域DELETE请求。在较旧的浏览器中不支持此功能,但较新的浏览器支持CORS,只要目标服务器和浏览器都支持它,就可以轻松实现跨域请求。

在 CORS 中,服务器发送它的数据以及特殊的标头,让浏览器知道什么是允许的,什么是不允许的。在, 和requests 的情况下GET,它简单地期望标头与请求数据以及请求资源的页面的主机名值一起发送。HEADPOSTAccess-Control-Allow-Origin

DELETE请求的情况下,它将首先发送一个OPTIONS请求以确认是否DELETE允许通过 CORS。在这种情况下,您需要返回第二个标头,Access-Control-Allow-Methods其值为DELETE(以及您想要支持的任何其他不在我上面列表中的方法)。

所以在你的情况下,你应该有这样的东西:

app.options('/rest/room/:id', function(req, res){
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'DELETE');
  res.end();
});

根据用例,您可能不需要'*',而是应该列出允许访问您的 API 的实际域。

另一种选择是完全避免跨域请求。目前您正在端口 3000 上访问 Node,但 HTML 是通过(我假设是 Apache?)在端口 80 上加载的,这意味着它们是通过完全独立的服务器加载的。您可以考虑通过中介代理您的流量,以便两个请求都发送到同一台服务器。

于 2013-04-21T16:31:38.173 回答