fix: apply raw api header flags

This commit is contained in:
fsafasff 2026-05-29 17:38:03 +08:00
parent 2f8b987c2c
commit 33387ae042
4 changed files with 98 additions and 2 deletions

View File

@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
"strings"
@ -66,7 +67,12 @@ func runAPI(c *cobra.Command, args []string) error {
}
}
env, err := cli.Do(method, path, body, query)
headers, err := parseHeaders(c)
if err != nil {
return err
}
env, err := cli.DoWithHeaders(method, path, body, query, headers)
if err != nil {
if apiErr, ok := err.(*client.APIError); ok {
errEnv := output.ErrorEnvelope(apiErr.Code, apiErr.Message, "")
@ -78,6 +84,27 @@ func runAPI(c *cobra.Command, args []string) error {
return output.Print(env, resolveFormat())
}
func parseHeaders(c *cobra.Command) (http.Header, error) {
values, _ := c.Flags().GetStringSlice("header")
if len(values) == 0 {
return nil, nil
}
headers := http.Header{}
for _, value := range values {
key, headerValue, ok := strings.Cut(value, ":")
if !ok {
return nil, fmt.Errorf("invalid header %q: expected key:value", value)
}
key = strings.TrimSpace(key)
if key == "" {
return nil, fmt.Errorf("invalid header %q: header key is empty", value)
}
headers.Add(key, strings.TrimSpace(headerValue))
}
return headers, nil
}
func readJSONBody(c *cobra.Command) (interface{}, error) {
bodyStr, _ := c.Flags().GetString("body")
bodyFile, _ := c.Flags().GetString("body-file")

View File

@ -88,3 +88,38 @@ func TestReadJSONBodyWithoutSource(t *testing.T) {
t.Fatalf("body = %v, want nil", body)
}
}
func TestParseHeaders(t *testing.T) {
cmd := NewAPICmd()
cmd.Flags().Set("header", "X-Test: value")
cmd.Flags().Set("header", "X-Trace: one:two")
headers, err := parseHeaders(cmd)
if err != nil {
t.Fatalf("parseHeaders returned error: %v", err)
}
if got := headers.Get("X-Test"); got != "value" {
t.Fatalf("X-Test = %q, want value", got)
}
if got := headers.Get("X-Trace"); got != "one:two" {
t.Fatalf("X-Trace = %q, want one:two", got)
}
}
func TestParseHeadersRejectsInvalidValue(t *testing.T) {
cmd := NewAPICmd()
cmd.Flags().Set("header", "missing-colon")
if _, err := parseHeaders(cmd); err == nil {
t.Fatal("expected invalid header to return an error")
}
}
func TestParseHeadersRejectsEmptyKey(t *testing.T) {
cmd := NewAPICmd()
cmd.Flags().Set("header", ": value")
if _, err := parseHeaders(cmd); err == nil {
t.Fatal("expected empty header key to return an error")
}
}

View File

@ -42,6 +42,10 @@ func New() (*Client, error) {
}
func (c *Client) Do(method, path string, body interface{}, query url.Values) (*output.Envelope, error) {
return c.DoWithHeaders(method, path, body, query, nil)
}
func (c *Client) DoWithHeaders(method, path string, body interface{}, query url.Values, headers http.Header) (*output.Envelope, error) {
path = normalizeAPIPath(c.BaseURL, path)
// Append .json suffix if not already present (GitLink API convention)
@ -78,6 +82,11 @@ func (c *Client) Do(method, path string, body interface{}, query url.Values) (*o
if err != nil {
return nil, err
}
for key, values := range headers {
for _, value := range values {
req.Header.Add(key, value)
}
}
if c.Debug {
fmt.Printf("→ %s %s\n", method, fullURL)

View File

@ -1,6 +1,10 @@
package client
import "testing"
import (
"net/http"
"net/http/httptest"
"testing"
)
func TestNormalizeAPIPathStripsDuplicateAPIPrefix(t *testing.T) {
got := normalizeAPIPath("https://www.gitlink.org.cn/api", "/api/v1/repos/Gitlink/gitlink-cli/contents/README.md")
@ -25,3 +29,24 @@ func TestNormalizeAPIPathKeepsAPIPrefixForNonAPIBaseURL(t *testing.T) {
t.Fatalf("normalizeAPIPath() = %q, want %q", got, want)
}
}
func TestDoWithHeadersAddsRequestHeaders(t *testing.T) {
var gotHeader string
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
gotHeader = r.Header.Get("X-Test")
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"status":1,"data":{"ok":true}}`))
}))
defer server.Close()
cli := &Client{HTTP: server.Client(), BaseURL: server.URL}
headers := http.Header{}
headers.Set("X-Test", "value")
if _, err := cli.DoWithHeaders("GET", "/users/me", nil, nil, headers); err != nil {
t.Fatalf("DoWithHeaders returned error: %v", err)
}
if gotHeader != "value" {
t.Fatalf("X-Test header = %q, want value", gotHeader)
}
}