feat(14-03): tide keeps binary upstream bodies and compares every *_url upload by shape
- A response body that is not valid UTF-8 (a cover image) is written as a YAML !!binary scalar, never masked and replayed byte for byte - The upload URL normalizer covers every key ending in _url (cover_url), not only url and thumb_url - README and parity-testing docs updated
This commit is contained in:
@@ -286,3 +286,51 @@ func TestUpstreamFakeHashesBase64Bodies(t *testing.T) {
|
||||
t.Fatalf("mismatch message not clipped: %d bytes", len(err.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
// TestUpstreamBinaryBodyRoundTrip pins that a response body that is not
|
||||
// valid UTF-8 (an image) is written as !!binary, kept unmasked, read back
|
||||
// byte for byte and replayed by the fake unchanged.
|
||||
func TestUpstreamBinaryBodyRoundTrip(t *testing.T) {
|
||||
store := upstreamTestStore(t)
|
||||
store.Set("id:short", "7")
|
||||
img := "\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01 7 {{ example-token-value \xff\xd9"
|
||||
s := UpstreamSidecar{Version: 1, Exchanges: []UpstreamExchange{{
|
||||
Request: UpstreamRequest{Method: "GET", URL: "https://img.example.test/cover.jpg"},
|
||||
Response: UpstreamResponse{Status: 200, Headers: map[string]string{"Content-Type": "image/jpeg"}, Body: img},
|
||||
}, {
|
||||
Request: UpstreamRequest{Method: "GET", URL: "https://api.example.test/v1/me"},
|
||||
Response: UpstreamResponse{Status: 200, Body: `{"token":"example-token-value"}`},
|
||||
}}}
|
||||
path := filepath.Join(t.TempDir(), "bin.upstream.yaml")
|
||||
if err := WriteUpstream(path, s, store); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
raw, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Contains(raw, []byte("body: !!binary "+base64.StdEncoding.EncodeToString([]byte(img)))) {
|
||||
t.Fatalf("binary body not written as !!binary:\n%s", raw)
|
||||
}
|
||||
if !bytes.Contains(raw, []byte(`{{secret:example-token}}`)) {
|
||||
t.Fatalf("text body not masked:\n%s", raw)
|
||||
}
|
||||
got, err := LoadUpstream(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got.Exchanges[0].Response.Body != img {
|
||||
t.Fatalf("binary body changed: %q", got.Exchanges[0].Response.Body)
|
||||
}
|
||||
fake := NewUpstreamFake(got, store)
|
||||
req, _ := http.NewRequest(http.MethodGet, "https://img.example.test/cover.jpg", nil)
|
||||
res, err := fake.RoundTrip(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
_, _ = buf.ReadFrom(res.Body)
|
||||
if buf.String() != img {
|
||||
t.Fatalf("replayed body %q", buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user