...

Source file src/cloud.google.com/go/httpreplay/httpreplay.go

Documentation: cloud.google.com/go/httpreplay

     1  // Copyright 2018 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package httpreplay provides an API for recording and replaying traffic
    16  // from HTTP-based Google API clients.
    17  //
    18  // To record:
    19  //  1. Call NewRecorder to get a Recorder.
    20  //  2. Use its Client method to obtain an HTTP client to use when making API calls.
    21  //  3. Close the Recorder when you're done. That will save the log of interactions
    22  //     to the file you provided to NewRecorder.
    23  //
    24  // To replay:
    25  //  1. Call NewReplayer with the same filename you used to record to get a Replayer.
    26  //  2. Call its Client method and use the client to make the same API calls.
    27  //     You will get back the recorded responses.
    28  //  3. Close the Replayer when you're done.
    29  //
    30  // This package is EXPERIMENTAL and is subject to change or removal without notice.
    31  // It requires Go version 1.8 or higher.
    32  package httpreplay
    33  
    34  // TODO(jba): add examples.
    35  
    36  import (
    37  	"context"
    38  	"net/http"
    39  
    40  	"cloud.google.com/go/httpreplay/internal/proxy"
    41  	"google.golang.org/api/option"
    42  	htransport "google.golang.org/api/transport/http"
    43  )
    44  
    45  // A Recorder records HTTP interactions.
    46  type Recorder struct {
    47  	proxy *proxy.Proxy
    48  }
    49  
    50  // NewRecorder creates a recorder that writes to filename. The file will
    51  // also store initial state that can be retrieved to configure replay.
    52  //
    53  // You must call Close on the Recorder to ensure that all data is written.
    54  func NewRecorder(filename string, initial []byte) (*Recorder, error) {
    55  	p, err := proxy.ForRecording(filename, 0)
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  	p.Initial = initial
    60  	return &Recorder{proxy: p}, nil
    61  }
    62  
    63  // RemoveRequestHeaders will remove request headers matching patterns from the log,
    64  // and skip matching them during replay.
    65  //
    66  // Pattern is taken literally except for *, which matches any sequence of characters.
    67  func (r *Recorder) RemoveRequestHeaders(patterns ...string) {
    68  	r.proxy.RemoveRequestHeaders(patterns)
    69  }
    70  
    71  // ClearHeaders will replace the value of request and response headers that match
    72  // any of the patterns with CLEARED, on both recording and replay.
    73  // Use ClearHeaders when the header information is secret or may change from run to
    74  // run, but you still want to verify that the headers are being sent and received.
    75  //
    76  // Pattern is taken literally except for *, which matches any sequence of characters.
    77  func (r *Recorder) ClearHeaders(patterns ...string) {
    78  	r.proxy.ClearHeaders(patterns)
    79  }
    80  
    81  // RemoveQueryParams will remove URL query parameters matching patterns from the log,
    82  // and skip matching them during replay.
    83  //
    84  // Pattern is taken literally except for *, which matches any sequence of characters.
    85  func (r *Recorder) RemoveQueryParams(patterns ...string) {
    86  	r.proxy.RemoveQueryParams(patterns)
    87  }
    88  
    89  // ClearQueryParams will replace the value of URL query parametrs that match any of
    90  // the patterns with CLEARED, on both recording and replay.
    91  // Use ClearQueryParams when the parameter information is secret or may change from
    92  // run to run, but you still want to verify that it are being sent.
    93  //
    94  // Pattern is taken literally except for *, which matches any sequence of characters.
    95  func (r *Recorder) ClearQueryParams(patterns ...string) {
    96  	r.proxy.ClearQueryParams(patterns)
    97  }
    98  
    99  // Client returns an http.Client to be used for recording. Provide authentication options
   100  // like option.WithTokenSource as you normally would, or omit them to use Application Default
   101  // Credentials.
   102  func (r *Recorder) Client(ctx context.Context, opts ...option.ClientOption) (*http.Client, error) {
   103  	return proxyClient(ctx, r.proxy, opts...)
   104  }
   105  
   106  func proxyClient(ctx context.Context, p *proxy.Proxy, opts ...option.ClientOption) (*http.Client, error) {
   107  	trans, err := htransport.NewTransport(ctx, p.Transport(), opts...)
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  	return &http.Client{Transport: trans}, nil
   112  }
   113  
   114  // Close closes the Recorder and saves the log file.
   115  func (r *Recorder) Close() error {
   116  	return r.proxy.Close()
   117  }
   118  
   119  // A Replayer replays previously recorded HTTP interactions.
   120  type Replayer struct {
   121  	proxy *proxy.Proxy
   122  }
   123  
   124  // NewReplayer creates a replayer that reads from filename.
   125  func NewReplayer(filename string) (*Replayer, error) {
   126  	p, err := proxy.ForReplaying(filename, 0)
   127  	if err != nil {
   128  		return nil, err
   129  	}
   130  	return &Replayer{proxy: p}, nil
   131  }
   132  
   133  // Client returns an HTTP client for replaying. The client does not need to be
   134  // configured with credentials for authenticating to a server, since it never
   135  // contacts a real backend.
   136  func (r *Replayer) Client(ctx context.Context) (*http.Client, error) {
   137  	return proxyClient(ctx, r.proxy, option.WithoutAuthentication())
   138  }
   139  
   140  // Initial returns the initial state saved by the Recorder.
   141  func (r *Replayer) Initial() []byte {
   142  	return r.proxy.Initial
   143  }
   144  
   145  // IgnoreHeader will not use h when matching requests.
   146  func (r *Replayer) IgnoreHeader(h string) {
   147  	r.proxy.IgnoreHeader(h)
   148  }
   149  
   150  // Close closes the replayer.
   151  func (r *Replayer) Close() error {
   152  	return r.proxy.Close()
   153  }
   154  
   155  // DebugHeaders helps to determine whether a header should be ignored.
   156  // When true, if requests have the same method, URL and body but differ
   157  // in a header, the first mismatched header is logged.
   158  func DebugHeaders() {
   159  	proxy.DebugHeaders = true
   160  }
   161  
   162  // Supported reports whether httpreplay is supported in the current version of Go.
   163  // For Go 1.8 and above, the answer is true.
   164  func Supported() bool { return true }
   165  

View as plain text