英文:
Fetch Api vs Axios Api
问题
如果我在React.js前端使用fetch请求发送API请求,并尝试在fetch请求中添加body,浏览器会抛出错误:
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请求,浏览器不会抛出错误,但服务器将无法在请求的body中获取任何内容。另一个奇怪的行为是,在具有值的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请求更改为在空对象中包含data,浏览器将为此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请求中包含data字段,即使请求方法为'GET',浏览器也会发送预检。但是,当使用将方法设置为'GET'的fetch API并尝试包含body字段时,浏览器将不发送任何内容。另外,我正在使用Edge浏览器。
从上面的内容中,我推断Axios的data不仅仅是对axios的body的抽象,这两者之间存在根本的区别。有人可以告诉我我的推断是否正确,并解释这种行为的原因吗?
P.S
另外,如果我们将上述端点的方法类型更改为'POST',并且无论我们使用axios还是fetch API,如果我们在fetch API的情况下发送不带body字段的POST请求,或者在axios的情况下发送不带data字段的POST请求,预检请求都不会被发送。根据我阅读的文章和文档,我了解到,如果请求不是'GET'或'OPTION',则会发送预检请求。但在这种情况下,仅仅一个'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
设置的请求体。
这将导致进行预检请求,如果成功,将会发送一个带有内容类型但没有请求体的真实请求。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论