feat(api): support HEAD request bodies in OpenAPI client
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
19838779ef
commit
b9f91811d8
2 changed files with 74 additions and 4 deletions
|
|
@ -86,8 +86,8 @@ func NewOpenAPIClient(opts ...OpenAPIClientOption) *OpenAPIClient {
|
|||
//
|
||||
// The params argument may be a map, struct, or nil. For convenience, a map may
|
||||
// include "path", "query", and "body" keys to explicitly control where the
|
||||
// values are sent. When no explicit body is provided, non-GET requests send the
|
||||
// remaining parameters as JSON.
|
||||
// values are sent. When no explicit body is provided, requests with a declared
|
||||
// requestBody send the remaining parameters as JSON.
|
||||
func (c *OpenAPIClient) Call(operationID string, params any) (any, error) {
|
||||
if err := c.load(); err != nil {
|
||||
return nil, err
|
||||
|
|
@ -273,7 +273,7 @@ func (c *OpenAPIClient) buildURL(op openAPIOperation, params map[string]any) (st
|
|||
query.Set(key, fmt.Sprint(value))
|
||||
}
|
||||
}
|
||||
if op.method == http.MethodGet || op.method == http.MethodHead {
|
||||
if op.method == http.MethodGet || (op.method == http.MethodHead && !op.hasRequestBody) {
|
||||
for key, value := range params {
|
||||
if key == "path" || key == "body" || key == "query" {
|
||||
continue
|
||||
|
|
@ -300,7 +300,7 @@ func (c *OpenAPIClient) buildBody(op openAPIOperation, params map[string]any) (i
|
|||
return encodeJSONBody(explicitBody)
|
||||
}
|
||||
|
||||
if op.method == http.MethodGet || op.method == http.MethodHead {
|
||||
if op.method == http.MethodGet || (op.method == http.MethodHead && !op.hasRequestBody) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ package api_test
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
|
|
@ -124,6 +125,75 @@ paths:
|
|||
}
|
||||
}
|
||||
|
||||
func TestOpenAPIClient_Good_CallHeadOperationWithRequestBody(t *testing.T) {
|
||||
errCh := make(chan error, 1)
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/head", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodHead {
|
||||
errCh <- fmt.Errorf("expected HEAD, got %s", r.Method)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if got := r.URL.RawQuery; got != "" {
|
||||
errCh <- fmt.Errorf("expected no query string, got %q", got)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
errCh <- fmt.Errorf("read body: %v", err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if string(body) != `{"name":"Ada"}` {
|
||||
errCh <- fmt.Errorf("expected JSON body {\"name\":\"Ada\"}, got %q", string(body))
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
})
|
||||
|
||||
srv := httptest.NewServer(mux)
|
||||
defer srv.Close()
|
||||
|
||||
specPath := writeTempSpec(t, `openapi: 3.1.0
|
||||
info:
|
||||
title: Test API
|
||||
version: 1.0.0
|
||||
paths:
|
||||
/head:
|
||||
head:
|
||||
operationId: head_check
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
`)
|
||||
|
||||
client := api.NewOpenAPIClient(
|
||||
api.WithSpec(specPath),
|
||||
api.WithBaseURL(srv.URL),
|
||||
)
|
||||
|
||||
result, err := client.Call("head_check", map[string]any{
|
||||
"name": "Ada",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
select {
|
||||
case err := <-errCh:
|
||||
t.Fatal(err)
|
||||
default:
|
||||
}
|
||||
if result != nil {
|
||||
t.Fatalf("expected nil result for empty HEAD response body, got %T", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenAPIClient_Bad_MissingOperation(t *testing.T) {
|
||||
specPath := writeTempSpec(t, `openapi: 3.1.0
|
||||
info:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue