feat(api): allow openapi specs from readers
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
799de22d4d
commit
1f43f019b1
2 changed files with 79 additions and 9 deletions
39
client.go
39
client.go
|
|
@ -29,6 +29,7 @@ import (
|
|||
// data, err := client.Call("get_health", nil)
|
||||
type OpenAPIClient struct {
|
||||
specPath string
|
||||
specReader io.Reader
|
||||
baseURL string
|
||||
bearerToken string
|
||||
httpClient *http.Client
|
||||
|
|
@ -67,6 +68,18 @@ func WithSpec(path string) OpenAPIClientOption {
|
|||
}
|
||||
}
|
||||
|
||||
// WithSpecReader sets an in-memory or streamed OpenAPI document source.
|
||||
// It is read once the first time the client loads its spec.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// client := api.NewOpenAPIClient(api.WithSpecReader(strings.NewReader(spec)))
|
||||
func WithSpecReader(reader io.Reader) OpenAPIClientOption {
|
||||
return func(c *OpenAPIClient) {
|
||||
c.specReader = reader
|
||||
}
|
||||
}
|
||||
|
||||
// WithBaseURL sets the base URL used for outgoing requests.
|
||||
//
|
||||
// Example:
|
||||
|
|
@ -239,17 +252,25 @@ func (c *OpenAPIClient) load() error {
|
|||
}
|
||||
|
||||
func (c *OpenAPIClient) loadSpec() error {
|
||||
if c.specPath == "" {
|
||||
return coreerr.E("OpenAPIClient.loadSpec", "spec path is required", nil)
|
||||
var (
|
||||
data []byte
|
||||
err error
|
||||
)
|
||||
|
||||
switch {
|
||||
case c.specReader != nil:
|
||||
data, err = io.ReadAll(c.specReader)
|
||||
case c.specPath != "":
|
||||
f, openErr := os.Open(c.specPath)
|
||||
if openErr != nil {
|
||||
return coreerr.E("OpenAPIClient.loadSpec", "read spec", openErr)
|
||||
}
|
||||
defer f.Close()
|
||||
data, err = io.ReadAll(f)
|
||||
default:
|
||||
return coreerr.E("OpenAPIClient.loadSpec", "spec path or reader is required", nil)
|
||||
}
|
||||
|
||||
f, err := os.Open(c.specPath)
|
||||
if err != nil {
|
||||
return coreerr.E("OpenAPIClient.loadSpec", "read spec", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
data, err := io.ReadAll(f)
|
||||
if err != nil {
|
||||
return coreerr.E("OpenAPIClient.loadSpec", "read spec", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
api "dappco.re/go/core/api"
|
||||
|
|
@ -125,6 +126,54 @@ paths:
|
|||
}
|
||||
}
|
||||
|
||||
func TestOpenAPIClient_Good_LoadsSpecFromReader(t *testing.T) {
|
||||
errCh := make(chan error, 1)
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/ping", 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":"pong"}}`))
|
||||
})
|
||||
|
||||
srv := httptest.NewServer(mux)
|
||||
defer srv.Close()
|
||||
|
||||
client := api.NewOpenAPIClient(
|
||||
api.WithSpecReader(strings.NewReader(`openapi: 3.1.0
|
||||
info:
|
||||
title: Test API
|
||||
version: 1.0.0
|
||||
paths:
|
||||
/ping:
|
||||
get:
|
||||
operationId: ping
|
||||
`)),
|
||||
api.WithBaseURL(srv.URL),
|
||||
)
|
||||
|
||||
result, err := client.Call("ping", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
select {
|
||||
case err := <-errCh:
|
||||
t.Fatal(err)
|
||||
default:
|
||||
}
|
||||
|
||||
ping, ok := result.(map[string]any)
|
||||
if !ok {
|
||||
t.Fatalf("expected map result, got %T", result)
|
||||
}
|
||||
if ping["message"] != "pong" {
|
||||
t.Fatalf("expected message=pong, got %#v", ping["message"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenAPIClient_Good_CallHeadOperationWithRequestBody(t *testing.T) {
|
||||
errCh := make(chan error, 1)
|
||||
mux := http.NewServeMux()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue