将 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 请求丢失了值
将 EXTJS AJAX 方法从 GET 更改为 POST 将导致任何性能问题