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

Posted

技术标签:

【中文标题】将 jquery ajax POST 请求更改为 fetch api POST【英文标题】:Change a jquery ajax POST request into a 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 格式的请求。 【参考方案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,即使是跨域调用。

【讨论】:

注意:规范在 2017 年发生了变化,现代浏览器现在默认为 same-origin。 developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch 谢谢大卫,相应地修改了答案:)【参考方案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) 转换为表单编码字符串。

【讨论】:

以上是关于将 jquery ajax POST 请求更改为 fetch api POST的主要内容,如果未能解决你的问题,请参考以下文章

将 Node.js GET /POST 请求更改为 Ajax

带有 ajax 和 jquery serialize() 的 POST 请求丢失了值

AJAX 请求正文为空(无 jQuery)

将 EXTJS AJAX 方法从 GET 更改为 POST 将导致任何性能问题

jquery tokenInput如何将ajax调用url动态更改为脚本

Jquery 对ajax请求如何实现非异步