Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion pilot/thousandeyes-kiota/internal/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,22 @@ func New(cfg Config) (*sdk.ThousandEyesClient, error) {
validator: validator,
})

adapter, err := kiotahttp.NewNetHttpRequestAdapter(authProvider)
// Request-body compression is off, and this is load-bearing rather than a
// preference: kiota's default middleware gzips every request body and sets
// Content-Encoding, which the ThousandEyes API answers with a bare 400 --
// the first live acceptance run of this pilot found exactly that. The
// resty pilot has always sent plain JSON; this client must match the wire
// behaviour the recorded evidence was gathered under.
middlewares, err := kiotahttp.GetDefaultMiddlewaresWithOptions(
kiotahttp.NewCompressionOptionsReference(false),
)
if err != nil {
return nil, fmt.Errorf("building the HTTP middleware: %w", err)
}

adapter, err := kiotahttp.NewNetHttpRequestAdapterWithParseNodeFactoryAndSerializationWriterFactoryAndHttpClient(
authProvider, nil, nil, kiotahttp.GetDefaultClient(middlewares...),
)
if err != nil {
return nil, fmt.Errorf("building the ThousandEyes client: %w", err)
}
Expand Down
86 changes: 86 additions & 0 deletions pilot/thousandeyes-kiota/internal/client/client_wire_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package client

import (
"context"
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"testing"

"github.com/deploymenttheory/terraform-plugin-framework-codegen/pilot/thousandeyes-kiota/internal/sdk/models"
)

// TestUnit_Client_SendsPlainJSONBodies pins the wire shape of a write.
//
// Kiota's default middleware gzips every request body and sets
// Content-Encoding, and the ThousandEyes API answers that with a bare 400 --
// which is exactly how the first live acceptance run of this pilot failed,
// with nothing in the error naming the cause. The recorded probe evidence was
// gathered over plain JSON, so plain JSON is the contract this client must
// keep; this test fails if the compression middleware ever comes back.
func TestUnit_Client_SendsPlainJSONBodies(t *testing.T) {
t.Parallel()

type captured struct {
method, path, contentType, encoding, auth string
body []byte
}
var got captured

srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
b, _ := io.ReadAll(r.Body)
got = captured{
method: r.Method,
path: r.URL.String(),
contentType: r.Header.Get("Content-Type"),
encoding: r.Header.Get("Content-Encoding"),
auth: r.Header.Get("Authorization"),
body: b,
}
w.Header().Set("Content-Type", "application/hal+json")
w.WriteHeader(http.StatusCreated)
_, _ = w.Write([]byte(`{"id":"11111111-1111-1111-1111-111111111111","key":"k","value":"v"}`))
}))
defer srv.Close()

c, err := New(Config{BearerToken: "tok", APIEndpoint: srv.URL + "/v7"})
if err != nil {
t.Fatal(err)
}

body := models.NewTags_API_TagInfo()
k, v := "tfacc-key", "tfacc-value"
body.SetKey(&k)
body.SetValue(&v)
ot, _ := models.ParseTags_API_ObjectType("test")
body.SetObjectType(ot.(*models.Tags_API_ObjectType))

if _, err := c.Tags().Post(context.Background(), body, nil); err != nil {
t.Fatalf("Post: %v", err)
}

if got.method != http.MethodPost || got.path != "/v7/tags" {
t.Errorf("request = %s %s, want POST /v7/tags", got.method, got.path)
}
if got.auth != "Bearer tok" {
t.Errorf("Authorization = %q", got.auth)
}
if got.contentType != "application/json" {
t.Errorf("Content-Type = %q", got.contentType)
}
if got.encoding != "" {
t.Errorf("Content-Encoding = %q; the body must go uncompressed", got.encoding)
}

var decoded map[string]any
if err := json.Unmarshal(got.body, &decoded); err != nil {
t.Fatalf("the body is not plain JSON (%v):\n%q", err, got.body)
}
want := map[string]any{"key": "tfacc-key", "objectType": "test", "value": "tfacc-value"}
for field, wantVal := range want {
if decoded[field] != wantVal {
t.Errorf("body[%s] = %v, want %v (full body: %s)", field, decoded[field], wantVal, got.body)
}
}
}
Loading