使用Axios+React发送POST请求遭遇CORS错误求助
问题描述
我想用Axios和React发送POST请求,但点击提交按钮后遇到跨域错误。已经查看MDN相关文档,也给Axios headers添加了默认配置,但网络面板仍显示如下错误:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://127.0.0.1:8000/announcement/create/ (Reason: CORS request did not succeed). Status code: (null)
且没有服务器响应,以下是我的代码:
export default function NewRequestForm(props) { const [country, setCountry] = useState(''); const [city, setCity] = useState(''); const [arrival_date, setArrivalDate] = useState('') const [departure_date, setDepartureDate] = useState(''); const [arrival_date_is_flexible, setIsArrDateFelxible] = useState(false); const [departure_date_is_flexible, setIsDptDateFelxible] = useState(false); const [message, setMessage] = useState(''); const handleChangeCountry = (event) => { setCountry(event.target.value); } const handleChangeCity = (event) => { setCity(event.target.value); } const handleChangeArrivalDate = (event) => { setArrivalDate(event.target.value); } const handleChangeDepartureDate = (event) => { setDepartureDate(event.target.value); } const handleChangeMessage = (event) => { setMessage(event.target.value); } const handleChangeIsArrDateFlexible = (event) => { setIsArrDateFelxible(event.target.checked); }; const handleChangeIsDptDateFlexible = (event) => { setIsDptDateFelxible(event.target.checked); }; const [values, setValues] = useState(intialState); const handleChange = (prop) => (event) => { setValues({ ...values, [prop]: event.target.value, }); }; // Data Validation and Send to Backend axios.defaults.headers.post['Content-Type'] ='application/json;charset=utf-8'; axios.defaults.headers.post['Access-Control-Allow-Origin'] = '*'; const onSubmit = async (e) => { e.preventDefault(); axios.post("http://127.0.0.1:8000/announcement/create/", { country : country, city : city, arrival_date: arrival_date, departure_date: departure_date, arrival_date_is_flexible: arrival_date_is_flexible, departure_date_is_flexible: departure_date_is_flexible, message: message, }) .then((res) =>{ console.log(res.data) }) .catch((error) => { if (!error?.response) { console.log("No Server Response"); } else if (error?.code === AxiosError.ERR_NETWORK) { console.log("Network Error"); } else if (error.response?.status === 404) { console.log("404 - Not Found"); } else if (error?.code) { console.log("Code: " + error.code); } else { console.log("Unknown Error"); } }); } const handleClose = () => { props.setOpen(false); }; const onCancle = () => { props.setRequestData({}); setValues(intialState); }; return ( <Dialog open={props.open} onClose={handleClose} aria-labelledby="responsive-dialog-title" > <Box className="add-request-center-element" sx={{ m: 2, maxWidth: "100%" }}> <Box className="request-management-add-request"> <Grid container spacing={3}> <Grid item xl={12} lg={12} md={12} sm={12} xs={12}> <Box className="add-request-center-element"> <form className="add-request-form"> <Box> <Box className="add-request-center-element form-title"> <h1 style={{ marginBottom: "3rem"}}>Enter The Trip Info</h1> </Box> <Grid container spacing={2}> {/* country name */} <Grid item xl={6} lg={6} md={6} sm={12} xs={12}> <FormControl sx={{width: "100%"}}> <TextField id="new-request-country" name="country" type="text" label="Country" variant="outlined" inputProps={{maxLength: 20}} onChange={handleChangeCountry} required/> </FormControl> </Grid> {/* city name */} <Grid item xl={6} lg={6} md={6} sm={12} xs={12}> <FormControl sx={{width: "100%"}}> <TextField id="new-request-city" name="city" type="text" label="City" variant="outlined" inputProps={{maxLength: 20}} onChange={handleChangeCity} required/> </FormControl> </Grid> {/* Arrival Date */} <Grid item xl={6} lg={6} md={6} sm={12} xs={12}> <FormControl sx={{ mt: 1 }} style={{ width: "100%" }} className="rtlDatePicker"> <DatePicker animations={[ transition({ from: 35, transition: "all 400ms cubic-bezier(0.335, 0.010, 0.030, 1.360)", }) ]} style={{ width: "100%"}} inputClass="new-request-date-picker-input" className="date-picker" format="YYYY/MM/DD" name="arrival_date" calendarPosition="bottom-end" placeholder="Arrival Date *" hideOnScroll editable // onChange={handleChangeArrivalDate} /> {/* arrival date is flexible */} <FormControlLabel control={<Checkbox value="arrivaldateisflexible" color="primary" onChange={handleChangeIsArrDateFlexible} />} label="Arrival date is flexible" /> </FormControl> </Grid> {/* Departure Date */} <Grid item xl={6} lg={6} md={6} sm={12} xs={12}> <FormControl sx={{ mt: 1 }} style={{ width: "100%" }} className="rtlDatePicker"> <DatePicker animations={[ transition({ from: 35, transition: "all 400ms cubic-bezier(0.335, 0.010, 0.030, 1.360)", }) ]} style={{ width: "100%"}} inputClass="new-request-date-picker-input" className="date-picker" format="YYYY/MM/DD" name="departure_date" calendarPosition="bottom-end" placeholder="Departure Date *" hideOnScroll editable required minDate={values.arrival_date} // onChange={handleChangeDepartureDate} /> </FormControl> {/* departure date is flexible */} <FormControlLabel control={<Checkbox value="arrivaldateisflexible" color="primary" onChange={handleChangeIsDptDateFlexible} />} label="Departure date is flexible" /> </Grid> {/* Travelers count */} {/* message */} <Grid item xl={12} lg={12} md={12} sm={12} xs={12}> <FormControl sx={{width: "100%"}}> <TextField id="new-request-message" name="message" type="text" label="Message" variant="outlined" multiline fullWidth="true" size="medium" rows={10} maxRows={10} onChange={handleChangeMessage} /> </FormControl> </Grid> {/* Confirm Button */} <Grid item xl={6} lg={6} md={6} sm={12} xs={12}> <Button variant="contained" sx={{ width: "100%" }} type="submit" onClick={onSubmit} > Submit the information </Button> </Grid> {/* Quit */} <Grid sx={{ display: "flex", justifyContent: "flex-end" }} item xl={6} lg={6} md={6} sm={12} xs={12}> <Button variant="outlined" sx={{ width: "1000%", }} type="submit" onClick={onCancle} > Quit </Button> </Grid> </Grid> </Box> </form> </Box> </Grid> </Grid> </Box> </Box> </Dialog> ); }
解决方案
核心问题:前端设置Access-Control-Allow-Origin无效
你在Axios里添加的Access-Control-Allow-Origin是后端返回给浏览器的响应头,不是前端要发送的请求头。浏览器的跨域验证逻辑是检查后端有没有返回正确的CORS响应头,所以前端加这行完全没用,反而可能干扰请求。
方案1:后端配置CORS(生产环境必须)
跨域问题本质是浏览器的安全限制,必须在后端配置允许你的前端域名访问。根据后端框架不同,配置方式如下:
- Django:安装
django-cors-headers,在settings.py中添加配置:INSTALLED_APPS = [ ... 'corsheaders', ... ] MIDDLEWARE = [ ... 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', ... ] # 允许你的React开发服务器地址 CORS_ALLOWED_ORIGINS = [ "http://localhost:3000", "http://127.0.0.1:3000", ] # 允许POST等请求方法 CORS_ALLOW_METHODS = [ "POST", "GET", "OPTIONS", ] - Flask:安装
flask-cors,初始化时配置:from flask import Flask from flask_cors import CORS app = Flask(__name__) # 指定允许的前端域名 CORS(app, origins=["http://localhost:3000"]) - Express:安装
cors中间件,配置规则:const express = require('express'); const cors = require('cors'); const app = express(); app.use(cors({ origin: 'http://localhost:3000', // 允许的前端域名 methods: ['POST', 'GET', 'OPTIONS'] // 允许的请求方法 }));
方案2:React开发环境代理(仅开发阶段用)
如果只是开发测试,可以用React内置的代理功能绕开跨域限制:
- 在React项目的
package.json中添加一行:"proxy": "http://127.0.0.1:8000" - 修改Axios请求的URL为相对路径:
axios.post("/announcement/create/", { ... })
这样开发服务器会自动把请求转发到后端,浏览器会认为是同源请求,不会触发跨域限制。
前端代码优化
- 删掉
axios.defaults.headers.post['Access-Control-Allow-Origin'] = '*';,这行代码完全无效。 - 检查DatePicker组件的
onChange事件,你现在注释掉了onChange={handleChangeArrivalDate}和onChange={handleChangeDepartureDate},会导致arrival_date和departure_date为空值,提交时会有数据问题,记得绑定对应的处理函数。
内容的提问来源于stack exchange,提问作者Aylin Naebzadeh
相关产品推荐
相关产品推荐

