在 Express.js 中解决跨域请求问题的完整指南

跨域请求是指在一个域名下的网页获取另一个域名下的资源。在前端开发中,经常会遇到跨域请求的问题。在 Express.js 中,我们可以通过设置响应头来解决跨域请求问题。

什么是跨域请求?

在浏览器中,同源策略是一种安全机制,它限制了一个源(协议、域名、端口)的脚本只能访问同源下的资源。如果不同源,就会出现跨域请求问题。例如,一个页面在 http://example.com 下,想要获取 http://api.example.com 下的数据,就会触发跨域请求。

解决跨域请求问题的方法

JSONP

JSONP(JSON with Padding)是解决跨域请求的一种方法。它利用了 script 标签可以跨域请求的特性,通过在请求参数中添加一个回调函数名,服务端返回一个函数调用,并将数据作为参数传入该函数中。例如:

function jsonp(url, callback) {
  const script = document.createElement('script');
  script.src = url + '&callback=' + callback;
  document.body.appendChild(script);
}

jsonp('http://api.example.com/data', function(data) {
  console.log(data);
});

服务端返回的数据格式如下:

callbackFunctionName({
  data: 'some data'
})

JSONP 的缺点是只支持 GET 请求,并且容易受到 XSS 攻击。

CORS

CORS(Cross-Origin Resource Sharing)是 W3C 标准,它允许浏览器向跨域服务器发送 AJAX 请求,并且允许服务器返回响应。在服务端,我们需要设置响应头来允许跨域请求。例如,在 Express.js 中,我们可以使用 cors 中间件来设置响应头:

const express = require('express');
const cors = require('cors');

const app = express();

app.use(cors());

app.get('/data', (req, res) => {
  res.send('some data');
});

app.listen(3000, () => {
  console.log('Server is running at http://localhost:3000');
});

上面的代码中,cors 中间件会自动设置 Access-Control-Allow-Origin 和 Access-Control-Allow-Methods 响应头,允许任何域名的请求,并且允许 GET、POST、PUT、DELETE 方法。

如果需要更细粒度的控制,可以手动设置响应头。例如:

const express = require('express');

const app = express();

app.get('/data', (req, res) => {
  res.set('Access-Control-Allow-Origin', 'http://example.com');
  res.set('Access-Control-Allow-Methods', 'GET, POST');
  res.set('Access-Control-Allow-Headers', 'Content-Type');
  res.send('some data');
});

app.listen(3000, () => {
  console.log('Server is running at http://localhost:3000');
});

上面的代码中,我们手动设置了 Access-Control-Allow-Origin、Access-Control-Allow-Methods 和 Access-Control-Allow-Headers 响应头,允许 http://example.com 域名下的 GET 和 POST 请求,并且允许 Content-Type 请求头。

总结

跨域请求是前端开发中常见的问题,我们可以使用 JSONP 或 CORS 来解决。在 Express.js 中,我们可以使用 cors 中间件来设置响应头,也可以手动设置响应头。不同的业务场景需要不同的设置,需要根据实际情况来选择合适的方法。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65bca498add4f0e0ff53a0c9