从昨晚一直在试,明明之前用的封装的axios发送请求给其他的后端(springboot)是可以的,但昨天用了新项目的后端(node.js)就不行。
之前用了代理,所以浏览器发送的post请求不会被拦截,但是昨天因为项目的接口没有统一前缀的原因(比如都用admin)开头,所以直接把baseUrl写成http://127.0.0.1:7123了,但是发送post请求出错,我还以为前端写错了,后面发现post请求的话总不行,报是跨域的问题,但是get的话就可以,查了一下,get的话请求参数会被放在query里面,post请求会跨域,所以node那边得写成 res.header("Access-Control-Allow-Headers", "X-Requested-With,Content-Type");原来的话是 res.header("Access-Control-Allow-Headers", "X-Requested-With")
解决跨域问题的写法:(记得加Content-Type)
res.header("Access-Control-Allow-Headers", "X-Requested-With,Content-Type");
总结,如果post用application/x-www-form-urlencoded,得格式化数据
// 2. 使用 URLSearchParams 格式化数据
const formData = new URLSearchParams();
for (const key in data1) {
formData.append(key, data1[key]);
}
// 3. 发送 POST 请求
axios.post('http://127.0.0.1:7123/admin/login', formData, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
})
如果post用json,则不用,因为axios会自动帮我们json化
const data1 = {
account: 'value1',
password: 'value2'
};
// 2. 使用 URLSearchParams 格式化数据
const formData = new URLSearchParams();
for (const key in data1) {
formData.append(key, data1[key]);
}
// 3. 发送 POST 请求
axios.post('http://127.0.0.1:7123/admin/login', data1, {
headers: {
'Content-Type': 'application/json',
},
})
上面的例子是不封装的情况,如果是封装的话,如果传进来dataType:"json"格式,按照以下代码可以执行,因为这时候Content-Type为application/json,后端用req.body可以获取到
import axios from "axios"
import { ElLoading } from 'element-plus'; // 正确的拼写是 ElLoading,不是 Lloading
import router from '@/router'
import Message from '../utils/Message'
import { getCurrentInstance } from "vue";
const contentTypeForm='application/x-www-form-urlencoded;charset-UTF-8'
const contentTypeJson='application/json'
const contentTypeMulti ='multipart/form-data'
let loading=null;
import VueCookies from 'vue-cookies';
const instance=axios.create({
baseURL:'http://127.0.0.1:7123', //请求后端接口的baseUrl
timeout:10*1000, //设置请求的超时时间
})
//请求前拦截器
instance.interceptors.request.use(
(config)=>{
const data= VueCookies.get("loginInfo");
if(data)
{
const token=data.token;
if (token) {
config.headers.token = token
}
}
if(config.showLoading)
{
loading=ElLoading.service({
lock:true,
text:'加载中……',
background:'rgba(0,0,0,0.7)',
})
}
return config;
},
(error)=>{
if(config.showLoading&&loading)
{
loading.close();
}
Message.error("请求发送失败");
return Promise.reject("请求发送失败");
}
);
//请求后拦截器
instance.interceptors.response.use(
(response)=>{
const{showLoading,errorCallback,showError=true}=response.config;
if(showLoading&&loading)
{
loading.close();
}
//正常请求
if (response.status==200)
{
return response.data;
}
},
(error)=>{
const { showLoading, errorCallback, showError = true } = error.config;
if (showLoading && loading) {
loading.close();
}
(error.response);
if(error.response)
{
const responseData = error.response;
if (responseData.status == 401) {
setTimeout(() => {
router.push("/login")
}, 2000);
return Promise.reject({ showError: true, msg: "登录超时" });
}
}
if(error.config.showLoading&&loading)
{
loading.close();
}
return Promise.reject({showError:true,msg:"网络异常"})
}
);
const request = ({ url, method, params, dataType, showLoading = true, errorCallback, showError = true, data }) => {
// 设置默认 Content-Type
const contentType = method === 'upload' ? contentTypeMulti : (dataType === 'json' ? contentTypeJson : contentTypeForm);
// 处理请求数据
const requestData = method === 'upload' ? { data } : (method === 'get' || method === 'delete' ? { params } : { data: params });
// 上传请求强制使用 POST 方法
if (method === 'upload') {
method = 'post';
}
return instance.request({
method,
url,
...requestData,
headers: {
'Content-Type': contentType,
'X-Requested-With': 'XMLHttpRequest',
},
showLoading,
}).catch(error => {
console.error(error);
if (showError) {
Message.error(error.msg || 'An error occurred');
}
if (errorCallback) {
errorCallback(error);
}
return null;
});
};
export default request;
但是如果不传入dataType的话,默认为application/x-www-form-urlencoded的话,就要注意了,
const requestData = method === 'upload' ? { data } : (method === 'get' || method === 'delete' ? { params } : { data: params });这行代码得改为 const requestData = method === 'upload' ? { data } : (method === 'get' || method === 'delete' ? { params } : { params });因为application/x-www-form-urlencoded是以 类似‘name=edward&age=25’ 这样的形式放在参数中,后端得用req.query才能获取数据,req.body获取不到。
但是如果要在req.body获取得到的话,那么
import qs from 'qs';
const request = axios.create({
baseURL: process.env.BASE_URL,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
}
})
request.interceptors.request.use(config => {
if (config.method === 'post') {
config.data = qs.stringify(config.data)
}
return config;
})
记得要qs序列化。!!!!!!!!!!!!!!!!!!!!!!!!!
暂时先写这么多,后续有更清晰的理解再补充,哪里写错还请路过的大佬斧正。
贴一下原贴
post请求头设置成application/json时的跨域错误_指定contenttype为json后报跨域-CSDN博客