fix(video): 视频结果下载 - 补齐 Grok 同源认证 (#158)

Co-authored-by: Danborad <Danborad@users.noreply.github.com>
This commit is contained in:
Danborad
2026-08-06 13:20:06 +08:00
committed by GitHub
parent 064f55e738
commit bb76e8b22b
2 changed files with 34 additions and 7 deletions

View File

@@ -1035,7 +1035,7 @@ func runVideoTask(ctx context.Context, input canvasGenerationInput) (map[string]
status := strings.ToLower(stringField(state, "status"))
if status == "completed" || status == "succeeded" || status == "success" || status == "done" {
if videoURL := newAPIVideoResultURL(state); videoURL != "" {
data, mimeType, err := getExternalBinary(withProviderRequestKind(ctx, "download"), videoURL)
data, mimeType, err := getProviderExternalBinary(withProviderRequestKind(ctx, "download"), input.Config, videoURL)
if err != nil {
return nil, fmt.Errorf("视频结果下载失败(任务 %s):%w", id, err)
}
@@ -1291,7 +1291,7 @@ func queryNewAPIChannel2VideoTask(ctx context.Context, input canvasGenerationInp
if videoURL == "" {
return nil, status, fmt.Errorf("NewAPI Video Generations 任务 %s 已成功但没有返回视频地址", id)
}
data, mimeType, err := getExternalBinary(withProviderRequestKind(ctx, "download"), videoURL)
data, mimeType, err := getProviderExternalBinary(withProviderRequestKind(ctx, "download"), input.Config, videoURL)
if err != nil {
return nil, status, fmt.Errorf("NewAPI Video Generations 视频结果下载失败(任务 %s):%w", id, err)
}
@@ -1871,6 +1871,27 @@ func getExternalBinary(ctx context.Context, rawURL string) ([]byte, string, erro
return doBinary(req)
}
func getProviderExternalBinary(ctx context.Context, config providerConfig, rawURL string) ([]byte, string, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, rawURL, nil)
if err != nil {
return nil, "", err
}
if sameProviderOrigin(config.BaseURL, rawURL) {
req.Header.Set("Authorization", "Bearer "+config.APIKey)
ApplyOutboundHeaders(req, config.Headers)
}
return doBinary(req)
}
func sameProviderOrigin(baseURL string, rawURL string) bool {
base, baseErr := url.Parse(strings.TrimSpace(baseURL))
target, targetErr := url.Parse(strings.TrimSpace(rawURL))
if baseErr != nil || targetErr != nil || base.Scheme == "" || base.Host == "" || target.Scheme == "" || target.Host == "" {
return false
}
return strings.EqualFold(base.Scheme, target.Scheme) && strings.EqualFold(base.Host, target.Host)
}
func doJSON(req *http.Request, target interface{}) error {
data, mimeType, err := doBinary(req)
if err != nil {

View File

@@ -401,8 +401,8 @@ func TestRunVideoTaskUsesNestedURLBeforeResultURL(t *testing.T) {
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{"code":"success","data":{"task_id":"video-1","status":"SUCCESS","result_url":"` + server.URL + `/v1/videos/video-1/content","data":{"status":"completed","url":"` + server.URL + `/files/video.mp4"}}}`))
case "GET /files/video.mp4":
if authorization := r.Header.Get("Authorization"); authorization != "" {
t.Errorf("file Authorization = %q, want empty", authorization)
if authorization := r.Header.Get("Authorization"); authorization != "Bearer test-key" {
t.Errorf("file Authorization = %q, want Bearer test-key", authorization)
}
w.Header().Set("Content-Type", "video/mp4")
_, _ = w.Write([]byte("video"))
@@ -512,8 +512,8 @@ func TestRunVideoTaskUsesXAIVideoGenerationEndpoint(t *testing.T) {
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{"status":"done","video":{"url":"` + server.URL + `/files/video.mp4"}}`))
case "GET /files/video.mp4":
if authorization := r.Header.Get("Authorization"); authorization != "" {
t.Errorf("file Authorization = %q, want empty", authorization)
if authorization := r.Header.Get("Authorization"); authorization != "Bearer test-key" {
t.Errorf("file Authorization = %q, want Bearer test-key", authorization)
}
w.Header().Set("Content-Type", "video/mp4")
_, _ = w.Write([]byte("video"))
@@ -779,6 +779,9 @@ func TestRunNewAPIChannel1VideoTaskDownloadsSucceededObject(t *testing.T) {
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{"id":"channel-1-task","status":"SUCCEEDED","object":"` + server.URL + `/video.mp4"}`))
case "GET /video.mp4":
if authorization := r.Header.Get("Authorization"); authorization != "" {
t.Errorf("file Authorization = %q, want empty", authorization)
}
w.Header().Set("Content-Type", "video/mp4")
_, _ = w.Write([]byte("video"))
default:
@@ -819,7 +822,7 @@ func TestRunNewAPIChannel2VideoTaskDownloadsTemporaryResult(t *testing.T) {
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
t.Fatalf("decode request: %v", err)
}
if body["model"] != "grok-image-video" || body["seconds"] != "10" || body["aspect_ratio"] != "9:16" || body["resolution"] != "720p" {
if body["model"] != "grok-image-video" || body["seconds"] != "15" || body["aspect_ratio"] != "9:16" || body["resolution"] != "720p" {
t.Errorf("body = %#v", body)
}
images, ok := body["image_urls"].([]interface{})
@@ -837,6 +840,9 @@ func TestRunNewAPIChannel2VideoTaskDownloadsTemporaryResult(t *testing.T) {
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{"code":"success","data":{"task_id":"grok-task","status":"SUCCESS","result_url":"` + server.URL + `/video.mp4"}}`))
case "GET /video.mp4":
if authorization := r.Header.Get("Authorization"); authorization != "Bearer test-key" {
t.Errorf("file Authorization = %q, want Bearer test-key", authorization)
}
w.Header().Set("Content-Type", "video/mp4")
_, _ = w.Write([]byte("video"))
default: