简体   繁体   English

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

[英]Change a jquery ajax POST request into a fetch api POST

I have some json data that I have been posting to an API using $.ajax but I would like to update this to use the fetch API. 我有一些使用$ .ajax发布到API的json数据,但我想对其进行更新以使用fetch API。 However I seem to have it setup the Fetch API request ends up returning a 403 so I must be missing something but I can't work it out. 但是,我似乎已经设置了Fetch API请求,但最终返回了403,因此我必须丢失某些内容,但无法解决。

Ajax request: 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)
        }
    });

Fetch attempt (one of many): 尝试获取(众多)之一:

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

I have tried with various different headers, content encoding and sending the data as form data using: 我尝试了各种不同的标题,内容编码并使用以下形式将数据作为表单数据发送:

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

Any help would be great and if you need any more info let me know 任何帮助都会很棒,如果您需要更多信息,请告诉我

Thanks 谢谢

To port an existing jQuery.ajax request to fetch, you need to consider that jQuery always includes cookies for you, but fetch does not. 要移植现有的jQuery.ajax请求以进行提取,您需要考虑到jQuery始终为您提供cookie,而fetch则不包括。

Quoting MDN (emphasis mine): 引用MDN (强调我的名字 ):

Note that the fetch specification differs from jQuery.ajax() in mainly two ways that bear keeping in mind: 请注意,fetch规范与jQuery.ajax()的主要区别在于两个方面:
- The Promise returned from fetch() won't reject on HTTP error status [ ... ] -从fetch()返回的Promise不会拒绝HTTP错误状态[...]
- By default, fetch won't send or receive any cookies from the server, resulting in unauthenticated requests if the site relies on maintaining a user session (to send cookies, the credentials header must be sent) . -默认情况下, 如果站点依赖于维护用户会话(要发送cookie,必须发送凭据标头) ,则fetch不会从服务器发送或接收任何cookie从而导致未经身份验证的请求


Edit: spec has changed since then, so this should no longer be a problem: 编辑:从那时起规格已经改变,所以这应该不再是问题:

Since Aug 25, 2017. The spec changed the default credentials policy to same-origin. 从2017年8月25日开始。 该规范将默认凭据策略更改为同源。 Firefox changed since 61.0b13 . 从61.0b13开始,Firefox进行了更改

So the following (returning to original answer) only applies to "older" browsers. 因此,以下内容(返回原始答案)仅适用于“较旧的”浏览器。

Thanks David Richmond from comments :) 感谢David Richmond的评论:)


So you get 403 (Forbidden) because your API likely relies on cookies for authentication/authorization (even in your case, where you send a csrfmiddlewaretoken , the server-side framework might still expect a cookie with that -- guessing Django?). 因此,您得到403(禁止访问),因为您的API可能依赖于cookie进行身份验证/授权(即使在您的情况下,您发送csrfmiddlewaretoken ,服务器端框架可能仍会希望有一个cookie —猜测是Django?)。

To fix this, add credentials: "same-origin" to your Request (*), like so: 要解决此问题, 请在Request (*)中添加credentials: "same-origin" ,例如:

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

(*) Valid options for credentials are: (*) credentials有效选项是:

  • omit : Never send cookies. omit :永远不要发送cookie。 This is the default (and your problem). 这是默认设置(也是您的问题)。
  • same-origin : Only send cookies if the URL is on the same origin as the calling script. same-origin :仅当URL与调用脚本的起源相同时才发送cookie。
  • include : Always send cookies, even for cross-origin calls. include :始终发送cookie,即使是跨域调用也是如此。

You say: 你说:

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

and

  body: JSON.stringify( payload ) 

JSON Encoding is not the same thing as WWW Form Encoding! JSON编码与WWW表单编码不同!


You also tried 您也尝试过

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

FormData objects are converted to Multipart MIME. FormData对象将转换为Multipart MIME。

Multipart MIME is also not the same as WWW Form Encoded data. 多部分MIME也与WWW表单编码数据不同。

JSON nested inside Multipart MIME even less so. 嵌套在Multipart MIME中的JSON更是如此。


This question describes how to convert an object ( payload ) into a Form Encoded string. 这个问题描述了如何将一个对象( payload )转换成一个Form Encoded字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM