feat(12-01): record multipart uploads and match Winter upload URLs
- attach.PublicURL and (*File).URL build Winter File::getPath() URLs; the thumbnailer decodes webp via golang.org/x/image v0.46.0 and checks the image size from the header before decoding - tide requests carry multipart parts (files beside the fixture pinned by sha256) encoded with the fixed MultipartBoundary, so PHP and Go receive byte-identical bodies - tide masks the random partition, disk name and file id of url/thumb_url upload URLs while still diffing prefix, size, mode and extension, and NormalizePublications masks Carbon dates in the published album
This commit is contained in:
@@ -42,6 +42,9 @@ type Request struct {
|
||||
Query string `yaml:"query,omitempty"`
|
||||
Headers map[string]string `yaml:"headers,omitempty"`
|
||||
Body Body `yaml:"body,omitempty"`
|
||||
// Parts is a multipart/form-data body, encoded with MultipartBoundary
|
||||
// when the step runs. A request has Body or Parts, never both.
|
||||
Parts []Part `yaml:"parts,omitempty"`
|
||||
}
|
||||
|
||||
// Response is the recorded or expected HTTP reply.
|
||||
@@ -73,21 +76,28 @@ type NormalizeRule struct {
|
||||
type Body string
|
||||
|
||||
// RecordConfig injects the HTTP target, client and body bound for recording.
|
||||
// BaseDir is the fixture directory that request part files are read from.
|
||||
type RecordConfig struct {
|
||||
Target string
|
||||
Client *http.Client
|
||||
MaxBody int64
|
||||
Store *Store
|
||||
Rules Rules
|
||||
BaseDir string
|
||||
}
|
||||
|
||||
// ReplayConfig injects the HTTP target, client and body bound for replay.
|
||||
// BaseDir is the fixture directory that body_file sidecars and request part
|
||||
// files are read from.
|
||||
// UploadPrefix is the public URL prefix of uploaded files whose url and
|
||||
// thumb_url values are compared by shape; empty means DefaultUploadPrefix.
|
||||
type ReplayConfig struct {
|
||||
Target string
|
||||
Client *http.Client
|
||||
MaxBody int64
|
||||
Store *Store
|
||||
BaseDir string
|
||||
Target string
|
||||
Client *http.Client
|
||||
MaxBody int64
|
||||
Store *Store
|
||||
BaseDir string
|
||||
UploadPrefix string
|
||||
}
|
||||
|
||||
// Result is the outcome of replaying a flow.
|
||||
@@ -169,6 +179,9 @@ func validateFlow(flow Flow) error {
|
||||
if err := validateSidecar(step.Response.BodyFile); err != nil {
|
||||
return fmt.Errorf("tide: step %s: %w", step.ID, err)
|
||||
}
|
||||
if err := validateParts(step.Request); err != nil {
|
||||
return fmt.Errorf("tide: step %s: %w", step.ID, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user