# net.listen Web 服务

## 功能

`net.listen({type: 'web'})` 启动 BT Web 服务。每个请求都会执行站点入口 BT 文件，并注入 `web` 请求上下文。

## 语法

```bt
server = net.listen({
    type: 'web',
    bind: '127.0.0.1:8080',
    sites: [
        {
            root: 'web/',
            entry: 'main.bt',
            domains: ['localhost'],
            upload: {temp: 'temp/'},
            static: {
                route: '/static/{**}',
                path: 'web/static/',
                default: 'index.html',
                list: false
            },
            ssl: {cert: 'ssl/cert.pem', key: 'ssl/key.pem'}
        }
    ]
})
```

## 参数

| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|------|------|
| type | String | 是 | 无 | 固定为 web。 |
| bind | String | 否 | 0.0.0.0:8080 | 监听地址。 |
| sites | Array | 是 | 无 | 站点配置数组，至少一个。 |
| sites[].root | String | 否 | web/ | 站点根目录。 |
| sites[].entry | String | 否 | main.bt | 请求入口 BT 文件。 |
| sites[].domains | Array | 否 | [] | Host 过滤域名。 |
| sites[].upload.temp | String | 否 | temp/ | 上传文件临时目录。 |
| sites[].static | Object | 否 | 无 | 静态文件配置对象；字段见下方 `static 字段`。 |
| sites[].ssl | Object | 否 | 无 | TLS 证书配置对象；字段见下方 `ssl 字段`。 |

## sites 字段

`sites` 是站点配置数组。每个站点对象字段如下：

| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|------|------|
| root | String | 否 | `web/` | 站点根目录。入口脚本、默认静态目录等相对路径会基于该目录解析。 |
| entry | String | 否 | `main.bt` | 每个动态请求执行的 BT 入口文件。 |
| domains | Array | 否 | `[]` | Host 过滤域名列表。为空数组时作为不限制域名的默认站点。 |
| upload | Object | 否 | 无 | 上传文件配置对象；字段见下方 `upload 字段`。 |
| static | Object | 否 | 无 | 静态文件配置对象。传入该对象即启用静态文件服务。 |
| ssl | Object | 否 | 无 | TLS 证书配置对象。必须同时提供 `cert` 和 `key` 才会启用 HTTPS。 |

## upload 字段

| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|------|------|
| temp | String | 否 | `temp/` | 上传文件临时保存目录。`web.files[*].path` 和 `web.files[*].file` 会指向这里保存后的文件。 |

## static 字段

| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|------|------|
| route | String | 否 | `/static/{**}` | 静态资源路由匹配规则。 |
| path | String | 否 | `root/static` | 静态文件目录。未填写时使用当前站点 root 下的 `static` 目录。 |
| default | String | 否 | `index.html` | 访问目录时尝试返回的默认文件名。 |
| list | Bool | 否 | `false` | 是否允许目录列表展示。生产环境通常保持 false。 |

## ssl 字段

| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|------|------|
| cert | String | 是 | 无 | TLS 证书文件路径。 |
| key | String | 是 | 无 | TLS 私钥文件路径。 |

## 返回值

| 类型 | 说明 |
|------|------|
| WebServer | 返回 Web 服务句柄。 |

## WebServer 字段和方法

| 名称 | 类型 | 说明 |
|------|------|------|
| addr | String | 实际监听地址，格式通常为 `host:port`。 |
| type | String | 固定为 `web`。 |
| close() | Fn -> Bool | 关闭后台 Web 服务，成功返回 true。 |

## 示例

```bt
// 启动一个最小 Web 服务，请求进入后执行 web/main.bt。
server = net.listen({
    type: 'web',
    bind: '127.0.0.1:8080',
    sites: [{root: 'web/', entry: 'main.bt'}]
})

// 输出：web
echo(server.type)
```

## 注意事项

- root、upload.temp、static.path、ssl.cert、ssl.key 的相对路径基于调用源码文件所在目录解析；@ 表示项目根。
- `ssl.cert` 和 `ssl.key` 任一为空时不会启用 TLS。
