# 在请求中注入 Secret
<subtitle>通过网络规则，将 Secret 注入沙箱的出站 HTTPS 请求。</subtitle>

Secret 通过按主机的网络规则注入到沙箱的出站 **HTTPS** 请求中，明文 HTTP 请求不会被注入。在网络规则的 `transform` 中，使用 `Secret.fill()` 生成请求头的值。

下面的例子把 [星图平台](https://astraflow.ucloud.cn/modelverse/api-keys) 的 API Key 保存为 Secret。沙箱内的代码调用星图 Chat Completions 接口时不需要持有这个 Key，由出站代理自动加上 `Authorization` 请求头。

```python
from ucloud_sandbox import Sandbox, Secret

Secret.create("modelverse_api_key", "your-modelverse-api-key")

sandbox = Sandbox.create(
    network={
        # 仅允许访问已注册规则的主机
        "allow_out": lambda ctx: list(ctx.rules.keys()),
        # 拒绝其他所有流量
        "deny_out": lambda ctx: [ctx.all_traffic],
        "rules": {
            "api.modelverse.cn": [
                {
                    "transform": {
                        "headers": {
                            "Authorization": f"Bearer {Secret.fill('modelverse_api_key')}",
                        },
                    },
                },
            ],
        },
    },
)

# 沙箱内的请求不带 API Key，出站代理会自动注入 Authorization 请求头
result = sandbox.commands.run("""
curl -s https://api.modelverse.cn/v1/chat/completions \\
  -H "Content-Type: application/json" \\
  -d '{"model": "glm-5.2", "messages": [{"role": "user", "content": "你好"}]}'
""")
print(result.stdout)
```

> 星图 Chat Completions 接口的完整说明请参阅 [创建对话补全](https://astraflow.ucloud.cn/reference/modelverse-api-protocol/llm/chat/create-chat-completion#description/introduction)。

## 使用说明

- `Secret.fill()` 只是本地格式化方法，返回对 Secret 的引用，不会发起网络请求，也不会检查 Secret 是否存在。
- `Secret.fill()` 需要传入 Secret 的**名称**，而不是 Secret ID。
- 请始终使用 `Secret.fill()` 生成引用，不要手写引用格式，其格式属于内部实现，后续可能变化。
- 出站代理在沙箱外部为每个匹配的请求解析 Secret 的当前值，因此 [轮换 Secret](/docs/agent-sandbox/secret/rotate.md) 后无需重建沙箱。
- 网络规则本身不会放行或拦截流量，需要配合 `allow_out` / `deny_out` 使用，详见 [网络访问](/docs/agent-sandbox/network/internet-access.md)。
- 一个请求头的值可以同时包含 Secret 引用和普通文本，例如上例中的 `Bearer ` 前缀。
- 网络规则在创建沙箱时确定。如需在运行中的沙箱上修改，请使用 `update_network`，它会整体替换当前的出站配置。

## 排查注入失败

创建沙箱时不会校验引用的 Secret 是否存在。如果注入没有生效，目标服务通常会返回 `401` 或 `403`。请依次检查：

1. Secret 是否存在于当前项目中，可以用 [`Secret.exists()`](/docs/agent-sandbox/secret/list.md) 确认。注意 `exists()` 只检查 Secret 是否存在，并不验证注入是否成功。
2. `Secret.fill()` 传入的是否为 Secret 名称。
3. 请求是否使用 HTTPS，目标主机是否与规则中的主机一致。
4. Secret 的值是否可以作为 HTTP 请求头使用，例如不能包含换行符等控制字符。
