Skip to content

Commit

Permalink
Add --output-http-compatibility-mode
Browse files Browse the repository at this point in the history
Add support for using default Go HTTP client
  • Loading branch information
buger committed Mar 10, 2019
1 parent 707b311 commit a8cfaa7
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 16 deletions.
43 changes: 43 additions & 0 deletions http_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"log"
"net"
"net/http"
"net/http/httputil"
"net/url"
"runtime/debug"
"strconv"
Expand Down Expand Up @@ -41,6 +42,7 @@ type HTTPClientConfig struct {
ConnectionTimeout time.Duration
Timeout time.Duration
ResponseBufferSize int
CompatibilityMode bool
}

type HTTPClient struct {
Expand All @@ -53,6 +55,7 @@ type HTTPClient struct {
proxyAuth string
respBuf []byte
config *HTTPClientConfig
goClient *http.Client
redirectsCount int
}

Expand Down Expand Up @@ -80,6 +83,13 @@ func NewHTTPClient(baseURL string, config *HTTPClientConfig) *HTTPClient {
client.respBuf = make([]byte, config.ResponseBufferSize)
client.config = config

if config.CompatibilityMode {
client.goClient = &http.Client{
// #TODO
// CheckRedirect: redirectPolicyFunc,
}
}

if u.User != nil {
client.auth = "Basic " + base64.StdEncoding.EncodeToString([]byte(u.User.String()))
}
Expand Down Expand Up @@ -194,6 +204,35 @@ func (c *HTTPClient) isAlive(readBytes *int) bool {
return true
}

func (c *HTTPClient) SendGoClient(data []byte) ([]byte, error) {
var req *http.Request
var resp *http.Response
var err error

req, err = http.ReadRequest(bufio.NewReader(bytes.NewBuffer(data)))
if err != nil {
return nil, err
}

if !c.config.OriginalHost {
req.Host = c.host
}

if c.auth != "" {
req.Header.Add("Authorization", c.auth)
}

req.URL, _ = url.ParseRequestURI(c.scheme + "://" + c.host + req.RequestURI)
req.RequestURI = ""

resp, err = c.goClient.Do(req)
if err != nil {
return nil, err
}

return httputil.DumpResponse(resp, true)
}

func (c *HTTPClient) Send(data []byte) (response []byte, err error) {
// Don't exit on panic
defer func() {
Expand All @@ -208,6 +247,10 @@ func (c *HTTPClient) Send(data []byte) (response []byte, err error) {
}
}()

if c.config.CompatibilityMode {
return c.SendGoClient(data)
}

var readBytes int
if c.conn == nil || !c.isAlive(&readBytes) {
Debug("[HTTPClient] Connecting:", c.baseURL)
Expand Down
19 changes: 19 additions & 0 deletions http_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,25 @@ func TestHTTPClientSend(t *testing.T) {
client.Send(payload("POST"))

wg.Wait()

client = NewHTTPClient(server.URL, &HTTPClientConfig{Debug: true, CompatibilityMode: true})

wg.Add(4)

if _, err := client.Send(payload("POST")); err != nil {
t.Fatal(err.Error())
}
if _, err := client.Send(payload("GET")); err != nil {
t.Fatal(err.Error())
}
if _, err := client.Send(payload("POST_CHUNKED")); err != nil {
t.Fatal(err.Error())
}
if _, err := client.Send(payload("POST")); err != nil {
t.Fatal(err.Error())
}

wg.Wait()
}

func TestHTTPClientResonseByClose(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions output_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,8 @@ func (o *FileOutput) flush() {
if stat, err := o.file.Stat(); err == nil {
o.chunkSize = int(stat.Size())
} else {
log.Println("Error accessing file sats", err)
}
log.Println("Error accessing file sats", err)
}
}
}

Expand Down
9 changes: 6 additions & 3 deletions output_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,18 @@ type HTTPOutputConfig struct {
stats bool
workersMin int
workersMax int
statsMs int
workers int
queueLen int
statsMs int
workers int
queueLen int

elasticSearch string

Timeout time.Duration
OriginalHost bool
BufferSize int

CompatibilityMode bool

Debug bool

TrackResponses bool
Expand Down Expand Up @@ -113,6 +115,7 @@ func (o *HTTPOutput) startWorker() {
OriginalHost: o.config.OriginalHost,
Timeout: o.config.Timeout,
ResponseBufferSize: o.config.BufferSize,
CompatibilityMode: o.config.CompatibilityMode,
})

deathCount := 0
Expand Down
23 changes: 12 additions & 11 deletions settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,16 @@ type AppSettings struct {
outputFile MultiOption
outputFileConfig FileOutputConfig

inputRAW MultiOption
inputRAWEngine string
inputRAWTrackResponse bool
inputRAWRealIPHeader string
inputRAWExpire time.Duration
inputRAWBpfFilter string
inputRAWTimestampType string
copyBufferSize int
inputRAWImmediateMode bool
inputRawBufferSize int
inputRAW MultiOption
inputRAWEngine string
inputRAWTrackResponse bool
inputRAWRealIPHeader string
inputRAWExpire time.Duration
inputRAWBpfFilter string
inputRAWTimestampType string
copyBufferSize int
inputRAWImmediateMode bool
inputRawBufferSize int
inputRAWOverrideSnapLen bool

middleware string
Expand Down Expand Up @@ -153,8 +153,9 @@ func init() {

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.IntVar(&Settings.outputHTTPConfig.BufferSize, "output-http-response-buffer", 0, "HTTP response buffer size, all data after this size will be discarded.")
flag.BoolVar(&Settings.outputHTTPConfig.CompatibilityMode, "output-http-compatibility-mode", false, "Use standard Go client, instead of built-in implementation. Can be slower, but more compatible.")

flag.IntVar(&Settings.outputHTTPConfig.workersMin, "output-http-workers-min", 0, "Gor uses dynamic worker scaling. Enter a number to set a minimum number of workers. default = 1.")
flag.IntVar(&Settings.outputHTTPConfig.workersMin, "output-http-workers-min", 0, "Gor uses dynamic worker scaling. Enter a number to set a minimum number of workers. default = 1.")
flag.IntVar(&Settings.outputHTTPConfig.workersMax, "output-http-workers", 0, "Gor uses dynamic worker scaling. Enter a number to set a maximum number of workers. default = 0 = unlimited.")
flag.IntVar(&Settings.outputHTTPConfig.queueLen, "output-http-queue-len", 1000, "Number of requests that can be queued for output, if all workers are busy. default = 1000")

Expand Down

0 comments on commit a8cfaa7

Please sign in to comment.