英文:
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;
浏览器网络标签
使用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
没有Body字段
代码
let response = await (
await fetch("http://192.168.1.34:4488/webadmin/generatenewaccesstoken", {
method: "GET",
credentials: "include",
})
).json();
浏览器网络标签
使用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
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
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
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
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
时这样做,它会报错。
如果你尝试在使用XMLHttpRequest
(axios
是其包装器)时这样做,它会忽略你的无意义操作。
当你在HTTP请求中设置请求体时,需要指定请求体的Content-Type
(除非使用某种机制可以推断出它)。
将一个对象传递给axios
的data
属性会使axios
将Content-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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论