# @zenweb/body - 请求内容解析

zenweb 模块 - 解析 HTTP POST 请求内容（JSON、表单、文本、二进制等）

## 安装

```bash
npm install @zenweb/body
```

## 快速开始

```ts
import { Context, Post, Body, ObjectBody, BodyHelper, $body } from 'zenweb';

export class Controller {
  // 直接获取解析后的数据
  @Post()
  post(body: Body) {
    console.log(body.type); // 内容类型，如 'json'
    console.log(body.data); // 解析后的数据
  }

  // 获取对象形式的数据
  @Post()
  form(obj: ObjectBody) {
    console.log(obj.name, obj.age);
  }

  // 类型转换与校验
  @Post()
  async validate(helper: BodyHelper) {
    const { name, age } = await helper.get({
      name: 'string',    // 字符串类型
      age: '!int',       // 必填，整数类型
    });
  }
}

// 在非注入上下文中使用
async function outsideDI() {
  const data = await $body.data();
  const { name } = await $body.get({ name: 'string' });
}
```

## 解析流程

1. **RawBody** - 读取原始数据流，处理 gzip/deflate 解压
2. **TextBody** - 按字符集编码转换为文本（如 UTF-8、GBK）
3. **Body** - 根据 Content-Type 选择解析器，返回解析结果
4. **ObjectBody** - 将 Body.data 转为对象形式（仅 JSON/表单）

## 可注入对象

| 对象 | 作用域 | 说明 |
|-----|--------|------|
| RawBody | request | 原始 Buffer，已解压 |
| TextBody | request | 解码后的文本字符串 |
| Body | request | 解析后的数据，含 type、parser 属性 |
| ObjectBody | request | 对象形式，仅支持 JSON 和表单 |
| BodyHelper | request | 类型转换与校验，继承 @zenweb/helper |

## 全局函数

在非注入上下文中通过 AsyncLocalStorage 访问：

```ts
await $getRawBody()    // Buffer | undefined
await $getTextBody()   // string | undefined
await $getObjectBody() // ObjectBody 实例
$body                  // BodyHelper 代理
```

## 配置项

| 配置项 | 类型 | 默认值 | 说明 |
|-------|------|--------|------|
| encoding | string | 'utf-8' | 默认字符集编码 |
| limit | number | 1048576 | 内容大小限制 (bytes)，默认 1MB |
| inflate | boolean | true | 支持 gzip/deflate 压缩传输 |
| textTypes | string[] | ['text/*', 'xml', '+xml'] | 文本类型匹配规则 |
| parses | BodyParserClass[] | [JSONParser, URLEncodedParser] | 解析器列表 |

## 自定义解析器

```ts
import { Injectable } from '@zenweb/inject';
import body, { TextBodyParser, JSONParser, URLEncodedParser } from '@zenweb/body';

@Injectable('singleton')
export class XMLParser extends TextBodyParser {
  objected = false;              // 不能转为 ObjectBody
  types = ['xml', '+xml'];       // 匹配的 Content-Type

  parse(text: string) {
    return parseXML(text);       // 自定义解析逻辑
  }
}

// 注册
$initCore().setup(body({
  parses: [JSONParser, URLEncodedParser, XMLParser]
}));
```

## 指定解析器

强制使用特定解析器处理请求：

```ts
import { useBodyParser, JSONParser } from '@zenweb/body';

router.post('/api', useBodyParser(JSONParser), handler);
```

## 错误类型

模块抛出 http-errors，包含 type 字段：

| 状态码 | type | 说明 |
|-------|------|------|
| 400 | json.parse-error | JSON 解析失败 |
| 400 | decode.failed | 编码转换失败 |
| 400 | objected.only | 非 JSON/表单格式转 ObjectBody |
| 413 | entity.too.large | 超过大小限制 |
| 415 | json.strict | JSON 必须是对象或数组 |
| 415 | charset.unsupported | 不支持的字符集 |

## 扩展模块

- [@zenweb/xml-body](https://www.npmjs.com/package/@zenweb/xml-body) - XML 格式解析
