diff --git a/client.go b/client.go index 7eabeed..4a901a5 100644 --- a/client.go +++ b/client.go @@ -231,8 +231,13 @@ func (c *OpenAPIClient) loadSpec() error { } } - if c.baseURL == "" && len(c.servers) > 0 { - c.baseURL = c.servers[0] + if c.baseURL == "" { + for _, server := range c.servers { + if isAbsoluteBaseURL(server) { + c.baseURL = server + break + } + } } return nil @@ -453,3 +458,11 @@ func appendQueryValue(query url.Values, key string, value any) { query.Add(key, fmt.Sprint(value)) } + +func isAbsoluteBaseURL(raw string) bool { + u, err := url.Parse(raw) + if err != nil { + return false + } + return u.Scheme != "" && u.Host != "" +} diff --git a/client_test.go b/client_test.go index 884f43c..93558fe 100644 --- a/client_test.go +++ b/client_test.go @@ -257,6 +257,58 @@ paths: } } +func TestOpenAPIClient_Good_UsesFirstAbsoluteServer(t *testing.T) { + errCh := make(chan error, 1) + mux := http.NewServeMux() + mux.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + errCh <- fmt.Errorf("expected GET, got %s", r.Method) + w.WriteHeader(http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"success":true,"data":{"message":"hello"}}`)) + }) + + srv := httptest.NewServer(mux) + defer srv.Close() + + specPath := writeTempSpec(t, `openapi: 3.1.0 +info: + title: Test API + version: 1.0.0 +servers: + - url: / + - url: `+srv.URL+` +paths: + /hello: + get: + operationId: get_hello +`) + + client := api.NewOpenAPIClient( + api.WithSpec(specPath), + ) + + result, err := client.Call("get_hello", nil) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + select { + case err := <-errCh: + t.Fatal(err) + default: + } + + hello, ok := result.(map[string]any) + if !ok { + t.Fatalf("expected map result, got %T", result) + } + if hello["message"] != "hello" { + t.Fatalf("expected message=hello, got %#v", hello["message"]) + } +} + func TestOpenAPIClient_Bad_MissingOperation(t *testing.T) { specPath := writeTempSpec(t, `openapi: 3.1.0 info: