# 站点请求

<Badge type="warning" text="尚未发布" />

让后台任务借用 Cowork 里某个网站标签页的登录状态，调用该网站的 API。那里没有打开的标签页时，Cowork 会在后台打开一个。Cowork 从那个标签页发出请求；cookie、token 或请求头都不会到达 Extension。只允许 `dozin.sites` 里列出的站点、方法和路径。

## dozin.sites

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `host` | `string` | 是 | 小写主机名，不含协议、端口或路径 |
| `methods` | `string[]` | 是 | `GET`、`POST`、`PUT`、`PATCH`、`DELETE` 中的任意几个 |
| `pathPrefixes` | `string[]` | 是 | 1–16 个路径，请求路径必须以其中之一开头 |
| `minIntervalMs` | `number` | 否 | 对这个主机的两次请求之间的最短间隔；默认 1000，最多 60000 |

## ctx.site.request(request) <Badge type="warning" text="尚未发布" />

| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `request.host` | `string` | 是 | `dozin.sites` 里的某个 `host` |
| `request.method` | `string` | 否 | 默认 `GET` |
| `request.path` | `string` | 是 | 以 `/` 开头，并以某个 `pathPrefixes` 开头；不能含 `?`、`#`、`..` |
| `request.query` | `Record<string, string \| number \| boolean>` | 否 | 每个键一个值 |
| `request.body` | `unknown` | 否 | JSON 请求体；`GET` 不允许 |

### 返回值

`Promise<{ status: number, contentType: string | null, body: unknown }>`。响应是 JSON 时，`body` 为解析后的 JSON。

### 错误

promise 以一个错误 reject，其 `code` 为：

| `code` | 含义 |
|---|---|
| `NEED_LOGIN` | Cowork 无法在该站点上打开标签页，或站点回应用户未登录 |
| `SITE_NOT_ALLOWED` | 主机、方法或路径不在 `dozin.sites` 里 |
| `RATE_LIMITED` | 站点返回 429 |
| `NETWORK_ERROR` | 请求没有到达站点 |
| `BAD_REQUEST` | query 或请求体无效、`GET` 带了请求体，或参数无法发送给 Cowork |
| `RUN_ENDED` | 发起调用的那次运行已经结束 |

## ctx.site.session(host) <Badge type="warning" text="尚未发布" />

判断用户在该站点上是否看起来已登录。

| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `host` | `string` | 是 | `dozin.sites` 里的某个 `host` |

返回 `Promise<{ loggedIn: boolean | null }>`：有对该站点的上一次请求时，为那次请求的结果；否则，打开了该站点的标签页时为 `null`（Cowork 还无法判断），没有打开时为 `false`。

## 示例

```js
const { loggedIn } = await ctx.site.session('welladjustedhk.janeapp.com');
if (loggedIn === false) return ctx.status('Please log in to Jane', 'warn');
try {
  const res = await ctx.site.request({ host: 'welladjustedhk.janeapp.com', path: '/admin/api/v2/locations' });
  ctx.status(`OK · HTTP ${res.status}`);
} catch (error) {
  ctx.status(error.code === 'NEED_LOGIN' ? 'Please log in to Jane' : `Error: ${error.code}`, 'error');
}
```

## 相关

- [后台任务](https://docs.micromeet.ai/zh/extension-sdk/service.md): `ctx.site` 从哪里来
- [概览](https://docs.micromeet.ai/zh/extension-sdk/overview.md): `package.json` 的字段
