diff --git a/http_modifier.go b/http_modifier.go new file mode 100644 index 0000000..73b5203 --- /dev/null +++ b/http_modifier.go @@ -0,0 +1,11 @@ +package main + +type HTTPModifierConfig struct { + urlRegexp HTTPUrlRegexp + urlRewrite UrlRewriteMap + headerFilters HTTPHeaderFilters + headerHashFilters HTTPHeaderHashFilters + + headers HTTPHeaders + methods HTTPMethods +} \ No newline at end of file diff --git a/output_http.go b/output_http.go index cd39eed..14b630e 100644 --- a/output_http.go +++ b/output_http.go @@ -59,16 +59,10 @@ const InitialDynamicWorkers = 10 type HTTPOutputConfig struct { redirectLimit int - urlRegexp HTTPUrlRegexp - urlRewrite UrlRewriteMap - headerFilters HTTPHeaderFilters - headerHashFilters HTTPHeaderHashFilters - stats bool workers int - headers HTTPHeaders - methods HTTPMethods + modifier HTTPModifierConfig elasticSearch string } @@ -210,16 +204,16 @@ func (o *HTTPOutput) sendRequest(client *http.Client, data []byte) { return } - if len(o.config.methods) > 0 && !o.config.methods.Contains(request.Method) { + if len(o.config.modifier.methods) > 0 && !o.config.modifier.methods.Contains(request.Method) { return } - if !(o.config.urlRegexp.Good(request) && o.config.headerFilters.Good(request) && o.config.headerHashFilters.Good(request)) { + if !(o.config.modifier.urlRegexp.Good(request) && o.config.modifier.headerFilters.Good(request) && o.config.modifier.headerHashFilters.Good(request)) { return } // Rewrite the path as necessary - request.URL.Path = o.config.urlRewrite.Rewrite(request.URL.Path) + request.URL.Path = o.config.modifier.urlRewrite.Rewrite(request.URL.Path) // Change HOST of original request URL := o.address + request.URL.Path + "?" + request.URL.RawQuery @@ -227,7 +221,7 @@ func (o *HTTPOutput) sendRequest(client *http.Client, data []byte) { request.RequestURI = "" request.URL, _ = url.ParseRequestURI(URL) - for _, header := range o.config.headers { + for _, header := range o.config.modifier.headers { SetHeader(request, header.Name, header.Value) } diff --git a/output_http_test.go b/output_http_test.go index 82c8877..589cab4 100644 --- a/output_http_test.go +++ b/output_http_test.go @@ -74,8 +74,9 @@ func TestHTTPOutput(t *testing.T) { headers := HTTPHeaders{HTTPHeader{"User-Agent", "Gor"}} methods := HTTPMethods{"GET", "PUT", "POST"} + modifierConfig := HTTPModifierConfig{headers: headers, methods: methods} - output := NewHTTPOutput(listener.Addr().String(), &HTTPOutputConfig{headers: headers, methods: methods}) + output := NewHTTPOutput(listener.Addr().String(), &HTTPOutputConfig{modifier: modifierConfig}) Plugins.Inputs = []io.Reader{input} Plugins.Outputs = []io.Writer{output} diff --git a/plugins.go b/plugins.go index 65d7937..88134ef 100644 --- a/plugins.go +++ b/plugins.go @@ -96,6 +96,6 @@ func InitPlugins() { } for _, options := range Settings.outputHTTP { - registerPlugin(NewHTTPOutput, options, &HTTPOutputSettings) + registerPlugin(NewHTTPOutput, options, &Settings.outputHTTPConfig) } } diff --git a/settings.go b/settings.go index 6d917e9..669d145 100644 --- a/settings.go +++ b/settings.go @@ -31,20 +31,11 @@ type AppSettings struct { inputHTTP MultiOption outputHTTP MultiOption - outputHTTPHeaders HTTPHeaders - outputHTTPMethods HTTPMethods - outputHTTPUrlRegexp HTTPUrlRegexp - outputHTTPUrlRewrite UrlRewriteMap - outputHTTPHeaderFilters HTTPHeaderFilters - outputHTTPHeaderHashFilters HTTPHeaderHashFilters - outputHTTPElasticSearch string - outputHTTPWorkers int - outputHTTPStats bool - outputHTTPRedirects int + + outputHTTPConfig HTTPOutputConfig } var Settings AppSettings = AppSettings{} -var HTTPOutputSettings = HTTPOutputConfig{} func usage() { fmt.Printf("Gor is a simple http traffic replication tool written in Go. Its main goal is to replay traffic from production servers to staging and dev environments.\nProject page: https://github.com/buger/gor\nAuthor: leonsbox@gmail.com\nCurrent Version: %s\n\n", VERSION) @@ -75,17 +66,17 @@ func init() { flag.Var(&Settings.inputHTTP, "input-http", "Read requests from HTTP, should be explicitly sent from your application:\n\t# Listen for http on 9000\n\tgor --input-http :9000 --output-http staging.com") flag.Var(&Settings.outputHTTP, "output-http", "Forwards incoming requests to given http address.\n\t# Redirect all incoming requests to staging.com address \n\tgor --input-raw :80 --output-http http://staging.com") - flag.Var(&HTTPOutputSettings.headers, "output-http-header", "Inject additional headers to http reqest:\n\tgor --input-raw :8080 --output-http staging.com --output-http-header 'User-Agent: Gor'") - flag.Var(&HTTPOutputSettings.methods, "output-http-method", "Whitelist of HTTP methods to replay. Anything else will be dropped:\n\tgor --input-raw :8080 --output-http staging.com --output-http-method GET --output-http-method OPTIONS") - flag.Var(&HTTPOutputSettings.urlRegexp, "output-http-url-regexp", "A regexp to match requests against. Anything else will be dropped:\n\t gor --input-raw :8080 --output-http staging.com --output-http-url-regexp ^www.") - flag.Var(&HTTPOutputSettings.headerFilters, "output-http-header-filter", "A regexp to match a specific header against. Requests with non-matching headers will be dropped:\n\t gor --input-raw :8080 --output-http staging.com --output-http-header-filter api-version:^v1") - flag.Var(&HTTPOutputSettings.headerHashFilters, "output-http-header-hash-filter", "Takes a fraction of requests, consistently taking or rejecting a request based on the FNV32-1A hash of a specific header. The fraction must have a denominator that is a power of two:\n\t gor --input-raw :8080 --output-http staging.com --output-http-header-hash-filter user-id:1/4") - flag.IntVar(&HTTPOutputSettings.workers, "output-http-workers", 0, "Gor uses dynamic worker scaling by default. Enter a number to run a set number of workers.") - flag.BoolVar(&HTTPOutputSettings.stats, "output-http-stats", false, "Report http output queue stats to console every 5 seconds.") + flag.IntVar(&Settings.outputHTTPConfig.workers, "output-http-workers", 0, "Gor uses dynamic worker scaling by default. Enter a number to run a set number of workers.") + flag.IntVar(&Settings.outputHTTPConfig.redirectLimit, "output-http-redirects", 0, "Enable how often redirects should be followed.") + flag.Var(&Settings.outputHTTPConfig.modifier.headers, "output-http-header", "Inject additional headers to http reqest:\n\tgor --input-raw :8080 --output-http staging.com --output-http-header 'User-Agent: Gor'") + flag.Var(&Settings.outputHTTPConfig.modifier.methods, "output-http-method", "Whitelist of HTTP methods to replay. Anything else will be dropped:\n\tgor --input-raw :8080 --output-http staging.com --output-http-method GET --output-http-method OPTIONS") + flag.Var(&Settings.outputHTTPConfig.modifier.urlRegexp, "output-http-url-regexp", "A regexp to match requests against. Anything else will be dropped:\n\t gor --input-raw :8080 --output-http staging.com --output-http-url-regexp ^www.") + flag.Var(&Settings.outputHTTPConfig.modifier.urlRewrite, "output-http-rewrite-url", "Rewrite the requst url based on a mapping:\n\tgor --input-raw :8080 --output-http staging.com --output-http-rewrite-url /xml_test/interface.php:/api/service.do") + flag.Var(&Settings.outputHTTPConfig.modifier.headerFilters, "output-http-header-filter", "A regexp to match a specific header against. Requests with non-matching headers will be dropped:\n\t gor --input-raw :8080 --output-http staging.com --output-http-header-filter api-version:^v1") + flag.Var(&Settings.outputHTTPConfig.modifier.headerHashFilters, "output-http-header-hash-filter", "Takes a fraction of requests, consistently taking or rejecting a request based on the FNV32-1A hash of a specific header. The fraction must have a denominator that is a power of two:\n\t gor --input-raw :8080 --output-http staging.com --output-http-header-hash-filter user-id:1/4") + flag.BoolVar(&Settings.outputHTTPConfig.stats, "output-http-stats", false, "Report http output queue stats to console every 5 seconds.") - flag.StringVar(&HTTPOutputSettings.elasticSearch, "output-http-elasticsearch", "", "Send request and response stats to ElasticSearch:\n\tgor --input-raw :8080 --output-http staging.com --output-http-elasticsearch 'es_host:api_port/index_name'") - flag.Var(&HTTPOutputSettings.urlRewrite, "output-http-rewrite-url", "Rewrite the requst url based on a mapping:\n\tgor --input-raw :8080 --output-http staging.com --output-http-rewrite-url /xml_test/interface.php:/api/service.do") - flag.IntVar(&HTTPOutputSettings.redirectLimit, "output-http-redirects", 0, "Enable how often redirects should be followed.") + flag.StringVar(&Settings.outputHTTPConfig.elasticSearch, "output-http-elasticsearch", "", "Send request and response stats to ElasticSearch:\n\tgor --input-raw :8080 --output-http staging.com --output-http-elasticsearch 'es_host:api_port/index_name'") } func Debug(args ...interface{}) {