【问题标题】:Change a jquery ajax POST request into a fetch api POST将 jquery ajax POST 请求更改为 fetch api POST
【发布时间】:2017-11-09 18:44:07
【问题描述】:

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

Ajax 请求:

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

获取尝试(许多之一):

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())

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

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
});
...

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

谢谢

【问题讨论】:

  • 为什么不标头:headers: { 'Content-Type': 'application/json' }
  • 我试过了,但似乎没有用。我会再试一次,也许是其他事情搞砸了!
  • @sideshowbarker — 工作 (jQuery) 代码使用 www 表单编码。没有任何迹象表明服务器支持 JSON 格式的请求。

标签: javascript ajax fetch-api


【解决方案1】:

要将现有的 jQuery.ajax 请求移植到获取,您需要考虑到 jQuery 始终为您包含 cookie,但 fetch 不包含。

Quoting MDN(强调我的):

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


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

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

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

感谢 cmets 的 David Richmond :)


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

要解决此问题,add credentials: "same-origin" to your Request (*),如下所示:

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

(*) credentials 的有效选项是:

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

【讨论】:

【解决方案2】:

你说:

'Content-Type': 'application/x-www-form-urlencoded'

 body:  JSON.stringify( payload )

JSON 编码与 WWW 表单编码不同!


你也试过

form_data.append( "json", JSON.stringify( payload ) );

FormData 对象被转换为 Multipart MIME。

Multipart MIME 也不同于 WWW 表单编码数据。

JSON 嵌套在 Multipart MIME 中更是如此。


This question 描述了如何将对象 (payload) 转换为表单编码字符串。

【讨论】:

    猜你喜欢
    • 2018-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-12
    • 1970-01-01
    • 2016-11-28
    • 2018-09-14
    相关资源
    最近更新 更多