# 跨域响应头问题

URL: https://caijiao.org/koa/faq/cors
Source: docs/koa/faq/cors.md
Description: 本文讨论了 Koa 中如何处理跨域问题，并配置响应头以支持跨域请求，确保前后端分离应用的正常通信。

在开发前后端分离的应用时，跨域请求是一个常见问题。浏览器的同源策略会限制不同源之间的请求，尤其是在开发环境中，前端和后端通常运行在不同的端口或域上。为了解决这个问题，我们需要[配置跨域](/koa/advanced/cors)资源共享（CORS）相关的响应头。

## 1. 什么是 CORS

跨域资源共享（CORS，Cross-Origin Resource Sharing）是一种机制，它允许服务器通过 HTTP 头部的配置来指示浏览器允许哪些源的请求访问资源。具体来说，CORS 是通过设置特定的 HTTP 响应头来允许跨域请求。

### 关键 CORS 响应头：

- **Access-Control-Allow-Origin**：指定允许的跨域源。
- **Access-Control-Allow-Methods**：指定允许的 HTTP 方法（如 `GET`, `POST`, `PUT`, `DELETE` 等）。
- **Access-Control-Allow-Headers**：指定允许的请求头字段。
- **Access-Control-Allow-Credentials**：指示是否允许携带认证信息（如 Cookies）。
- **Access-Control-Max-Age**：指定预检请求的结果可以缓存多长时间。

## 2. 如何在 Koa 中处理 CORS

在 Koa 中，处理 CORS 需要通过设置相应的响应头。最简单的方法是使用 `koa-cors` 中间件，它可以帮助你自动设置必要的 CORS 响应头。

### 安装 koa-cors

```bash
npm install koa-cors
````

### 配置 CORS

在 Koa 应用中使用 `koa-cors` 中间件，允许来自所有域的请求：

```javascript
const Koa = require('koa');
const cors = require('koa-cors');
const app = new Koa();

app.use(cors());  // 允许所有来源的跨域请求

app.use(ctx => {
  ctx.body = 'Hello, World!';
});

app.listen(3000);
```

这将自动为所有请求添加适当的 CORS 响应头。

## 3. 自定义 CORS 配置

你还可以自定义 CORS 配置，允许特定的来源、请求方法或头信息。例如，允许来自特定域名的请求，并支持 `GET` 和 `POST` 方法：

```javascript
const Koa = require('koa');
const cors = require('koa-cors');
const app = new Koa();

app.use(cors({
  origin: 'http://example.com',  // 允许来自 http://example.com 的请求
  methods: ['GET', 'POST'],     // 只允许 GET 和 POST 方法
  allowedHeaders: ['Content-Type', 'Authorization'], // 允许的请求头
  credentials: true,  // 允许携带 cookies
}));

app.use(ctx => {
  ctx.body = 'Hello, World!';
});

app.listen(3000);
```

这样，只有来自 `http://example.com` 的请求才会被允许，并且请求方法和请求头的配置会受到限制。

## 4. 预检请求

当你发送跨域请求时，某些请求（如 `POST` 请求带有自定义头部或复杂数据）会先发送一个 `OPTIONS` 请求，称为预检请求（Preflight Request）。服务器需要响应此请求并返回相应的 CORS 头部。

### 处理预检请求

如果你的应用需要处理预检请求，可以通过以下方式配置：

```javascript
app.use(async (ctx, next) => {
  if (ctx.method === 'OPTIONS') {
    ctx.status = 200;
    ctx.set('Access-Control-Allow-Origin', '*');
    ctx.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
    ctx.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
    return;
  }
  await next();
});
```

这种方法会在收到预检请求时，返回适当的响应头，确保跨域请求可以正常进行。

## 5. 错误处理与调试

在调试跨域问题时，确保浏览器的开发者工具中查看请求和响应的头部信息，特别是 `Access-Control-Allow-Origin` 和其他 CORS 相关的响应头。如果遇到跨域错误，可以参考以下步骤排查：

* **确认源**：检查请求来源域名是否在允许的跨域列表中。
* **预检请求**：确保服务器对 `OPTIONS` 请求进行了正确的响应。
* **方法与头部**：检查请求方法（如 `GET`, `POST`）和请求头（如 `Content-Type`, `Authorization`）是否被允许。

## 6. 总结

* CORS 是一种机制，通过设置响应头，允许跨域请求访问服务器资源。
* Koa 中可以使用 `koa-cors` 中间件轻松处理 CORS 问题，也可以手动配置跨域响应头。
* 预检请求是跨域请求的一个重要部分，需要确保服务器正确响应 `OPTIONS` 请求。
* 调试 CORS 问题时，关注请求和响应的头部信息，确保它们符合预期。

通过合理的 CORS 配置，Koa 应用能够支持跨域请求并确保安全性。
