Documentation ¶
Index ¶
- Constants
- Variables
- func AdditionalMatcherOptions(ctx context.Context, opts ...RecordMatcherOptions)
- func Client(ctx context.Context) *http.Client
- func ContextWithNewHttpRecorder(ctx context.Context, opts ...HTTPVCROptions) (context.Context, error)
- func ConvertCassetteFileV1toV2(src, dest string) error
- func IsRecording(ctx context.Context) bool
- func NewRemoteTokenStoreReader(opts ...RemoteTokenStoreOptions) oauth2.TokenStoreReader
- func PackageHttpRecordingMode() suitetest.PackageOptions
- func ResetRecorder(ctx context.Context)
- func StopRecorder(ctx context.Context) error
- func WithHttpPlayback(t *testing.T, opts ...HTTPVCROptions) test.Options
- func WithRecordedScopes() test.Options
- type GenericMatcherFunc
- func NewRecordHeaderMatcher(fuzzyKeys ...string) GenericMatcherFunc[http.Header, http.Header]
- func NewRecordMatcher(opts ...RecordMatcherOptions) GenericMatcherFunc[*http.Request, cassette.Request]
- func NewRecordQueryMatcher(fuzzyKeys ...string) GenericMatcherFunc[url.Values, url.Values]
- func NewRecordURLMatcher(ignoreHost bool) GenericMatcherFunc[*url.URL, *url.URL]
- type HTTPVCROption
- type HTTPVCROptions
- func ApplyHttpLatency() HTTPVCROptions
- func DisableHttpRecordOrdering() HTTPVCROptions
- func DisableHttpRecorderHooks(names ...string) HTTPVCROptions
- func DisableHttpRecordingMode() HTTPVCROptions
- func FixedHttpRecordDuration(duration time.Duration) HTTPVCROptions
- func HttpRecordIgnoreHost() HTTPVCROptions
- func HttpRecordMatching(opts ...RecordMatcherOptions) HTTPVCROptions
- func HttpRecordName(name string) HTTPVCROptions
- func HttpRecordOrdering(enforced bool) HTTPVCROptions
- func HttpRecorderHooks(hooks ...RecorderHook) HTTPVCROptions
- func HttpRecordingMode() HTTPVCROptions
- func HttpTransport(transport http.RoundTripper) HTTPVCROptions
- func SanitizeHttpRecord() HTTPVCROptions
- type HttpRecorder
- type Mode
- type RecordBodyMatcher
- type RecordBodyMatcherFunc
- type RecordFormBodyMatcher
- type RecordHeaderMatcherFunc
- type RecordJsonBodyMatcher
- type RecordLiteralBodyMatcher
- type RecordMatcherFunc
- type RecordMatcherOption
- type RecordMatcherOptions
- type RecordQueryMatcherFunc
- type RecordURLMatcherFunc
- type RecorderDI
- type RecorderHook
- func FixedDurationHook(duration time.Duration) RecorderHook
- func InteractionIndexAwareHook() RecorderHook
- func LocalhostRewriteHook() RecorderHook
- func NewRecorderHook(name string, fn recorder.HookFunc, kind recorder.HookKind) RecorderHook
- func NewRecorderHookWithOrder(name string, fn recorder.HookFunc, kind recorder.HookKind, order int) RecorderHook
- func SanitizingHook() RecorderHook
- type RemoteTokenStoreOption
- type RemoteTokenStoreOptions
- type RemoteTokenStoreReader
- func (r *RemoteTokenStoreReader) ReadAccessToken(ctx context.Context, value string) (oauth2.AccessToken, error)
- func (r *RemoteTokenStoreReader) ReadAuthentication(ctx context.Context, tokenValue string, hint oauth2.TokenHint) (oauth2.Authentication, error)
- func (r *RemoteTokenStoreReader) ReadRefreshToken(ctx context.Context, value string) (oauth2.RefreshToken, error)
- type V1Cassette
- type V1Interaction
- type V2Cassette
- type V2Interaction
- type ValueSanitizer
Constants ¶
const ( HookNameIndexAware = "index-aware" HookNameSanitize = "sanitize" HookNameFixedDuration = "fixed-duration" HookNameLocalhostRewrite = "localhost-rewrite" )
const CLIRecordModeFlag = "record-http"
const CheckTokenPath = `/v2/check_token`
const DefaultHTTPDuration = 200 * time.Microsecond
DefaultHTTPDuration default duration of recorded HTTP interaction
const (
DefaultHost = "webservice"
)
Variables ¶
var ( IgnoredRequestHeaders = utils.NewStringSet(xInteractionIndexHeader) FuzzyRequestHeaders = utils.NewStringSet("Authorization") FuzzyRequestQueries = utils.NewStringSet("password", "secret", "nonce", "token", "access_token") FuzzyRequestJsonPaths = utils.NewStringSet() FuzzyResponseHeaders = utils.NewStringSet("Date") FuzzyResponseJsonPaths = utils.NewStringSet("$..access_token") )
var ( HeaderSanitizers = map[string]ValueSanitizer{ "Authorization": RegExpValueSanitizer("^(?P<prefix>Basic |Bearer |Digest ).*|.*", "${prefix}******"), "Date": SubstituteValueSanitizer("Fri, 19 Aug 2022 8:51:32 GMT"), } QuerySanitizers = map[string]ValueSanitizer{ "password": DefaultValueSanitizer(), "secret": DefaultValueSanitizer(), "nonce": DefaultValueSanitizer(), "token": DefaultValueSanitizer(), "access_token": DefaultValueSanitizer(), } BodySanitizers = map[string]ValueSanitizer{ "access_token": DefaultValueSanitizer(), } )
Functions ¶
func AdditionalMatcherOptions ¶
func AdditionalMatcherOptions(ctx context.Context, opts ...RecordMatcherOptions)
AdditionalMatcherOptions temporarily add additional RecordMatcherOptions to the current test context on top of test's HTTPVCROptions. Any changes made with this method can be reset via ResetRecorder. When using with WithHttpPlayback(), the reset is automatic per sub-test Note: The additional options take effect within the scope of sub-test. For test level options, use HttpRecordMatching.
func Client ¶
Client extract http.Client that provided by Recorder. If Recorder is not available, it returns nil
func ContextWithNewHttpRecorder ¶ added in v0.15.0
func ContextWithNewHttpRecorder(ctx context.Context, opts ...HTTPVCROptions) (context.Context, error)
ContextWithNewHttpRecorder is a convenient function that create a new HTTP recorder and store it in context. The returned context can be used with context value accessor such as Client(ctx), IsRecording(ctx), AdditionalMatcherOptions(ctx), etc. See NewHttpRecorder
func ConvertCassetteFileV1toV2 ¶
ConvertCassetteFileV1toV2 is a utility function that help with migrating from httpvcr/v3 (using version 1 format) to httpvcr/v3 (using version 2 format). Note: Usually test authors should re-record interactions instead of using this utility. However, there might be cases that re-recording is not possible due to lack of remote server setup.
func IsRecording ¶
IsRecording returns true if HTTP VCR is in recording mode
func NewRemoteTokenStoreReader ¶
func NewRemoteTokenStoreReader(opts ...RemoteTokenStoreOptions) oauth2.TokenStoreReader
func PackageHttpRecordingMode ¶
func PackageHttpRecordingMode() suitetest.PackageOptions
PackageHttpRecordingMode returns a suitetest.PackageOptions that enables HTTP recording mode for the entire package. This is usually used in TestMain function. Note: this option has no effect to tests using DisableHttpRecordingMode e.g. <code>
func TestMain(m *testing.M) { suitetest.RunTests(m, PackageHttpRecordingMode(), ) }
</code>
func ResetRecorder ¶ added in v0.15.0
ResetRecorder revert the change made by AdditionalMatcherOptions. Note: If tests configured via WithHttpPlayback, this method is automatically invoked at sub-test teardown.
func StopRecorder ¶ added in v0.15.0
StopRecorder stops the recorder extracted from the given context. Note: If tests configured via WithHttpPlayback, this method is automatically invoked at test teardown.
func WithHttpPlayback ¶
func WithHttpPlayback(t *testing.T, opts ...HTTPVCROptions) test.Options
WithHttpPlayback enables remote HTTP server playback capabilities supported by `httpvcr` This mode requires apptest.Bootstrap to work Each top-level test should have corresponding recorded HTTP responses in `testdata` folder, or the test will fail. To enable record mode, use `go test ... --record-http` at CLI, or do it programmatically with HttpRecordingMode See https://github.com/cockroachdb/copyist for more details
func WithRecordedScopes ¶
Types ¶
type GenericMatcherFunc ¶
func NewRecordHeaderMatcher ¶
NewRecordHeaderMatcher returns RecordHeaderMatcherFunc that compare keys and values of recorded and actual queries Any header value is ignored if its key is in the optional fuzzyKeys
func NewRecordMatcher ¶
func NewRecordMatcher(opts ...RecordMatcherOptions) GenericMatcherFunc[*http.Request, cassette.Request]
NewRecordMatcher create a custom RecordMatcherFunc to compare recorded request and actual request. By default, the crated matcher compare following: - Method, Host, Path are exact match - Queries are exact match except for FuzzyRequestQueries - Headers are exact match except for FuzzyRequestHeaders - Body is compared as JSON or x-www-form-urlencoded Form
Note: In case the request contains random/temporal data in queries/headers/form/JSON, use Fuzzy* options
func NewRecordQueryMatcher ¶
NewRecordQueryMatcher returns RecordQueryMatcherFunc that compare keys and values of recorded and actual queries Any query value is ignored if its key is in the optional fuzzyKeys
func NewRecordURLMatcher ¶
NewRecordURLMatcher returns RecordURLMatcherFunc that compares Method, Path, Host and Port
type HTTPVCROption ¶
type HTTPVCROption struct { Name string Mode Mode SavePath string RecordMatching []RecordMatcherOptions Hooks []RecorderHook RealTransport http.RoundTripper SkipRequestLatency bool // contains filtered or unexported fields }
type HTTPVCROptions ¶
type HTTPVCROptions func(opt *HTTPVCROption)
func ApplyHttpLatency ¶
func ApplyHttpLatency() HTTPVCROptions
ApplyHttpLatency apply recorded HTTP latency. By default, HTTP latency is not applied for faster test run. This option has no effect in recording mode.
func DisableHttpRecordOrdering ¶
func DisableHttpRecordOrdering() HTTPVCROptions
DisableHttpRecordOrdering disable HTTP interactions order matching. By default, HTTP interactions have to happen in the recorded order. When this option is used, HTTP interactions can happen in any order. However, each matched record can only replay once
func DisableHttpRecorderHooks ¶ added in v0.15.0
func DisableHttpRecorderHooks(names ...string) HTTPVCROptions
DisableHttpRecorderHooks returns a HTTPVCROptions that removes installed hooks by name
func DisableHttpRecordingMode ¶
func DisableHttpRecordingMode() HTTPVCROptions
DisableHttpRecordingMode returns a HTTPVCROptions that force replaying mode regardless the command line flag
func FixedHttpRecordDuration ¶ added in v0.15.0
func FixedHttpRecordDuration(duration time.Duration) HTTPVCROptions
FixedHttpRecordDuration install a hook to set a fixed duration on interactions before they are saved. If the duration is less or equal to 0, the actual latency will be recorded. When HTTPVCROption.SkipRequestLatency is set to false (via ApplyHttpLatency option), the recorded duration will be applied during playback See FixedDurationHook for details. This option has no effect in playback mode.
func HttpRecordIgnoreHost ¶
func HttpRecordIgnoreHost() HTTPVCROptions
HttpRecordIgnoreHost convenient HTTPVCROptions that would ignore host when matching recorded requests, equivalent to HttpRecordMatching(IgnoreHost())
func HttpRecordMatching ¶
func HttpRecordMatching(opts ...RecordMatcherOptions) HTTPVCROptions
HttpRecordMatching returns a HTTPVCROptions that allows custom matching of recorded requests
func HttpRecordName ¶
func HttpRecordName(name string) HTTPVCROptions
HttpRecordName returns a HTTPVCROptions that set HTTP record's name
func HttpRecordOrdering ¶ added in v0.15.0
func HttpRecordOrdering(enforced bool) HTTPVCROptions
HttpRecordOrdering toggles HTTP interactions order matching. When enforced, HTTP interactions have to happen in the recorded order. Otherwise, HTTP interactions can happen in any order, but each matched record can only replay once By default, record ordering is enabled
func HttpRecorderHooks ¶
func HttpRecorderHooks(hooks ...RecorderHook) HTTPVCROptions
HttpRecorderHooks returns a HTTPVCROptions that adds recording hooks. If given hooks also implementing order.Ordered, the order will be respected
func HttpRecordingMode ¶
func HttpRecordingMode() HTTPVCROptions
HttpRecordingMode returns a HTTPVCROptions that turns on Recording mode. Normally recording mode should be enabled via `go test` argument `-record-http` Note: Record mode is forced off if flag is set to "-record-http=false" explicitly IMPORTANT: When Record mode is enabled, all sub tests interact with actual HTTP remote service.
So use this mode on LOCAL DEV ONLY
func HttpTransport ¶
func HttpTransport(transport http.RoundTripper) HTTPVCROptions
HttpTransport override the RealTransport during recording mode. This option has no effect in playback mode
func SanitizeHttpRecord ¶ added in v0.15.0
func SanitizeHttpRecord() HTTPVCROptions
SanitizeHttpRecord install a hook to sanitize request and response before they are saved in file. See SanitizingHook for details.
type HttpRecorder ¶
type HttpRecorder struct { *recorder.Recorder RawOptions *recorder.Options InitMatcher cassette.MatcherFunc Options *HTTPVCROption }
HttpRecorder wrapper of recorder.RawRecorder, used to hold some value that normally inaccessible via wrapped recorder.RawRecorder. Note: This type is for other test utilities to re-configure recorder.RawRecorder
func NewHttpRecorder ¶
func NewHttpRecorder(opts ...HTTPVCROptions) (*HttpRecorder, error)
NewHttpRecorder create a new HttpRecorder. Commonly used by: - other test utilities that relies on http recording. (e.g. opensearchtest, consultest, etc.) - unit tests that doesn't bootstrap dependency injection
func Recorder ¶ added in v0.15.0
func Recorder(ctx context.Context) *HttpRecorder
Recorder extract HttpRecorder from given context. If HttpRecorder is not available, it returns nil
type RecordBodyMatcher ¶
type RecordBodyMatcher interface { Support(contentType string) bool Matches(out []byte, record []byte) error }
func NewRecordFormBodyMatcher ¶
func NewRecordFormBodyMatcher(fuzzyKeys ...string) RecordBodyMatcher
NewRecordFormBodyMatcher returns RecordBodyMatcher that matches request bodies as application/x-www-form-urlencoded. any value in the fuzzyKeys is not compared. But outgoing body need to have all keys contained in the record body
func NewRecordJsonBodyMatcher ¶
func NewRecordJsonBodyMatcher(fuzzyJsonPaths ...string) RecordBodyMatcher
NewRecordJsonBodyMatcher returns a RecordBodyMatcher that matches JSON body of recorded and outgoing request. Values of any field matching the optional fuzzyJsonPaths is not compared, but outgoing request body must contain all fields that the record contains
func NewRecordLiteralBodyMatcher ¶
func NewRecordLiteralBodyMatcher() RecordBodyMatcher
NewRecordLiteralBodyMatcher returns RecordBodyMatcher that matches request bodies literally
type RecordBodyMatcherFunc ¶
type RecordBodyMatcherFunc GenericMatcherFunc[[]byte, []byte]
type RecordFormBodyMatcher ¶
type RecordFormBodyMatcher GenericMatcherFunc[[]byte, []byte]
func (RecordFormBodyMatcher) Matches ¶
func (m RecordFormBodyMatcher) Matches(out []byte, record []byte) error
func (RecordFormBodyMatcher) Support ¶
func (m RecordFormBodyMatcher) Support(contentType string) bool
type RecordHeaderMatcherFunc ¶
type RecordHeaderMatcherFunc GenericMatcherFunc[http.Header, http.Header]
type RecordJsonBodyMatcher ¶
type RecordJsonBodyMatcher GenericMatcherFunc[[]byte, []byte]
func (RecordJsonBodyMatcher) Matches ¶
func (m RecordJsonBodyMatcher) Matches(out []byte, record []byte) error
func (RecordJsonBodyMatcher) Support ¶
func (m RecordJsonBodyMatcher) Support(contentType string) bool
type RecordLiteralBodyMatcher ¶
type RecordLiteralBodyMatcher GenericMatcherFunc[[]byte, []byte]
func (RecordLiteralBodyMatcher) Matches ¶
func (m RecordLiteralBodyMatcher) Matches(out []byte, record []byte) error
func (RecordLiteralBodyMatcher) Support ¶
func (m RecordLiteralBodyMatcher) Support(_ string) bool
type RecordMatcherFunc ¶
type RecordMatcherFunc GenericMatcherFunc[*http.Request, cassette.Request]
type RecordMatcherOption ¶
type RecordMatcherOption struct { // Convenient Options IgnoreHost bool FuzzyHeaders []string FuzzyQueries []string FuzzyPostForm []string FuzzyJsonPaths []string // Advanced Options, if set, will overwrite corresponding convenient options // Note: directly changing these defaults requires knowledge about golang generics and function casting. URLMatcher RecordURLMatcherFunc QueryMatcher RecordQueryMatcherFunc HeaderMatcher RecordHeaderMatcherFunc BodyMatchers []RecordBodyMatcher }
type RecordMatcherOptions ¶
type RecordMatcherOptions func(opt *RecordMatcherOption)
func FuzzyForm ¶
func FuzzyForm(formKeys ...string) RecordMatcherOptions
FuzzyForm returns RecordMatcherOptions that ignore form values (in queries and post body if applicable) of given keys during record matching Note: still check if the value exists, only value comparison is skipped
func FuzzyHeaders ¶
func FuzzyHeaders(headers ...string) RecordMatcherOptions
FuzzyHeaders returns RecordMatcherOptions that ignore header values of given names during record matching Note: still check if the header exists, only value comparison is skipped
func FuzzyJsonPaths ¶
func FuzzyJsonPaths(jsonPaths ...string) RecordMatcherOptions
FuzzyJsonPaths returns RecordMatcherOptions that ignore fields in JSON body that matching the given JSONPaths JSONPath Syntax: https://goessner.net/articles/JsonPath/
func FuzzyQueries ¶
func FuzzyQueries(queries ...string) RecordMatcherOptions
FuzzyQueries returns RecordMatcherOptions that ignore query value of given keys during record matching Note: still check if the value exists, only value comparison is skipped. This function dosen't consider POST form data. Use FuzzyForm for both Queries and POST form data
func IgnoreHost ¶
func IgnoreHost() RecordMatcherOptions
IgnoreHost returns RecordMatcherOptions that ignore host during record matching
type RecordQueryMatcherFunc ¶
type RecordQueryMatcherFunc GenericMatcherFunc[url.Values, url.Values]
type RecordURLMatcherFunc ¶
type RecordURLMatcherFunc GenericMatcherFunc[*url.URL, *url.URL]
type RecorderDI ¶
type RecorderDI struct { fx.In Recorder *recorder.Recorder RecorderOption *recorder.Options RecorderMatcher cassette.MatcherFunc HTTPVCROption *HTTPVCROption }
type RecorderHook ¶
RecorderHook wrapper of recorder.Hook
func FixedDurationHook ¶
func FixedDurationHook(duration time.Duration) RecorderHook
FixedDurationHook changes the duration of record HTTP interaction to constant, to avoid randomness
func InteractionIndexAwareHook ¶
func InteractionIndexAwareHook() RecorderHook
InteractionIndexAwareHook inject interaction index into stored header: httpvcr store interaction's ID but doesn't expose it to cassette.MatcherFunc, so we need to store it in request for request matchers to access
func LocalhostRewriteHook ¶
func LocalhostRewriteHook() RecorderHook
LocalhostRewriteHook changes the host of request to a pre-defined constant if it is localhost, in order to avoid randomness
func NewRecorderHook ¶
func SanitizingHook ¶
func SanitizingHook() RecorderHook
SanitizingHook is an HTTP VCR hook that sanitize values in header, query, body (x-form-urlencoded/json). Values to sanitize are globally configured via HeaderSanitizers, QuerySanitizers, BodySanitizers. Note: Sanitized values cannot be exactly matched. If the configuration of sanitizers is changed, make sure
to configure fuzzy matching accordingly.
See NewRecordMatcher, FuzzyHeaders, FuzzyQueries, FuzzyForm and FuzzyJsonPaths
type RemoteTokenStoreOption ¶
type RemoteTokenStoreOption struct { JwtDecoder jwt.JwtDecoder HttpClient httpclient.Client HttpClientConfig *httpclient.ClientConfig BaseUrl string ServiceName string // auth service's name for LB Scheme string ContextPath string ClientId string ClientSecret string SkipRemoteCheck bool }
type RemoteTokenStoreOptions ¶
type RemoteTokenStoreOptions func(opt *RemoteTokenStoreOption)
type RemoteTokenStoreReader ¶
type RemoteTokenStoreReader struct { // JwtDecoder optional, when provided, token signature is pre-checked before sent to remote auth service JwtDecoder jwt.JwtDecoder // SkipRemoteCheck, if set to true, skip the remote check when JwtDecoder is provided and context details is not required. SkipRemoteCheck bool // HttpClient httpclient.Client to use for remote token check HttpClient httpclient.Client ClientId string ClientSecret string }
RemoteTokenStoreReader implements oauth2.TokenStoreReader that leverage /check_token endpoint to load authentication Note: this implementation is not mocks. With proper refactoring, it can be potentially used in production
func (*RemoteTokenStoreReader) ReadAccessToken ¶
func (r *RemoteTokenStoreReader) ReadAccessToken(ctx context.Context, value string) (oauth2.AccessToken, error)
func (*RemoteTokenStoreReader) ReadAuthentication ¶
func (r *RemoteTokenStoreReader) ReadAuthentication(ctx context.Context, tokenValue string, hint oauth2.TokenHint) (oauth2.Authentication, error)
func (*RemoteTokenStoreReader) ReadRefreshToken ¶
func (r *RemoteTokenStoreReader) ReadRefreshToken(ctx context.Context, value string) (oauth2.RefreshToken, error)
type V1Cassette ¶
type V1Cassette struct { Version int `json:"version"` Interactions []V1Interaction `json:"interactions"` }
type V1Interaction ¶
type V2Cassette ¶
type V2Cassette struct { Version int `json:"version"` Interactions []V2Interaction `json:"interactions"` }
type V2Interaction ¶
type ValueSanitizer ¶
func DefaultValueSanitizer ¶
func DefaultValueSanitizer() ValueSanitizer
func RegExpValueSanitizer ¶
func RegExpValueSanitizer(regex, repl string) ValueSanitizer
func SubstituteValueSanitizer ¶
func SubstituteValueSanitizer(repl any) ValueSanitizer