11package cmd
22
33import (
4+ "bytes"
45 "context"
56 "fmt"
7+ "io"
68 "net/http"
9+ "net/url"
710 "os"
811 "os/signal"
912 "strings"
1013 "syscall"
1114
1215 "github.com/elazarl/goproxy"
16+ "github.com/elazarl/goproxy/ext/auth"
1317 "github.com/linuxsuren/api-testing/extensions/collector/pkg"
1418 "github.com/linuxsuren/api-testing/extensions/collector/pkg/filter"
1519 "github.com/spf13/cobra"
1620)
1721
1822type option struct {
19- port int
20- filterPath string
21- output string
23+ port int
24+ filterPath []string
25+ saveResponseBody bool
26+ output string
27+ upstreamProxy string
28+ verbose bool
29+ username string
30+ password string
2231}
2332
2433// NewRootCmd creates the root command
@@ -31,8 +40,13 @@ func NewRootCmd() (c *cobra.Command) {
3140 }
3241 flags := c .Flags ()
3342 flags .IntVarP (& opt .port , "port" , "p" , 8080 , "The port for the proxy" )
34- flags .StringVarP (& opt .filterPath , "filter-path" , "" , "" , "The path prefix for filtering" )
43+ flags .StringSliceVarP (& opt .filterPath , "filter-path" , "" , []string {}, "The path prefix for filtering" )
44+ flags .BoolVarP (& opt .saveResponseBody , "save-response-body" , "" , false , "Save the response body" )
3545 flags .StringVarP (& opt .output , "output" , "o" , "sample.yaml" , "The output file" )
46+ flags .StringVarP (& opt .upstreamProxy , "upstream-proxy" , "" , "" , "The upstream proxy" )
47+ flags .StringVarP (& opt .username , "username" , "" , "" , "The username for basic auth" )
48+ flags .StringVarP (& opt .password , "password" , "" , "" , "The password for basic auth" )
49+ flags .BoolVarP (& opt .verbose , "verbose" , "" , false , "Verbose mode" )
3650
3751 _ = cobra .MarkFlagRequired (flags , "filter-path" )
3852 return
@@ -41,6 +55,7 @@ func NewRootCmd() (c *cobra.Command) {
4155type responseFilter struct {
4256 urlFilter * filter.URLPathFilter
4357 collects * pkg.Collects
58+ ctx context.Context
4459}
4560
4661func (f * responseFilter ) filter (resp * http.Response , ctx * goproxy.ProxyCtx ) * http.Response {
@@ -51,21 +66,42 @@ func (f *responseFilter) filter(resp *http.Response, ctx *goproxy.ProxyCtx) *htt
5166
5267 req := resp .Request
5368 if f .urlFilter .Filter (req .URL ) {
54- f .collects .Add (req .Clone (context .TODO ()))
69+ simpleResp := & pkg.SimpleResponse {StatusCode : resp .StatusCode }
70+
71+ if resp .Body != nil {
72+ buf := new (bytes.Buffer )
73+ io .Copy (buf , resp .Body )
74+ simpleResp .Body = buf .String ()
75+ resp .Body = io .NopCloser (buf )
76+ }
77+
78+ f .collects .Add (req .Clone (f .ctx ), simpleResp )
5579 }
5680 return resp
5781}
5882
5983func (o * option ) runE (cmd * cobra.Command , args []string ) (err error ) {
6084 urlFilter := & filter.URLPathFilter {PathPrefix : o .filterPath }
6185 collects := pkg .NewCollects ()
62- responseFilter := & responseFilter {urlFilter : urlFilter , collects : collects }
86+ responseFilter := & responseFilter {urlFilter : urlFilter , collects : collects , ctx : cmd . Context () }
6387
6488 proxy := goproxy .NewProxyHttpServer ()
65- proxy .Verbose = true
89+ proxy .Verbose = o .verbose
90+ if o .upstreamProxy != "" {
91+ proxy .Tr .Proxy = func (r * http.Request ) (* url.URL , error ) {
92+ return url .Parse (o .upstreamProxy )
93+ }
94+ proxy .ConnectDial = proxy .NewConnectDialToProxy (o .upstreamProxy )
95+ cmd .Println ("Using upstream proxy" , o .upstreamProxy )
96+ }
97+ if o .username != "" && o .password != "" {
98+ auth .ProxyBasic (proxy , "my_realm" , func (user , pwd string ) bool {
99+ return user == o .username && o .password == pwd
100+ })
101+ }
66102 proxy .OnResponse ().DoFunc (responseFilter .filter )
67103
68- exporter := pkg .NewSampleExporter ()
104+ exporter := pkg .NewSampleExporter (o . saveResponseBody )
69105 collects .AddEvent (exporter .Add )
70106
71107 srv := & http.Server {
0 commit comments