Download internal/syncer/space.go from a3216/gcli2api: direct link, hf CLI and curl.
- Browser
- Download file 2.28 kB
-
https://huggingface.co/spaces/a3216/gcli2api/resolve/main/internal/syncer/space.go
- Command line
-
hf download hf://spaces/a3216/gcli2api/internal/syncer/space.go
-
curl -L -o space.go https://huggingface.co/spaces/a3216/gcli2api/resolve/main/internal/syncer/space.go
2.28 kB
| package syncer | |
| import ( | |
| "context" | |
| "fmt" | |
| "io" | |
| "net/http" | |
| "net/url" | |
| "strings" | |
| "time" | |
| ) | |
| // RestartSpace 请求 Hugging Face 重启一个 Space。 | |
| // | |
| // 为什么需要它:Space 上的网关只在**启动时**扫一遍凭证目录(没有文件监听), | |
| // 所以往桶里推了新账号之后,正在运行的 Space 并不会加载它——签到时候就会漏掉这个号。 | |
| // 重启一次(30~60s 冷启动)即可让它从挂载卷重新读齐。 | |
| // | |
| // 这也是配置成"只在推了 auths/ 下的文件时才做"的原因:改 state.json 之类不必重启, | |
| // 白白打断正在进行中的签到任务。 | |
| func RestartSpace(ctx context.Context, endpoint, spaceID, token string, timeout time.Duration, insecureSkipVerify bool) error { | |
| if strings.TrimSpace(spaceID) == "" { | |
| return fmt.Errorf("restart_space 未配置") | |
| } | |
| if strings.TrimSpace(endpoint) == "" { | |
| endpoint = DefaultEndpoint | |
| } | |
| if timeout <= 0 { | |
| timeout = 60 * time.Second | |
| } | |
| endpoint = strings.TrimRight(endpoint, "/") | |
| u := fmt.Sprintf("%s/api/spaces/%s/restart", endpoint, strings.Trim(spaceID, "/")) | |
| req, err := http.NewRequestWithContext(ctx, http.MethodPost, u, nil) | |
| if err != nil { | |
| return err | |
| } | |
| if token != "" { | |
| req.Header.Set("Authorization", "Bearer "+token) | |
| } | |
| req.Header.Set("User-Agent", userAgent) | |
| cli := newHTTPClient(timeout, insecureSkipVerify, "") | |
| resp, err := cli.Do(req) | |
| if err != nil { | |
| // 把 URL 里的信息去掉,避免日志里出现带着鉴权语义的完整地址。 | |
| return fmt.Errorf("请求重启 Space 失败: %w", err) | |
| } | |
| defer func() { _ = resp.Body.Close() }() | |
| body, _ := io.ReadAll(io.LimitReader(resp.Body, 1<<20)) | |
| if resp.StatusCode < 200 || resp.StatusCode > 299 { | |
| return fmt.Errorf("重启 Space 返回 %d: %s", resp.StatusCode, truncate(string(body), 300)) | |
| } | |
| return nil | |
| } | |
| // SpaceIDFromBucket 不是必须的辅助函数,但留一个把桶 ID 归一化的入口, | |
| // 便于调用方传 "a3216/wb2api-storage" 或 "https://huggingface.co/..." 两种写法。 | |
| func SpaceIDFromBucket(raw string) string { | |
| raw = strings.TrimSpace(raw) | |
| if raw == "" { | |
| return "" | |
| } | |
| if strings.Contains(raw, "://") { | |
| if u, err := url.Parse(raw); err == nil { | |
| raw = strings.Trim(u.Path, "/") | |
| } | |
| } | |
| return strings.Trim(raw, "/") | |
| } | |