代码示例
五种语言的最小可用封装。共同点:统一处理 Bearer 头,并且先判 ok 再判状态码。
cURL
export HSCDN_KEY="你的API密钥"
BASE="https://cdn.treeidc.cn"
# 读: 站点列表
curl -s -H "Authorization: Bearer $HSCDN_KEY" "$BASE/api/me/sites"
# 写: 修改回源地址(把 123 换成你自己的站点 ID, 否则 404)
curl -s -X POST "$BASE/api/sites/123/update" \
-H "Authorization: Bearer $HSCDN_KEY" \
-H "Content-Type: application/json" \
-d '{"origins":[{"addr":"203.0.113.10","weight":1,"status":true}]}'
# 写: 刷新缓存
curl -s -X POST "$BASE/api/cache/refresh" \
-H "Authorization: Bearer $HSCDN_KEY" \
-H "Content-Type: application/json" \
-d '{"urls":"https://www.example.com/index.html"}'
Python
下面这段可以直接跑(只读),把密钥放进环境变量 HSCDN_KEY 即可:
import os
import requests
BASE = "https://cdn.treeidc.cn"
S = requests.Session()
S.headers.update({"Authorization": "Bearer " + os.environ["HSCDN_KEY"]})
def call(method, path, **kw):
r = S.request(method, BASE + path, timeout=20, **kw)
d = r.json()
if not d.get("ok"): # 先看 ok, 再看状态码
raise RuntimeError(f"{path} 失败: {d.get('message')} (HTTP {r.status_code})")
return d
# 列出站点
for s in call("GET", "/api/me/sites")["sites"]:
print(s["id"], s["domain"], "启用" if s["enabled"] else "停用")
写操作 —— 把 SITE_ID 换成上面列出来的、你自己的站点 ID:
SITE_ID = 123 # ← 换成你自己的站点 ID, 否则会得到 404「网站不存在」
# 改回源
d = call("POST", f"/api/sites/{SITE_ID}/update",
json={"origins": [{"addr": "203.0.113.10", "weight": 1, "status": True}]})
# 字段名写错时请求照样返回 ok:true —— 只有这里能看出来
if d.get("ignored_fields"):
raise RuntimeError(f"这些字段名写错了, 没有生效: {d['ignored_fields']}")
# 刷新缓存(注意 urls 是**字符串**, 多条用换行分隔)
call("POST", "/api/cache/refresh",
json={"urls": "\n".join(["https://www.example.com/index.html"])})
Node.js
只读部分,可以直接跑(需要 Node 18+ 的原生 fetch):
const BASE = 'https://cdn.treeidc.cn'
async function call (method, path, body) {
const res = await fetch(BASE + path, {
method,
headers: {
Authorization: `Bearer ${process.env.HSCDN_KEY}`,
...(body ? { 'Content-Type': 'application/json' } : {})
},
body: body ? JSON.stringify(body) : undefined
})
const data = await res.json()
if (!data.ok) throw new Error(`${path} 失败: ${data.message} (HTTP ${res.status})`)
return data
}
const { sites } = await call('GET', '/api/me/sites')
console.log(sites.map(s => s.domain))
写操作 —— 把 SITE_ID 换成上面列出来的、你自己的站点 ID:
const SITE_ID = 123 // ← 换成你自己的站点 ID, 否则会抛「网站不存在 (HTTP 404)」
const d = await call('POST', `/api/sites/${SITE_ID}/update`, {
origins: [{ addr: '203.0.113.10', weight: 1, status: true }]
})
if (d.ignored_fields?.length) throw new Error(`字段名写错了: ${d.ignored_fields}`)
await call('POST', '/api/cache/refresh', {
urls: 'https://www.example.com/index.html' // 字符串, 多条用 \n 分隔
})
PHP
<?php
function hscdn($method, $path, $body = null) {
$ch = curl_init('https://cdn.treeidc.cn' . $path);
$headers = ['Authorization: Bearer ' . getenv('HSCDN_KEY')];
if ($body !== null) {
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
}
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
]);
$raw = curl_exec($ch);
curl_close($ch);
$data = json_decode($raw, true);
if (empty($data['ok'])) {
throw new Exception($path . ' 失败: ' . ($data['message'] ?? '未知错误'));
}
return $data;
}
$sites = hscdn('GET', '/api/me/sites')['sites'];
hscdn('POST', '/api/cache/refresh', ['urls' => 'https://www.example.com/index.html']);
Go
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
"time"
)
const base = "https://cdn.treeidc.cn"
func call(method, path string, body any) (map[string]any, error) {
buf := bytes.NewBuffer(nil)
if body != nil {
b, _ := json.Marshal(body)
buf = bytes.NewBuffer(b)
}
req, _ := http.NewRequest(method, base+path, buf)
req.Header.Set("Authorization", "Bearer "+os.Getenv("HSCDN_KEY"))
if body != nil {
req.Header.Set("Content-Type", "application/json")
}
res, err := (&http.Client{Timeout: 20 * time.Second}).Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
var d map[string]any
if err := json.NewDecoder(res.Body).Decode(&d); err != nil {
return nil, err
}
if ok, _ := d["ok"].(bool); !ok {
return nil, fmt.Errorf("%s 失败: %v (HTTP %d)", path, d["message"], res.StatusCode)
}
return d, nil
}
文档没写到的情况,或某个字段的行为与描述不符 —— 请在控制台提交工单,附上请求路径、请求体与完整响应,能最快定位。