Fetch Api vs Axios Api

huangapple go评论74阅读模式
英文:

Fetch Api vs Axios Api

问题

以下是翻译的内容:

如果我在我的React.js前端中使用fetch请求发送API请求,并尝试在fetch请求中添加请求体,浏览器将抛出错误:

“Uncaught (in promise) TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body”

但是,如果我使用Axios而不是fetch API来进行GET请求,这里使用的是data字段,而不是fetch API的body字段。如果在data字段中放入一些内容并发送GET请求,浏览器不会抛出错误。但是服务器不会在请求的正文中获取任何内容。另一个奇怪的行为是,使用带有值的data字段的Axios GET请求时,浏览器还会发送CORS预检请求,这很奇怪,因为这是一个GET请求。

使用Axios

以下是使用存储在httpOnly cookie中的刷新令牌生成新访问令牌的代码。这是Axios的GET请求。

没有Data字段

代码

const response = (
  await axios.request<AuthType>({
    url: "http://192.168.1.34:4488/webadmin/generatenewaccesstoken",
    method: "GET",
    withCredentials: true,
  })
).data;

浏览器网络标签

Fetch Api vs Axios Api

使用Data字段

如果我将Axios的GET请求更改为包含空对象的数据,浏览器将为此Axios请求发送预检请求。

代码

