govcr

repository·master·Indexed 41 days ago

https://github.com/seborama/govcr

A Go library for recording and replaying HTTP/HTTPS interactions to act as an HTTP mock for unit, behavioral, and integration tests. Inspired by php-vcr, it uses 'cassettes' (JSON files) to simulate APIs. Features include support for custom http.Client integration, request matching strategies, track mutators for transforming traffic, AES-GCM and ChaCha20Poly1305 encryption for sensitive data, and AWS S3 storage backend support. Current version is v17.

Tokens
10.6K
Snippets
41
Records
60
Agent score
51%

What's inside govcr

  1. Use Track Mutators to modify requests and responses

    master

    Mutators allow you to transform HTTP traffic. govcr protects live traffic from in-place modification, so mutators are used to transform data at specific lifecycle stages.

    Types of Mutators

    • Track Recording Mutator: Changes the request and/or response before they are persisted to the cassette file.
    • Track Replaying Mutator: Transforms a track after it has been matched and retrieved from the cassette, but before it is returned to the caller. This does not modify the cassette file. Replaying mutators can access an informational copy of the current HTTP request via Track.Response.Request to tailor the response.

    Predicates and Conditions

    Mutators are applied based on On conditions. You can compose complex logic using these helper functions:

    • Any(...): Logical OR.
    • All(...): Logical AND.
    • Not(...): Logical NOT.
    • None(...): Synonymous with Not(Any(...)).

    Example of conditional application:

    myMutator.
        On(Any(...)).
        On(Not(Any(...))).
        On(Not(All(...)))
  2. Match a request to a cassette track

    master

    By default, govcr uses a strict RequestMatcher that compares the method, full URL, headers, body, and trailers.

    To handle dynamic requests (e.g., those containing timestamps or changing IDs), you can use different matching strategies:

    • Relaxed Matching: Use NewMethodURLRequestMatcher() to match based only on the HTTP method and the full URL.
    • Custom Matching: Implement your own RequestMatcher to ignore or modify specific parts of the request (like certain headers) during the comparison process.

    Note: Changes made by a RequestMatcher are scoped to the matching logic and do not affect the original incoming HTTP request or the data written to the cassette.

  3. How govcr works

    master

    govcr acts as a wrapper around the Go http.Client. It intercepts requests and attempts to match them against existing tracks within a loaded cassette.

    The Workflow:

    1. Match: The request is compared against tracks in the cassette.
    2. Playback: If a match is found, the recorded response is returned immediately.
    3. Record: If no match is found, the request is executed live against the actual HTTP server. The resulting interaction is then recorded as a new track on the cassette for future use.

    This flow is primarily designed for test-oriented environments where you record traffic once and replay it in subsequent test runs.

  4. Encrypt cassettes with AES-GCM or ChaCha20Poly1305

    master

    To protect sensitive information in your cassettes, you can use encryption. govcr supports two Go-supported ciphers:

    • AES-GCM: Requires a 12-byte nonce and a 16 or 32-byte key.
    • ChaCha20Poly1305: Requires a 24-byte nonce and a 32-byte key.

    You must provide a secret key to a Crypter. The cryptographic nonce is stored in the cassette header. By default, a random n-byte nonce is generated, but you can provide a custom nonce generator.

    Warning: Never reuse a nonce value with the same private key, as this compromises encryption security.

  5. Understand limitations regarding Go empty interfaces

    master

    Because some http.Response properties are defined as interface{} (or any), json.Unmarshal may fail when attempting to restore a cassette. For example, if a field was originally a big.Int, JSON unmarshaling might attempt to convert it to a float64 and fail.

    Current Mitigation: govcr handles this by removing known untyped fields from the tracks (e.g., PublicKey in certificate chains of the TLS data structure).

  6. Glossary of Terms

    master

    Understanding the core terminology of govcr:

    • VCR: The engine and data provider. It acts as both an HTTP recorder and a player.
    • cassette: A sequential collection of tracks, typically stored as a JSON file.
    • Long Play cassette: A cassette compressed in gzip format (filename ends in .gz).
    • tracks: A single record of an HTTP interaction, containing request data, response data, or errors.
    • ControlPanel: The object instantiated by creating a VCR, used to interact with the VCR while concealing its internal implementation.
  7. Understand how HTTP transport errors are recorded and replayed

    master

    govcr records http.Client errors (such as network failures, timeouts, or firewall blocks) in the track for future playback.

    Because Go's error is an interface, the specific underlying type is lost during JSON unmarshaling. To mitigate this, govcr serializes two specific fields in the track record:

    • ErrType: The name/type of the error object.
    • ErrMsg: The error message string.

    Replay Behavior: Instead of re-creating the original error object (which is not possible by name at runtime in Go), govcr creates a standard error object where the error string is a combination of both ErrType and ErrMsg.

    Implications: If you only need to know that an error occurred, this behavior is transparent. If you rely on type-assertion of the error (e.g., err.(*net.OpError)), you may find the replayed error is a generic error containing the type information in its string.

  8. Install govcr

    master

    To use govcr in your Go project, install the latest version using go get. For versions prior to v5 that do not use go.mod, use the gopkg.in import path.

    Current version (v17):

    go get github.com/seborama/govcr/v17@latest

    Import path:

    import "github.com/seborama/govcr/v17"

    Legacy version (v4):

    go get gopkg.in/seborama/govcr.v4
  9. Integrate govcr with a custom `http.Client`

    master

    If your application uses a custom http.Client (e.g., with a custom Transport for TLS or timeouts), you can pass that client to govcr. govcr will wrap your client, preserving the original transport while adding VCR capabilities. You must use the returned client from vcr.HTTPClient() in your application code to ensure requests are intercepted.

    // Create a custom http.Transport
    tr := http.DefaultTransport.(*http.Transport)
    tr.TLSClientConfig = &tls.Config{ InsecureSkipVerify: true }
    
    // Create your app with the custom client
    app := &myApp{
        httpClient: &http.Client{
            Transport: tr,
            Timeout:   15 * time.Second,
        },
    }
    
    // Instantiate VCR and pass the app's client
    vcr := govcr.NewVCR(
        govcr.NewCassetteLoader(exampleCassetteName2),
        govcr.WithClient(app.httpClient),
    )
    
    // Inject the VCR's wrapped client back into the app
    app.httpClient = vcr.HTTPClient()
    
    // Now requests made by app will be intercepted by VCR
    app.Get("https://example.com/foo")
  10. Configure VCRSettings

    master

    The VCRSettings structure is used to configure the recorder via functional options. Key options include:

    • WithClient: Provide a custom http.Client. If omitted, the default Go http.Client is used.
    • WithRequestMatchers: Define how requests are matched to tracks.
    • WithTrackRecordingMutators: Define mutators to apply during the recording phase.
    • WithTrackReplayingMutators: Define mutators to apply during the playback phase.
    • WithLogging: Enables internal logging to assist with debugging.
  11. Use the ControlPanel struct

    master
    The ControlPanel is the primary interface for interacting with a running VCR. It wraps the underlying http.Client and provides high-level methods to manipulate the VCR's behavior, matchers, mutators, and encryption settings without needing to access the internal transport directly.