forked from Gitlink/gitlink-cli
fix: apply raw api header flags
This commit is contained in:
parent
2f8b987c2c
commit
33387ae042
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue