当前位置:首页 > 问答 > 正文

跨域|接口开发 node.js实现数据接口及解决跨域问题的方法

Node.js实现数据接口及解决跨域问题的方法

2025年7月最新消息:随着Web应用架构日益复杂,跨域请求已成为前端开发中的常见需求,最新Node.js 22版本进一步优化了内置HTTP模块性能,使得开发者能够更高效地构建跨域友好的API服务,据统计,超过78%的企业级应用需要处理跨域数据交互问题。

为什么需要解决跨域问题

跨域问题源于浏览器的同源策略(Same-Origin Policy),这是现代浏览器最基本的安全功能之一,当你的前端页面运行在http://a.com,而尝试请求http://b.com的API时,浏览器就会阻止这个请求。

在实际开发中,前后端分离架构非常普遍:

  • 前端可能运行在http://localhost:3000
  • 后端API可能在http://localhost:8000
  • 生产环境前端可能部署在CDN,与API不同域

Node.js基础接口开发

我们先从最基础的Node.js HTTP服务器开始:

跨域|接口开发 node.js实现数据接口及解决跨域问题的方法

const http = require('http');
const server = http.createServer((req, res) => {
  if (req.url === '/api/data' && req.method === 'GET') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ message: "基础接口响应成功" }));
  } else {
    res.writeHead(404);
    res.end('Not Found');
  }
});
server.listen(8000, () => {
  console.log('服务器运行在 http://localhost:8000');
});

这个简单例子创建了一个监听8000端口的服务器,当访问/api/data时会返回JSON数据。

Express框架实现RESTful API

实际开发中我们更常用Express这样的框架:

const express = require('express');
const app = express();
// 中间件:解析JSON请求体
app.use(express.json());
// 示例数据
let products = [
  { id: 1, name: '商品A', price: 100 },
  { id: 2, name: '商品B', price: 200 }
];
// GET /api/products
app.get('/api/products', (req, res) => {
  res.json(products);
});
// POST /api/products
app.post('/api/products', (req, res) => {
  const newProduct = req.body;
  products.push(newProduct);
  res.status(201).json(newProduct);
});
app.listen(8000, () => {
  console.log('API服务运行在 http://localhost:8000');
});

解决跨域问题的几种方法

CORS中间件(推荐方案)

const cors = require('cors');
// 允许所有来源
app.use(cors());
// 或者配置特定来源
app.use(cors({
  origin: 'http://localhost:3000',
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization']
}));

手动设置响应头

如果不使用cors中间件,可以手动设置:

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  // 处理预检请求(OPTIONS)
  if (req.method === 'OPTIONS') {
    return res.sendStatus(200);
  }
  next();
});

代理服务器方案

在开发环境中,前端框架通常支持代理配置:

// vite.config.js (Vite项目)
export default {
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:8000',
        changeOrigin: true,
        rewrite: path => path.replace(/^\/api/, '')
      }
    }
  }
}

JSONP(仅限GET请求)

虽然现在很少用,但在某些特殊场景可能有用:

跨域|接口开发 node.js实现数据接口及解决跨域问题的方法

app.get('/api/jsonp', (req, res) => {
  const callback = req.query.callback;
  const data = { message: "JSONP响应" };
  res.type('text/javascript');
  res.send(`${callback}(${JSON.stringify(data)})`);
});

处理复杂跨域场景

带凭证的请求

当请求需要携带cookie或认证信息时:

app.use(cors({
  origin: 'http://localhost:3000',
  credentials: true
}));
// 前端也需要配置
// fetch(url, { credentials: 'include' })

自定义中间件处理复杂逻辑

const allowOrigins = ['http://localhost:3000', 'https://myapp.com'];
app.use((req, res, next) => {
  const origin = req.headers.origin;
  if (allowOrigins.includes(origin)) {
    res.header('Access-Control-Allow-Origin', origin);
    res.header('Access-Control-Allow-Credentials', 'true');
  }
  if (req.method === 'OPTIONS') {
    res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
    res.status(200).end();
    return;
  }
  next();
});

生产环境最佳实践

  1. *不要使用``通配符**:生产环境应明确指定允许的域名
  2. 限制HTTP方法:只允许必要的HTTP方法
  3. 设置缓存时间:减少预检请求次数
    res.header('Access-Control-Max-Age', '86400'); // 24小时
  4. 结合环境变量
    const allowedOrigins = process.env.NODE_ENV === 'production'
      ? ['https://myapp.com']
      : ['http://localhost:3000'];

常见问题排查

  1. 预检请求失败:确保正确处理OPTIONS方法
  2. 响应头未生效:检查中间件顺序,确保在路由之前
  3. 凭证问题:前后端都需要配置credentials选项
  4. 缓存问题:开发时可禁用浏览器缓存或设置no-cache

完整示例代码

const express = require('express');
const cors = require('cors');
const app = express();
// 配置
const PORT = 8000;
const isProduction = process.env.NODE_ENV === 'production';
const allowedOrigins = isProduction
  ? ['https://myapp.com']
  : ['http://localhost:3000'];
// 中间件
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// CORS配置
app.use(cors({
  origin: (origin, callback) => {
    if (!origin || allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error('不允许的请求来源'));
    }
  },
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization']
}));
// 路由
app.get('/api/user', (req, res) => {
  res.json({ name: '张三', age: 30 });
});
app.post('/api/login', (req, res) => {
  const { username, password } = req.body;
  // 验证逻辑...
  res.json({ token: '模拟token', user: { username } });
});
// 错误处理
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).json({ error: err.message });
});
// 启动服务器
app.listen(PORT, () => {
  console.log(`服务器运行在 http://localhost:${PORT}`);
});

Node.js提供了多种灵活的方式来解决跨域问题,从简单的CORS头设置到复杂的代理服务器方案,选择哪种方案取决于你的具体需求:

  1. 开发环境:可以使用宽松的CORS配置或代理
  2. 生产环境:应该严格限制允许的来源和方法
  3. 特殊场景:可能需要组合多种方案

跨域问题本质是浏览器安全策略,服务端只是通过响应头告诉浏览器哪些跨域请求是被允许的,掌握这些技术后,你就能轻松构建前后端分离的现代化Web应用了。

发表评论