const response = (
  await axios.request<AuthType>({
    url: "http://192.168.1.34:4488/webadmin/generatenewaccesstoken",
    method: "GET",
    withCredentials: true,
    data:{}
  })

浏览器网络标签

以下图像是浏览器的网络标签,您可以看到即使请求方法仍为GET,也会发送预检请求。
Fetch Api vs Axios Api

使用Fetch

没有Body字段

代码

let response = await (
  await fetch("http://192.168.1.34:4488/webadmin/generatenewaccesstoken", {
    method: "GET",
    credentials: "include",
  })
).json();

浏览器网络标签

Fetch Api vs Axios Api

使用Body字段

代码

let response = await (
  await fetch("http://192.168.1.34:4488/webadmin/generatenewaccesstoken", {
    method: "GET",
    credentials: "include",
    body: JSON.stringify({}),
  })
).json();

浏览器网络标签

当使用Axios时,如果我们在GET请求中包含数据字段,即使请求方法为'GET',浏览器也会发送预检请求。但是,当使用方法设置为'GET'的Fetch API时,如果尝试包含body字段,浏览器将不会发送任何内容。此外,我正在使用Edge浏览器。

从上述情况来看,我推测Axios的data字段不仅仅是Axios的body的一个抽象,这两者之间存在根本性的差异。有人能告诉我我的推断是否正确,并解释这种行为的原因吗?

P.S

此外,如果我们将上述端点的方法类型更改为'POST',并且无论我们是使用Axios还是Fetch API,如果在Fetch API的情况下发送POST请求时没有body字段,或在Axios的情况下没有data字段,将不会发送预检请求。根据我所阅读的文章和文档,我理解的是,如果请求不是'GET'或'OPTIONS'之外的其他请求,都会发送预检请求。但在这种情况下,只有'POST'请求不会发送预检请求,它应该包含一个body或data,以便浏览器发送预检请求。

英文:

If i use fetch request to send API request from my react js front end and if i tried to put body in the fetch request. the browser will throw error saying

Uncaught (in promise) TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body

But if i use Axios instead of fetch API to make the get request, here there is data field instead of body of fetch API. and if put something in the data field and send the get request, browser does not throw error. but the server will not get anything in the body of request.Another strange behavior is that in this Axios get request with data field having value,browser also sends a CORS preflight request which is strange because this is a get request.

Using Axios

The following is the code to generate new access token using refresh token stored in httpOnly cookie.This is axios get request

Without Data Field

Code

    const response = (
      await axios.request<AuthType>({
        url: "http://192.168.1.34:4488/webadmin/generatenewaccesstoken",
        method: "GET",
        withCredentials: true,
      })
    ).data;

Browser Network Tab

Fetch Api vs Axios Api

With Data Field

If i change the axios get request to include data with empty object the browser will send a preflight for this axios request.

Code

    const response = (
      await axios.request<AuthType>({
        url: "http://192.168.1.34:4488/webadmin/generatenewaccesstoken",
        method: "GET",
        withCredentials: true,
        data:{}
      })

Browser Network Tab

the following image is the browser's network tab and you can see that preflight is sent even though the request method is still GET
Fetch Api vs Axios Api

Using Fetch

without body field

Code

    let response = await (
      await fetch("http://192.168.1.34:4488/webadmin/generatenewaccesstoken", {
        method: "GET",
        credentials: "include",
      })
    ).json();

Browser Network Tab

Fetch Api vs Axios Api

With body field

Code

    let response = await (
      await fetch("http://192.168.1.34:4488/webadmin/generatenewaccesstoken", {
        method: "GET",
        credentials: "include",
        body: JSON.stringify({}),
      })
    ).json();

Browser Network Tab

Fetch Api vs Axios Api

when using axios,if we include data field in the get request, the browser sends preflight for the request even though request method is 'GET'. but when using fetch Api with method set to 'GET if we try to include the body field. the browser will send nothing. Also I'am using edge browser

From the above, I' am inferring that data of Axios is not just a abstraction of body of axios, there is a fundamental difference in these two. Can someone tell me if my inference is correct and explain the reason for this behavior .

P.S

Also if we change the above endpoint method type to 'POST'. and whatever we are using axios or fetch api. if we are sending the post request without body field in the case of fetch api or without data field in the case of axios, the preflight request will not be send. From articles and documentation i have read,what i understood was if the request is request other than 'GET' or 'OPTION' a preflight request will be send. but in this case preflight will not be send for just a 'POST' request, it should contain a body or data for the browser to send preflight.

答案1

得分: 2

不可以在GET请求中设置请求体。

如果你尝试在使用fetch时这样做,它会报错。

如果你尝试在使用XMLHttpRequestaxios是其包装器)时这样做,它会忽略你的无意义操作。


当你在HTTP请求中设置请求体时,需要指定请求体的Content-Type(除非使用某种机制可以推断出它)。

将一个对象传递给axiosdata属性会使axiosContent-Type设置为application/json

带有Content-Type: application/json的跨域请求需要进行预检请求。

XMLHttpRequest不会忽略axios设置的Content-Type,但会忽略axios设置的请求体。

这会导致进行预检请求,如果成功,将使用Content-Type但没有请求体进行实际请求。

英文:

You may not set a body on a GET request.

If you try to do that with fetch then it will complain at you.

If you try to do that with XMLHttpRequest (which axios is a wrapper around) then it will ignore your nonsense.


When you set a body on an HTTP request, you need to specify the Content-Type of that body (unless you set it using a mechanism which from which it can be inferred).

Passing an object to data on axios will make axios set the Content-Type to application/json.

Cross-origin requests with Content-Type: application/json require a preflight request.

XMLHttpRequest won't ignore axios setting the Content-Type but it will ignore axios setting the request body.

This results in a preflighted request which, if successful, will make the real request with a content-type but no content in the body.

答案2

得分: 1

MDN 很好地解释了CORS的工作原理,什么是简单请求,以及哪些请求需要预检请求

GET请求不能有请求体,但可以在URL中包含查询参数。
POST请求也可以在URL中包含查询参数,同时还可以有请求体(可选)。
即使你向Axios提供了data,如果请求是GET,Axios也不会向XHR添加请求体。

英文:

MDN explains pretty well how CORS works, what is a simple request and which requests need preflight

GET requests can not have a body - but they can have query parameters in the URL.
POST requests can have query parameters in the URL, too - but they also can have a body (optionally).
Even if you provide data to Axios - if the request is GET then Axios will not add a body to the XHR.

huangapple
  • 本文由 发表于 2023年8月9日 14:59:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76865322-2.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定