跨域问题源于浏览器的同源策略(Same-Origin Policy),该策略限制了不同源(协议、域名、端口任一不同)之间的资源交互。Axios作为HTTP客户端,在浏览器环境中受此策略约束。
最标准的解决方案是后端配置CORS(跨域资源共享)。以下是Node.js Express框架的示例配置:
const express = require('express');
const cors = require('cors');
const app = express();
// 允许所有来源
app.use(cors());
// 或精细控制
app.use(cors({
origin: 'https://yourdomain.com',
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type']
}));
对于Spring Boot后端:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST");
}
}
开发环境下可以使用webpack-dev-server或vite的代理功能:
// vite.config.js
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://backend-server',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '')
}
}
}
})
webpack配置示例:
devServer: {
proxy: {
'/api': {
target: 'http://localhost:3000',
pathRewrite: { '^/api': '' }
}
}
}
直接请求时可能需要设置withCredentials:
axios.get('https://api.example.com/data', {
withCredentials: true
})
对于特殊headers的处理:
axios.post('https://api.example.com/login', data, {
headers: {
'Content-Type': 'application/json',
'X-Custom-Header': 'value'
}
})
对于不支持CORS的老旧API,可以使用JSONP:
function jsonp(url, callbackParam, callback) {
const script = document.createElement('script');
const callbackName = `jsonp_${Date.now()}`;
url += (url.includes('?') ? '&' : '?') + `${callbackParam}=${callbackName}`;
script.src = url;
window[callbackName] = data => {
delete window[callbackName];
document.body.removeChild(script);
callback(data);
};
document.body.appendChild(script);
}
生产环境常用Nginx作为反向代理解决跨域:
server {
listen 80;
server_name frontend.com;
location /api/ {
proxy_pass http://backend.com/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
add_header 'Access-Control-Allow-Origin' '*';
}
}
WebSocket不受同源策略限制,但可能需要设置协议头:
const socket = new WebSocket('wss://api.example.com/ws');
socket.onopen = () => {
socket.send(JSON.stringify({action: 'subscribe'}));
};
对于复杂请求,需要处理OPTIONS预检请求:
// Express中间件示例
app.options('/complex', (req, res) => {
res.setHeader('Access-Control-Allow-Methods', 'PUT')
.setHeader('Access-Control-Allow-Headers', 'Content-Type')
.status(204)
.end();
});
Axios跨域请求的典型错误处理:
axios.get('https://external-api.com/data')
.then(response => {
console.log(response.data);
})
.catch(error => {
if (error.response) {
// 服务器响应非2xx
console.log(error.response.status);
} else if (error.request) {
// 请求已发出但无响应
console.log('No response received');
} else {
// 请求配置错误
console.log('Request setup error', error.message);
}
});
每种解决方案都有其适用场景,开发环境推荐使用代理方案,生产环境应优先采用后端CORS配置。JSONP仅作为最后备选方案,因其安全性较差且只支持GET请求。