将 jquery ajax POST 请求更改为 fetch api POST

Des*_*023 5 javascript ajax fetch-api

我有一些 json 数据,已使用 $.ajax 发布到 API,但我想更新它以使用 fetch API。不过,我似乎设置了 Fetch API 请求最终返回 403,所以我一定错过了一些东西,但我无法解决。

阿贾克斯请求:

$.ajax({
        type: 'POST',
        url: url,
        data: {
            'title': data.title,
            'body': data.body,
            'csrfmiddlewaretoken': csrf_token,
            'request_json': true
        },
        success: function (data) {
            console.log(data)
        }
    });
Run Code Online (Sandbox Code Playgroud)

获取尝试(众多尝试之一):

let payload = {
    'title': data.title,
    'body': data.body,
    'csrfmiddlewaretoken': csrf_token,
    'request_json': true
}

let request = new Request(url, {
    method: 'post',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body:  JSON.stringify( payload )
});

fetch(request)
        .then((response) => {
            if (!response.ok) {
                throw Error(response.statusText);
            }
            return response;
        })
        .then((response) => response.json())
Run Code Online (Sandbox Code Playgroud)

我尝试过各种不同的标头、内容编码并使用以下方法将数据作为表单数据发送:

let form_data = new FormData();
form_data.append( "json", JSON.stringify( payload ) );

let request = new Request(url, {
    method: 'post',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body:  form_data
});
...
Run Code Online (Sandbox Code Playgroud)

任何帮助都会很棒,如果您需要更多信息,请告诉我

谢谢

Hug*_* M. 3

要将现有jQuery.ajax请求移植到 fetch,您需要考虑 jQuery 始终为您包含 cookie,但fetch事实并非如此。

\n\n

引用MDN(强调我的):

\n\n
\n

请注意,fetch 规范与 jQuery.ajax() 的不同之处主要在于以下两个方面,请记住:
\n - 从 fetch() 返回的 Promise won\xe2\x80\x99t拒绝 HTTP 错误状态 [ ... ]
\ n - 默认情况下,fetch 不会从服务器发送或接收任何 cookie,如果站点依赖于维护用户会话,则会导致未经身份验证的请求(要发送 cookie,必须发送凭据标头)

\n
\n\n
\n\n

编辑:从那时起规范已经改变,所以这应该不再是问题:

\n\n
\n

自 2017 年 8 月 25 日起。规范将默认凭据策略更改为同源。Firefox 自 61.0b13 起发生了变化

\n
\n\n

因此,以下内容(返回原始答案)仅适用于“旧版”浏览器。

\n\n

感谢大卫·里士满的评论:)

\n\n
\n\n

所以你会得到403(禁止),因为你的 API 可能依赖于 cookie 进行身份验证/授权(即使在你的情况下,你发送一个csrfmiddlewaretoken,服务器端框架可能仍然需要一个 cookie - 猜猜 Django?)。

\n\n

要解决此问题,请添加credentials: "same-origin"到您的Request(*),如下所示:

\n\n
let request = new Request(url, {\n    method: \'post\',\n    credentials: \'same-origin\',\n    headers: {\n      \'Content-Type\': \'application/json\'\n    },\n    body: JSON.stringify(payload)\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

(*) 有效选项为credentials

\n\n
    \n
  • omit:切勿发送 cookie。这是默认设置(也是您的问题)。
  • \n
  • same-origin:仅当 URL 与调用脚本同源时才发送 cookie。
  • \n
  • include:始终发送 cookie,即使是跨源调用。
  • \n
\n