11package main
22
33import (
4+ "crypto/tls"
45 "net/http"
56 "net/url"
7+ "os"
8+ "strings"
69
710 over "github.com/adrienaury/zeromdc"
811 "github.com/cgi-fr/pimo/internal/app/pimo"
@@ -11,13 +14,31 @@ import (
1114 "github.com/cgi-fr/pimo/pkg/uri"
1215 "github.com/rs/zerolog/log"
1316 "github.com/spf13/cobra"
17+ "golang.org/x/term"
1418)
1519
1620// pimo --serve ":8080" --mask 'name=[{add: true}, {randomChoiceInUri: "pimo://nameFR"}]'
1721// pimo -v5 mock -p :8081 http://localhost:8080
1822
23+ func askPassword (prompt string ) string {
24+ if term .IsTerminal (int (os .Stdin .Fd ())) {
25+ os .Stdout .Write ([]byte (prompt ))
26+ bytePassword , err := term .ReadPassword (int (os .Stdin .Fd ()))
27+ os .Stdout .Write ([]byte ("\n " ))
28+ if err != nil {
29+ os .Exit (1 )
30+ }
31+ return string (bytePassword )
32+ }
33+ return ""
34+ }
35+
1936func setupMockCommand (rootCmd * cobra.Command ) {
2037 mockAddr := ":8080"
38+ proxyURL := ""
39+ proxyAuth := ""
40+ serverAuth := ""
41+ insecure := false
2142
2243 mockCmd := & cobra.Command {
2344 Use : "mock" ,
@@ -34,12 +55,57 @@ func setupMockCommand(rootCmd *cobra.Command) {
3455 if cmd .Flags ().Changed ("seed" ) {
3556 globalSeed = & seedValue
3657 }
37- runMockCommand (backendURL , mockAddr , mockConfigFile , globalSeed )
58+
59+ client := http .DefaultClient
60+ if proxyURL != "" {
61+ proxyURLParsed , err := url .Parse (proxyURL )
62+ if err != nil {
63+ log .Fatal ().Err (err ).Msg ("Failed to parse proxy URL" )
64+ }
65+ if proxyAuth != "" {
66+ if ! strings .Contains (proxyAuth , ":" ) {
67+ password := askPassword ("enter password for proxy authentication: " )
68+ proxyAuth = proxyAuth + ":" + password
69+ }
70+ proxyURLParsed .User = url .UserPassword (strings .Split (proxyAuth , ":" )[0 ], strings .Split (proxyAuth , ":" )[1 ])
71+ }
72+ client .Transport = & http.Transport {
73+ Proxy : http .ProxyURL (proxyURLParsed ),
74+ }
75+ }
76+
77+ if insecure {
78+ if client .Transport == nil {
79+ client .Transport = & http.Transport {
80+ TLSClientConfig : & tls.Config {InsecureSkipVerify : true }, //nolint:gosec
81+ }
82+ } else {
83+ client .Transport .(* http.Transport ).TLSClientConfig = & tls.Config {InsecureSkipVerify : true } //nolint:gosec
84+ }
85+ }
86+
87+ if serverAuth != "" {
88+ if ! strings .Contains (serverAuth , ":" ) {
89+ password := askPassword ("enter password for server authentication: " )
90+ proxyAuth = proxyAuth + ":" + password
91+ }
92+ client .Transport = & TransportWithAuth {
93+ wrapped : client .Transport ,
94+ user : strings .Split (serverAuth , ":" )[0 ],
95+ pass : strings .Split (serverAuth , ":" )[1 ],
96+ }
97+ }
98+
99+ runMockCommand (backendURL , mockAddr , mockConfigFile , globalSeed , client )
38100 },
39101 Args : cobra .ExactArgs (1 ),
40102 }
41103
42104 mockCmd .PersistentFlags ().StringVarP (& mockAddr , "port" , "p" , mockAddr , "address and port number" )
105+ mockCmd .PersistentFlags ().StringVarP (& proxyURL , "proxy" , "x" , proxyURL , "use the specified proxy to perform backend request" )
106+ mockCmd .PersistentFlags ().StringVarP (& proxyAuth , "proxy-user" , "U" , proxyAuth , "specify user:password to use for proxy authentication" )
107+ mockCmd .PersistentFlags ().StringVarP (& serverAuth , "user" , "u" , serverAuth , "specify user:password to use for server authentication" )
108+ mockCmd .PersistentFlags ().BoolVarP (& insecure , "insecure" , "k" , insecure , "allow insecure server connections when using SSL" )
43109 addFlag (mockCmd , flagBufferSize )
44110 // addFlag(mockCmd, flagCatchErrors) // could use
45111 addFlag (mockCmd , flagConfigRoute )
@@ -56,7 +122,21 @@ func setupMockCommand(rootCmd *cobra.Command) {
56122 rootCmd .AddCommand (mockCmd )
57123}
58124
59- func runMockCommand (backendURL , mockAddr , configFile string , globalSeed * int64 ) {
125+ type TransportWithAuth struct {
126+ wrapped http.RoundTripper
127+ user string
128+ pass string
129+ }
130+
131+ func (t * TransportWithAuth ) RoundTrip (req * http.Request ) (* http.Response , error ) {
132+ req .SetBasicAuth (t .user , t .pass )
133+ if t .wrapped == nil {
134+ return http .DefaultTransport .RoundTrip (req )
135+ }
136+ return t .wrapped .RoundTrip (req )
137+ }
138+
139+ func runMockCommand (backendURL , mockAddr , configFile string , globalSeed * int64 , client * http.Client ) {
60140 pimo .InjectMasks ()
61141 statistics .Reset ()
62142
@@ -72,7 +152,7 @@ func runMockCommand(backendURL, mockAddr, configFile string, globalSeed *int64)
72152 log .Fatal ().Err (err ).Msg ("Failed to parse backend URL" )
73153 }
74154
75- ctx , err := cfg .Build (backend , globalSeed , cachesToLoad )
155+ ctx , err := cfg .Build (backend , globalSeed , cachesToLoad , client )
76156 if err != nil {
77157 log .Fatal ().Err (err ).Msgf ("Failed to build routes from %s" , configFile )
78158 }
0 commit comments