Documentation
¶
Overview ¶
Package httprr implements HTTP record and replay, mainly for use in tests.
Open creates a new RecordReplay. Whether it is recording or replaying is controlled by the -httprecord flag, which is defined by this package only in test programs (built by “go test”). See the Open documentation for more details.
Note: This package has been adapted for use in the LangChainGo library with convienence functions for creating RecordReplay instances that are suitable for testing.
Index ¶
- func CleanFileName(testName string) string
- func EmbeddingJSONFormatter() func(*bytes.Buffer) error
- func Recording(file string) (bool, error)
- func SkipIfNoCredentialsAndRecordingMissing(t *testing.T, envVars ...string)
- type Body
- type RecordReplay
- func (rr *RecordReplay) Client() *http.Client
- func (rr *RecordReplay) Close() error
- func (rr *RecordReplay) Recording() bool
- func (rr *RecordReplay) Replaying() bool
- func (rr *RecordReplay) RoundTrip(req *http.Request) (*http.Response, error)
- func (rr *RecordReplay) ScrubReq(scrubs ...func(req *http.Request) error)
- func (rr *RecordReplay) ScrubResp(scrubs ...func(*bytes.Buffer) error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CleanFileName ¶
CleanFileName converts a test name to a clean filename suitable for recordings. It replaces path separators and other non-path-friendly characters with hyphens. For example:
- "TestMyFunction/subtest" becomes "TestMyFunction-subtest"
- "Test API/Complex_Case" becomes "Test-API-Complex_Case"
func EmbeddingJSONFormatter ¶
EmbeddingJSONFormatter returns a response scrubber that formats JSON responses with special handling for number arrays (displays them on single lines). This is particularly useful for embedding API responses which often contain large arrays of floating-point numbers.
Usage in tests:
rr.ScrubResp(httprr.EmbeddingJSONFormatter())
func Recording ¶
Recording reports whether the "-httprecord" flag is set for the given file. It returns an error if the flag is set to an invalid value.
func SkipIfNoCredentialsAndRecordingMissing ¶
SkipIfNoCredentialsAndRecordingMissing skips the test if required environment variables are not set and no httprr recording exists. This allows tests to gracefully skip when they cannot run.
Example usage:
func TestMyAPI(t *testing.T) { httprr.SkipIfNoCredentialsAndRecordingMissing(t, "API_KEY", "API_URL") rr, err := httprr.OpenForTest(t, http.DefaultTransport) if err != nil { t.Fatal(err) } defer rr.Close() // use rr.Client() for HTTP requests... }
Types ¶
type Body ¶
A Body is an io.ReadCloser used as an HTTP request body. In a Scrubber, if req.Body != nil, then req.Body is guaranteed to have type *Body, making it easy to access the body to change it.
type RecordReplay ¶
type RecordReplay struct {
// contains filtered or unexported fields
}
A RecordReplay is an http.RoundTripper that can operate in two modes: record and replay.
In record mode, the RecordReplay invokes another RoundTripper and logs the (request, response) pairs to a file.
In replay mode, the RecordReplay responds to requests by finding an identical request in the log and sending the logged response.
func Open ¶
func Open(file string, rt http.RoundTripper) (*RecordReplay, error)
Open opens a new record/replay log in the named file and returns a RecordReplay backed by that file.
By default Open expects the file to exist and contain a previously-recorded log of (request, response) pairs, which RecordReplay.RoundTrip consults to prepare its responses.
If the command-line flag -httprecord is set to a non-empty regular expression that matches file, then Open creates the file as a new log. In that mode, RecordReplay.RoundTrip makes actual HTTP requests using rt but then logs the requests and responses to the file for replaying in a future run.
func OpenForEmbeddingTest ¶
func OpenForEmbeddingTest(t *testing.T, rt http.RoundTripper) *RecordReplay
OpenForTest creates a RecordReplay for the given test using a filename derived from the test name. The recording will be stored in a "testdata" subdirectory with a ".httprr" extension.
The transport parameter is optional. If not provided (nil), it defaults to httputil.DefaultTransport.
Example usage:
func TestMyAPI(t *testing.T) { rr := httprr.OpenForTest(t, nil) // Uses httputil.DefaultTransport defer rr.Close() client := rr.Client() // use client for HTTP requests... } // Or with a custom transport: func TestMyAPIWithCustomTransport(t *testing.T) { customTransport := &http.Transport{MaxIdleConns: 10} rr := httprr.OpenForTest(t, customTransport) defer rr.Close() client := rr.Client() // use client for HTTP requests... }
This will create/use a file at "testdata/TestMyAPI.httprr". OpenForEmbeddingTest creates a RecordReplay instance optimized for embedding tests. It automatically applies embedding JSON formatting to reduce file sizes.
func OpenForTest ¶
func OpenForTest(t *testing.T, rt http.RoundTripper) *RecordReplay
func (*RecordReplay) Client ¶
func (rr *RecordReplay) Client() *http.Client
Client returns an http.Client using rr as its transport. It is a shorthand for:
return &http.Client{Transport: rr}
For more complicated uses, use rr or the RecordReplay.RoundTrip method directly.
func (*RecordReplay) Close ¶
func (rr *RecordReplay) Close() error
Close closes the RecordReplay. It is a no-op in replay mode.
func (*RecordReplay) Recording ¶
func (rr *RecordReplay) Recording() bool
Recording reports whether the RecordReplay is in recording mode.
func (*RecordReplay) Replaying ¶
func (rr *RecordReplay) Replaying() bool
Replaying reports whether the RecordReplay is in replaying mode.
func (*RecordReplay) RoundTrip ¶
RoundTrip implements http.RoundTripper.
If rr has been opened in record mode, RoundTrip passes the requests on to the http.RoundTripper specified in the call to Open and then logs the (request, response) pair to the underlying file.
If rr has been opened in replay mode, RoundTrip looks up the request in the log and then responds with the previously logged response. If the log does not contain req, RoundTrip returns an error.
func (*RecordReplay) ScrubReq ¶
func (rr *RecordReplay) ScrubReq(scrubs ...func(req *http.Request) error)
ScrubReq adds new request scrubbing functions to rr.
Before using a request as a lookup key or saving it in the record/replay log, the RecordReplay calls each scrub function, in the order they were registered, to canonicalize non-deterministic parts of the request and remove secrets. Scrubbing only applies to a copy of the request used in the record/replay log; the unmodified original request is sent to the actual server in recording mode. A scrub function can assume that if req.Body is not nil, then it has type *Body.
Calling ScrubReq adds to the list of registered request scrubbing functions; it does not replace those registered by earlier calls.
func (*RecordReplay) ScrubResp ¶
func (rr *RecordReplay) ScrubResp(scrubs ...func(*bytes.Buffer) error)
ScrubResp adds new response scrubbing functions to rr.
Before using a response as a lookup key or saving it in the record/replay log, the RecordReplay calls each scrub function on a byte representation of the response, in the order they were registered, to canonicalize non-deterministic parts of the response and remove secrets.
Calling ScrubResp adds to the list of registered response scrubbing functions; it does not replace those registered by earlier calls.
Clients should be careful when loading the bytes into *http.Response using http.ReadResponse. This function can set http.Response.Close to true even when the original response had it false. See code in go/src/net/http.Response.Write and go/src/net/http.Write for more info.