From 74225ebb2236a46fd18a8fa4fa7de441497c13c4 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Mon, 1 May 2017 17:56:50 +0200 Subject: [PATCH 01/20] Rename all package imports from `gor` to `goreplay` --- COMM-LICENSE | 4 ++-- Dockerfile | 4 ++-- Makefile | 2 +- README.md | 10 +++++----- elasticsearch.go | 2 +- examples/middleware/token_modifier.go | 2 +- http_client.go | 2 +- http_client_test.go | 2 +- http_modifier.go | 2 +- http_modifier_test.go | 2 +- http_prettifier.go | 2 +- input_http_test.go | 2 +- input_raw.go | 4 ++-- input_raw_test.go | 2 +- kafka.go | 2 +- middleware_test.go | 2 +- output_http.go | 2 +- output_kafka.go | 2 +- proto/proto.go | 2 +- raw_socket_listener/listener.go | 4 ++-- raw_socket_listener/tcp_message.go | 2 +- vendor/vendor.json | 2 +- 22 files changed, 30 insertions(+), 30 deletions(-) diff --git a/COMM-LICENSE b/COMM-LICENSE index b5d8678..1b5fa2e 100644 --- a/COMM-LICENSE +++ b/COMM-LICENSE @@ -36,7 +36,7 @@ under the terms of the GNU Lesser General Public License versions 3.0 5. Fees and Payment. The Software license fees will be due and payable in full as set forth in the applicable invoice or at the time of purchase. If the Software does not function properly within two weeks of purchase, please contact us within those two weeks for a refund. You shall be responsible for all taxes, withholdings, duties and levies arising from the order (excluding taxes based on the net income of GoReplay LLC). -6. Support, Maintenance and Services. Subject to the terms and conditions of this Agreement, as set forth in your invoice, and as set forth on the GoReplay Pro support page (https://github.com/buger/gor/wiki/Pro-Support), support and maintenance services may be included with the purchase of your license subscription. +6. Support, Maintenance and Services. Subject to the terms and conditions of this Agreement, as set forth in your invoice, and as set forth on the GoReplay Pro support page (https://github.com/buger/goreplay/wiki/Pro-Support), support and maintenance services may be included with the purchase of your license subscription. 7. Term of Agreement. @@ -72,7 +72,7 @@ In no event will GoReplay LLC liability exceed the Software license price as ind 13.1 Entire Agreement. This Agreement sets forth our entire agreement with respect to the Software and the subject matter hereof and supersedes all prior and contemporaneous understandings and agreements whether written or oral. -13.2 Amendment. GoReplay LLC reserves the right, in its sole discretion, to amend this Agreement from time. Amendments to this Agreement can be located at: https://github.com/buger/gor/blob/master/COMM-LICENSE. +13.2 Amendment. GoReplay LLC reserves the right, in its sole discretion, to amend this Agreement from time. Amendments to this Agreement can be located at: https://github.com/buger/goreplay/blob/master/COMM-LICENSE. 13.3 Assignment. You may not assign this Agreement or any of its rights under this Agreement without the prior written consent of GoReplay LLC and any attempted assignment without such consent shall be void. diff --git a/Dockerfile b/Dockerfile index f3d1874..70bb5e3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,8 +15,8 @@ RUN wget http://www.tcpdump.org/release/libpcap-1.7.4.tar.gz && tar xzf libpcap- RUN go get github.com/google/gopacket RUN go get -u github.com/golang/lint/golint -WORKDIR /go/src/github.com/buger/gor/ -ADD . /go/src/github.com/buger/gor/ +WORKDIR /go/src/github.com/buger/goreplay/ +ADD . /go/src/github.com/buger/goreplay/ RUN wget http://archive.apache.org/dist/commons/io/binaries/commons-io-2.4-bin.tar.gz && tar xzf commons-io-2.4-bin.tar.gz && cd commons-io-2.4 && mv commons-io-2.4.jar /tmp/ RUN wget http://archive.apache.org/dist/commons/codec/binaries/commons-codec-1.9-bin.tar.gz && tar xzf commons-codec-1.9-bin.tar.gz diff --git a/Makefile b/Makefile index a6f3326..57a9f3f 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ SOURCE = emitter.go gor.go gor_stat.go input_dummy.go input_file.go input_raw.go input_tcp.go limiter.go output_dummy.go output_null.go output_file.go input_http.go output_http.go output_tcp.go plugins.go settings.go test_input.go elasticsearch.go http_modifier.go http_modifier_settings.go http_client.go middleware.go protocol.go output_file_settings.go output_kafka.go -SOURCE_PATH = /go/src/github.com/buger/gor/ +SOURCE_PATH = /go/src/github.com/buger/goreplay/ PORT = 8000 FADDR = :8000 RUN = docker run -v `pwd`:$(SOURCE_PATH) -p 0.0.0.0:$(PORT):$(PORT) -i -t gor diff --git a/README.md b/README.md index ef70b72..7a05b77 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![GitHub release](https://img.shields.io/github/release/buger/gor.svg?maxAge=3600)](https://github.com/buger/gor/releases) [![codebeat](https://codebeat.co/badges/6427d589-a78e-416c-a546-d299b4089893)](https://codebeat.co/projects/github-com-buger-gor) [![Go Report Card](https://goreportcard.com/badge/github.com/buger/gor)](https://goreportcard.com/report/github.com/buger/gor) [![Join the chat at https://gitter.im/buger/gor](https://badges.gitter.im/buger/gor.svg)](https://gitter.im/buger/gor?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![GitHub release](https://img.shields.io/github/release/buger/gor.svg?maxAge=3600)](https://github.com/buger/goreplay/releases) [![codebeat](https://codebeat.co/badges/6427d589-a78e-416c-a546-d299b4089893)](https://codebeat.co/projects/github-com-buger-gor) [![Go Report Card](https://goreportcard.com/badge/github.com/buger/gor)](https://goreportcard.com/report/github.com/buger/gor) [![Join the chat at https://gitter.im/buger/gor](https://badges.gitter.im/buger/gor.svg)](https://gitter.im/buger/gor?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ![Go Replay](http://i.imgur.com/ZG2ki5n.png) @@ -18,17 +18,17 @@ Here is basic workflow: The listener server catches http traffic and sends it to ![Diagram](http://i.imgur.com/9mqj2SK.png) -Check [latest documentation](http://github.com/buger/gor/wiki). +Check [latest documentation](http://github.com/buger/goreplay/wiki). ## Installation -Download latest binary from https://github.com/buger/gor/releases or [compile by yourself](https://github.com/buger/gor/wiki/Compilation). +Download latest binary from https://github.com/buger/goreplay/releases or [compile by yourself](https://github.com/buger/goreplay/wiki/Compilation). ## Getting started The most basic setup will be `sudo ./gor --input-raw :8000 --output-stdout` which acts like tcpdump. If you already have test environment you can start replaying: `sudo ./gor --input-raw :8000 --output-http http://staging.env`. -See the our [documentation](https://github.com/buger/gor/wiki/) and [Getting started](https://github.com/buger/gor/wiki/Getting-Started) page for more info. +See the our [documentation](https://github.com/buger/goreplay/wiki/) and [Getting started](https://github.com/buger/goreplay/wiki/Getting-Started) page for more info. ## Newsletter Subscribe to our [newsletter](https://www.getdrip.com/forms/89690474/submissions/new) to stay informed about the latest features and changes to Gor project. @@ -39,7 +39,7 @@ We have created a [GoReplay PRO](https://goreplay.org/pro.html) extension which ## Problems? -If you have a problem, please review the [FAQ](https://github.com/buger/gor/wiki/FAQ) and [Troubleshooting](https://github.com/buger/gor/wiki/Troubleshooting) wiki pages. Searching the [issues](https://github.com/buger/gor/issues) for your problem is also a good idea. +If you have a problem, please review the [FAQ](https://github.com/buger/goreplay/wiki/FAQ) and [Troubleshooting](https://github.com/buger/goreplay/wiki/Troubleshooting) wiki pages. Searching the [issues](https://github.com/buger/goreplay/issues) for your problem is also a good idea. All bug-reports and suggestions should go though Github Issues or our [Google Group](https://groups.google.com/forum/#!forum/gor-users) (you can just send email to gor-users@googlegroups.com). If you have a private question feel free to send email to support@gortool.com. diff --git a/elasticsearch.go b/elasticsearch.go index 2635b89..57fa863 100644 --- a/elasticsearch.go +++ b/elasticsearch.go @@ -2,7 +2,7 @@ package main import ( "encoding/json" - "github.com/buger/gor/proto" + "github.com/buger/goreplay/proto" "github.com/mattbaird/elastigo/lib" "log" "regexp" diff --git a/examples/middleware/token_modifier.go b/examples/middleware/token_modifier.go index 6536c0d..b715d76 100644 --- a/examples/middleware/token_modifier.go +++ b/examples/middleware/token_modifier.go @@ -24,7 +24,7 @@ import ( "bytes" "encoding/hex" "fmt" - "github.com/buger/gor/proto" + "github.com/buger/goreplay/proto" "os" ) diff --git a/http_client.go b/http_client.go index 1ed8f88..e30de04 100644 --- a/http_client.go +++ b/http_client.go @@ -15,7 +15,7 @@ import ( "syscall" "time" - "github.com/buger/gor/proto" + "github.com/buger/goreplay/proto" ) var httpMu sync.Mutex diff --git a/http_client_test.go b/http_client_test.go index 917c7c9..6d743ed 100644 --- a/http_client_test.go +++ b/http_client_test.go @@ -3,7 +3,7 @@ package main import ( "bytes" "crypto/rand" - "github.com/buger/gor/proto" + "github.com/buger/goreplay/proto" "io/ioutil" _ "log" "net" diff --git a/http_modifier.go b/http_modifier.go index fbca0c3..8d000ee 100644 --- a/http_modifier.go +++ b/http_modifier.go @@ -4,7 +4,7 @@ import ( "bytes" "hash/fnv" - "github.com/buger/gor/proto" + "github.com/buger/goreplay/proto" ) type HTTPModifier struct { diff --git a/http_modifier_test.go b/http_modifier_test.go index dc53250..343be5f 100644 --- a/http_modifier_test.go +++ b/http_modifier_test.go @@ -2,7 +2,7 @@ package main import ( "bytes" - "github.com/buger/gor/proto" + "github.com/buger/goreplay/proto" "testing" ) diff --git a/http_prettifier.go b/http_prettifier.go index 9a785c6..fa4360c 100644 --- a/http_prettifier.go +++ b/http_prettifier.go @@ -1,7 +1,7 @@ package main import ( - "github.com/buger/gor/proto" + "github.com/buger/goreplay/proto" "bytes" "compress/gzip" "strconv" diff --git a/input_http_test.go b/input_http_test.go index 19f460e..5f6dd4c 100644 --- a/input_http_test.go +++ b/input_http_test.go @@ -1,7 +1,7 @@ package main import ( - "github.com/buger/gor/proto" + "github.com/buger/goreplay/proto" "io" "log" "net/http" diff --git a/input_raw.go b/input_raw.go index 0236a2c..e809c33 100644 --- a/input_raw.go +++ b/input_raw.go @@ -1,8 +1,8 @@ package main import ( - "github.com/buger/gor/proto" - raw "github.com/buger/gor/raw_socket_listener" + "github.com/buger/goreplay/proto" + raw "github.com/buger/goreplay/raw_socket_listener" "log" "net" "time" diff --git a/input_raw_test.go b/input_raw_test.go index 9ad8065..30d3425 100644 --- a/input_raw_test.go +++ b/input_raw_test.go @@ -2,7 +2,7 @@ package main import ( "bytes" - "github.com/buger/gor/proto" + "github.com/buger/goreplay/proto" "io" "io/ioutil" "log" diff --git a/kafka.go b/kafka.go index 0c23032..bc5c56a 100644 --- a/kafka.go +++ b/kafka.go @@ -4,7 +4,7 @@ import ( "bytes" "fmt" "github.com/Shopify/sarama" - "github.com/buger/gor/proto" + "github.com/buger/goreplay/proto" ) // KafkaConfig should contains required information to diff --git a/middleware_test.go b/middleware_test.go index beaed15..6e65ee2 100644 --- a/middleware_test.go +++ b/middleware_test.go @@ -4,7 +4,7 @@ import ( "bytes" "crypto/rand" "encoding/hex" - "github.com/buger/gor/proto" + "github.com/buger/goreplay/proto" "io" "net/http" "net/http/httptest" diff --git a/output_http.go b/output_http.go index bf262cc..8a62efd 100644 --- a/output_http.go +++ b/output_http.go @@ -5,7 +5,7 @@ import ( "sync/atomic" "time" - "github.com/buger/gor/proto" + "github.com/buger/goreplay/proto" ) const initialDynamicWorkers = 10 diff --git a/output_kafka.go b/output_kafka.go index ec9855d..7a6309a 100644 --- a/output_kafka.go +++ b/output_kafka.go @@ -4,7 +4,7 @@ import ( "encoding/json" "github.com/Shopify/sarama" "github.com/Shopify/sarama/mocks" - "github.com/buger/gor/proto" + "github.com/buger/goreplay/proto" "io" "log" "strings" diff --git a/proto/proto.go b/proto/proto.go index bb0398c..68377e2 100644 --- a/proto/proto.go +++ b/proto/proto.go @@ -18,7 +18,7 @@ package proto import ( "bytes" - "github.com/buger/gor/byteutils" + "github.com/buger/goreplay/byteutils" ) // In HTTP newline defined by 2 bytes (for both windows and *nix support) diff --git a/raw_socket_listener/listener.go b/raw_socket_listener/listener.go index 7edd639..63050c1 100644 --- a/raw_socket_listener/listener.go +++ b/raw_socket_listener/listener.go @@ -16,7 +16,7 @@ import ( "bytes" "encoding/binary" "fmt" - "github.com/buger/gor/proto" + "github.com/buger/goreplay/proto" "github.com/google/gopacket" "github.com/google/gopacket/layers" "github.com/google/gopacket/pcap" @@ -241,7 +241,7 @@ func (e *DeviceNotFoundError) Error() string { devices, _ := pcap.FindAllDevs() if len(devices) == 0 { - return "Can't get list of network interfaces, ensure that you running Gor as root user or sudo.\nTo run as non-root users see this docs https://github.com/buger/gor/wiki/Running-as-non-root-user" + return "Can't get list of network interfaces, ensure that you running Gor as root user or sudo.\nTo run as non-root users see this docs https://github.com/buger/goreplay/wiki/Running-as-non-root-user" } var msg string diff --git a/raw_socket_listener/tcp_message.go b/raw_socket_listener/tcp_message.go index d2d2abb..59d280f 100644 --- a/raw_socket_listener/tcp_message.go +++ b/raw_socket_listener/tcp_message.go @@ -5,7 +5,7 @@ import ( "crypto/sha1" "encoding/binary" "encoding/hex" - "github.com/buger/gor/proto" + "github.com/buger/goreplay/proto" "log" "net" "strconv" diff --git a/vendor/vendor.json b/vendor/vendor.json index 0f8adaf..6da1d5c 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -46,7 +46,7 @@ }, { "checksumSHA1": "U2Ydh7vEAKlN0Wq22n1JpefF7uY=", - "origin": "github.com/buger/gor/vendor/github.com/google/gopacket", + "origin": "github.com/buger/goreplay/vendor/github.com/google/gopacket", "path": "github.com/google/gopacket", "revision": "b09bf408520f7646e29b7033d9adb00ed779a1c4", "revisionTime": "2016-05-12T15:06:07Z" From d9ce263c6a8bd83d7b2ebae5104166dd17532958 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Tue, 2 May 2017 17:42:13 +0200 Subject: [PATCH 02/20] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 7a05b77..0b09462 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ ## https://goreplay.org/ +## We just released a new version, see announcement https://leonsbox.com/goreplay-v0-16-and-4th-anniversary-5408b1fd72e0 + ## About GoReplay is the simplest and safest way to test your app using real traffic before you put it into production. From de47f6d6f62ba21cb4edb58364a63fb857dca237 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Wed, 17 May 2017 21:21:44 +0300 Subject: [PATCH 03/20] Fix httpHeader when header value contain ":" --- middleware/middleware.js | 13 ++++++++----- middleware/package.json | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/middleware/middleware.js b/middleware/middleware.js index d252576..431c384 100755 --- a/middleware/middleware.js +++ b/middleware/middleware.js @@ -255,14 +255,17 @@ function httpHeader(payload, name) { } header.start = -1 + header.valueStart = -1 continue; } else if (c == 10) { // "\r" i++ continue; } else if (c == 58) { // ":" Header/value separator symbol - header.valueStart = i + 1; - i++ - continue; + if (header.valueStart == -1) { + header.valueStart = i + 1; + i++ + continue; + } } if (header.start == -1) header.start = i; @@ -511,9 +514,9 @@ function TEST_httpBodyParam() { } function TEST_httpHeader() { - const examplePayload = "GET / HTTP/1.1\r\nUser-Agent: Node\r\nContent-Length:5\r\n\r\nhello"; + const examplePayload = "GET / HTTP/1.1\r\nHost: localhost:3000\r\nUser-Agent: Node\r\nContent-Length:5\r\n\r\nhello"; - let expected = {"User-Agent": "Node", "Content-Length": "5"} + let expected = {"Host": "localhost:3000", "User-Agent": "Node", "Content-Length": "5"} Object.keys(expected).forEach(function(name){ let payload = Buffer.from(examplePayload); diff --git a/middleware/package.json b/middleware/package.json index 72a450d..463a03f 100644 --- a/middleware/package.json +++ b/middleware/package.json @@ -1,6 +1,6 @@ { "name": "goreplay_middleware", - "version": "0.1.11", + "version": "0.1.12", "description": "Package for writing middleware for GoReplay https://goreplay.org", "main": "middleware.js", "scripts": { From a49b250ab482ca5e767f62eaf159802fad81f12e Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Wed, 17 May 2017 21:32:08 +0300 Subject: [PATCH 04/20] Fix typo --- middleware/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleware/README.md b/middleware/README.md index a2facc7..b82cf40 100644 --- a/middleware/README.md +++ b/middleware/README.md @@ -30,7 +30,7 @@ gor.on('request', function(data) { // GET / HTTP/1.1\r\n // User-Agent: Golang\r\n // \r\n - data.html + data.http // Meta is an array size of 3, containing: // 1. request type - 1, 2 or 3 (which maps to `request`, `respose` and `replay`) From 8f450c77a6f7b01faebbe2590baed7686f090a2d Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Wed, 17 May 2017 21:34:26 +0300 Subject: [PATCH 05/20] Update README.md --- middleware/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/middleware/README.md b/middleware/README.md index b82cf40..c8a9cf1 100644 --- a/middleware/README.md +++ b/middleware/README.md @@ -32,10 +32,11 @@ gor.on('request', function(data) { // \r\n data.http - // Meta is an array size of 3, containing: + // Meta is an array size of 4, containing: // 1. request type - 1, 2 or 3 (which maps to `request`, `respose` and `replay`) - // 2. timestamp of when request was made (for responses it is time of request start too) - // 3. latency - time difference between request start and finish. For `request` is zero. + // 2. uuid - request unique identifier. Request responses have the same ID as their request. + // 3. timestamp of when request was made (for responses it is time of request start too) + // 4. latency - time difference between request start and finish. For `request` is zero. data.meta // Unique request ID. It should be same for `request`, `response` and `replay` events of the same request. From c23f95d4cfea27669c1a7fad18ed9a50ba0acf47 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Wed, 17 May 2017 22:47:05 +0300 Subject: [PATCH 06/20] Add httpMethod function --- middleware/middleware.js | 20 +++++++++++++++++++- middleware/package.json | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/middleware/middleware.js b/middleware/middleware.js index 431c384..306c17b 100755 --- a/middleware/middleware.js +++ b/middleware/middleware.js @@ -183,6 +183,11 @@ function searchResponses(id, searchPattern, callback) { // \r\n // hello +function httpMethod(payload) { + var pEnd = payload.indexOf(' '); + return payload.slice(0, pEnd).toString("ascii"); +} + function httpPath(payload) { var pStart = payload.indexOf(' ') + 1; var pEnd = payload.indexOf(' ', pStart); @@ -351,6 +356,7 @@ module.exports = { parseMessage: parseMessage, searchResponses: searchResponses, httpPath: httpPath, + httpMethod: httpMethod, setHttpPath: setHttpPath, httpPathParam: httpPathParam, setHttpPathParam: setHttpPathParam, @@ -371,7 +377,7 @@ module.exports = { // =========== Tests ============== function testRunner(){ - ["init", "parseMessage", "httpPath", "setHttpHeader", "httpPathParam", "httpHeader", "httpBody", "setHttpBody", "httpBodyParam", "httpCookie", "setHttpCookie"].forEach(function(t){ + ["init", "parseMessage", "httpMethod", "httpPath", "setHttpHeader", "httpPathParam", "httpHeader", "httpBody", "setHttpBody", "httpBodyParam", "httpCookie", "setHttpCookie"].forEach(function(t){ console.log(`====== Start ${t} =======`) eval(`TEST_${t}()`) console.log(`====== End ${t} =======`) @@ -451,6 +457,18 @@ function TEST_httpPath() { } } +function TEST_httpMethod() { + const examplePayload = "GET /test HTTP/1.1\r\n\r\n"; + + let payload = Buffer.from(examplePayload); + let method = httpMethod(payload); + + if (method != "GET") { + return fail(`Path '${method}' != 'GET'`) + } +} + + function TEST_httpPathParam() { let p = Buffer.from("GET / HTTP/1.1\r\n\r\n"); diff --git a/middleware/package.json b/middleware/package.json index 463a03f..698165f 100644 --- a/middleware/package.json +++ b/middleware/package.json @@ -1,6 +1,6 @@ { "name": "goreplay_middleware", - "version": "0.1.12", + "version": "0.1.13", "description": "Package for writing middleware for GoReplay https://goreplay.org", "main": "middleware.js", "scripts": { From cdd818fe7796c1d9945039443b7c8e1a2475e798 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Wed, 17 May 2017 22:48:45 +0300 Subject: [PATCH 07/20] Update README.md --- middleware/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/middleware/README.md b/middleware/README.md index c8a9cf1..b53a0f2 100644 --- a/middleware/README.md +++ b/middleware/README.md @@ -98,6 +98,7 @@ gor.on("request", function(req) { Package expose following functions to process raw HTTP payloads: * `init` - initialize middleware object, start reading from STDIN. * `httpPath` - URL path of the request: `gor.httpPath(req.http)` +* `httpMethod` - Http method: 'GET', 'POST', etc. `gor.httpMethod(req.http)`. * `setHttpPath` - update URL path: `req.http = gor.setHttpPath(req.http, newPath)` * `httpPathParam` - get param from URL path: `gor.httpPathParam(req.http, queryParam)` * `setHttpPathParam` - set URL param: `req.http = gor.setHttpPathParam(req.http, queryParam, value)` From 064519ce8975bb1ff1faee0edafeae4f88dce9ab Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Thu, 18 May 2017 16:40:42 +0300 Subject: [PATCH 08/20] Rename Dockerfile to Dockerfile.dev --- Dockerfile => Dockerfile.dev | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename Dockerfile => Dockerfile.dev (99%) diff --git a/Dockerfile b/Dockerfile.dev similarity index 99% rename from Dockerfile rename to Dockerfile.dev index 70bb5e3..fd7850c 100644 --- a/Dockerfile +++ b/Dockerfile.dev @@ -21,4 +21,4 @@ ADD . /go/src/github.com/buger/goreplay/ RUN wget http://archive.apache.org/dist/commons/io/binaries/commons-io-2.4-bin.tar.gz && tar xzf commons-io-2.4-bin.tar.gz && cd commons-io-2.4 && mv commons-io-2.4.jar /tmp/ RUN wget http://archive.apache.org/dist/commons/codec/binaries/commons-codec-1.9-bin.tar.gz && tar xzf commons-codec-1.9-bin.tar.gz RUN javac -cp commons-io-2.4/commons-io-2.4.jar -cp commons-codec-1.9/commons-codec-1.9.jar ./examples/middleware/echo.java -RUN go get \ No newline at end of file +RUN go get From d755c579e4e122e50af8d9735377f8c7a0033fee Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Thu, 18 May 2017 16:47:41 +0300 Subject: [PATCH 09/20] Create Dockerfile --- Dockerfile | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0947b59 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,6 @@ +FROM alpine:latest + +RUN wget https://github.com/buger/goreplay/releases/download/v0.16.0.2/gor_0.16.0_x64.tar.gz -o gor.tar.gz +RUN tar xzf gor.tar.gz + +ENTRYPOINT ./gor From 2b20c1107a147b48080eedabe4be483ff5ee0f09 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Thu, 18 May 2017 16:52:46 +0300 Subject: [PATCH 10/20] Update Dockerfile From a1a4460c90d4db966e6c302871e20bfca15ecb0a Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Thu, 18 May 2017 16:53:11 +0300 Subject: [PATCH 11/20] Update Dockerfile --- Dockerfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0947b59..21eb2c3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,4 @@ FROM alpine:latest - RUN wget https://github.com/buger/goreplay/releases/download/v0.16.0.2/gor_0.16.0_x64.tar.gz -o gor.tar.gz RUN tar xzf gor.tar.gz - ENTRYPOINT ./gor From 23771b899450ccabfc338622da844193b9b011e2 Mon Sep 17 00:00:00 2001 From: KingLebron Date: Tue, 23 May 2017 11:06:12 +0800 Subject: [PATCH 12/20] [Spelling Error] Change 'dirrectory' to 'directory' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit :) --- gor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gor.go b/gor.go index b9cf1f8..cb2244c 100644 --- a/gor.go +++ b/gor.go @@ -52,7 +52,7 @@ func main() { } dir, _ := os.Getwd() - log.Println("Started example file server for current dirrectory on address ", args[1]) + log.Println("Started example file server for current directory on address ", args[1]) log.Fatal(http.ListenAndServe(args[1], loggingMiddleware(http.FileServer(http.Dir(dir))))) } else { From 4fe95be416d8b7204cd4fdb459909af991588a80 Mon Sep 17 00:00:00 2001 From: Michael Marino Date: Thu, 27 Apr 2017 15:35:41 +0200 Subject: [PATCH 13/20] Add example of middleware for javascript --- examples/middleware/echo.js | 57 +++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100755 examples/middleware/echo.js diff --git a/examples/middleware/echo.js b/examples/middleware/echo.js new file mode 100755 index 0000000..f7a823f --- /dev/null +++ b/examples/middleware/echo.js @@ -0,0 +1,57 @@ +#!/usr/bin/env node +const readline = require("readline"); +const StringDecoder = require("string_decoder").StringDecoder + +const rl = readline.createInterface({ + input: process.stdin +}); + +var ignoreIds = new Set(); +var ignoreAddresses = "/api"; +const decoder = new StringDecoder("utf8"); + +function convertHexString(hex) { + var bytes = []; + for (var i = 0; i < hex.length - 1; i += 2) { + bytes.push(parseInt(hex.substr(i, 2), 16)); + } + return decoder.write(Buffer.from(bytes)); +} + +function log(output) { + console.error("==================="); + console.error(output); +} + +function shouldOutputLine(request) { + const components = request.split("\n"); + const header = components[0].split(" "); + const type = parseInt(header[0]); + const tag = header[1]; + + if (type === 3) { + return true; + } + if (type === 1) { + // Check if it's oauth + const endpoint = components[1].split(" ")[1]; + if (!endpoint.startsWith(ignoreAddresses)) { + ignoreIds.add(tag); + return false; + } + } else if (type === 2) { + if (ignoreIds.has(tag)) { + ignoreIds.delete(tag); + return false; + } + } + return true; +} + +rl.on("line", (input) => { + const str = convertHexString(input); + console.log(input); + if (shouldOutputLine(str)) { + log(str); + } +}); From aa4a878436bc49b1ed3413e4f7e70ac6bd42f496 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Sat, 24 Jun 2017 20:35:35 +0200 Subject: [PATCH 14/20] Handle gzip encoding error Fix #470 --- emitter.go | 3 +++ http_prettifier.go | 1 + 2 files changed, 4 insertions(+) diff --git a/emitter.go b/emitter.go index e2c8beb..8e4180c 100644 --- a/emitter.go +++ b/emitter.go @@ -102,6 +102,9 @@ func CopyMulty(src io.Reader, writers ...io.Writer) (err error) { if Settings.prettifyHTTP { payload = prettifyHTTP(payload) + if len(payload) == 0 { + continue + } } if Settings.splitOutput { diff --git a/http_prettifier.go b/http_prettifier.go index fa4360c..3a6c426 100644 --- a/http_prettifier.go +++ b/http_prettifier.go @@ -52,6 +52,7 @@ func prettifyHTTP(p []byte) []byte { if err != nil { Debug("[Prettifier] GZIP encoding error:", err) + return []byte{} } content, _ = ioutil.ReadAll(g) From b3dffae66fc755eb307dcaecabd25d15ba1a172c Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Tue, 27 Jun 2017 13:56:14 +0200 Subject: [PATCH 15/20] When using --input-file it should exit once file is fully read --- gor.go | 11 ++++++----- input_file.go | 7 +++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/gor.go b/gor.go index cb2244c..6823eb2 100644 --- a/gor.go +++ b/gor.go @@ -32,7 +32,10 @@ func loggingMiddleware(next http.Handler) http.Handler { }) } +var closeCh chan int + func main() { + closeCh = make(chan int) // // Don't exit on panic // defer func() { // if r := recover(); r != nil { @@ -84,17 +87,15 @@ func main() { if Settings.exitAfter > 0 { log.Println("Running gor for a duration of", Settings.exitAfter) - closeCh := make(chan int) + closeCh = make(chan int) time.AfterFunc(Settings.exitAfter, func() { log.Println("Stopping gor after", Settings.exitAfter) close(closeCh) }) - - Start(closeCh) - } else { - Start(nil) } + + Start(closeCh) } func finalize() { diff --git a/input_file.go b/input_file.go index 6dfffc4..3346aa1 100644 --- a/input_file.go +++ b/input_file.go @@ -222,6 +222,13 @@ func (i *FileInput) emit() { } log.Printf("FileInput: end of file '%s'\n", i.path) + + // For now having fixed timeout is temporary solution + // Further should be modified, so outputs can report if their queue empty or not + time.Sleep(time.Second) + if closeCh != nil { + close(closeCh) + } } func (i *FileInput) Close() error { From 2680ce9dd4405456e739711c9be86cd5fcc8f6d8 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Tue, 27 Jun 2017 14:01:17 +0200 Subject: [PATCH 16/20] Fix #467 --- proto/proto.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/proto/proto.go b/proto/proto.go index 68377e2..aa4f129 100644 --- a/proto/proto.go +++ b/proto/proto.go @@ -345,6 +345,10 @@ func Path(payload []byte) []byte { start := bytes.IndexByte(payload, ' ') + 1 end := bytes.IndexByte(payload[start:], ' ') + if len(payload) < start + end { + return []byte{} + } + return payload[start : start+end] } From 03767d1a778f2bf594765e9ce5e5d46ff4d97ea6 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Tue, 27 Jun 2017 14:24:43 +0200 Subject: [PATCH 17/20] Add support for HTTP 1.0 and less --- proto/proto.go | 5 +++-- proto/proto_test.go | 14 ++++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/proto/proto.go b/proto/proto.go index aa4f129..1ef2449 100644 --- a/proto/proto.go +++ b/proto/proto.go @@ -343,10 +343,11 @@ func Body(payload []byte) []byte { // Path takes payload and retuns request path: Split(firstLine, ' ')[1] func Path(payload []byte) []byte { start := bytes.IndexByte(payload, ' ') + 1 + eol := bytes.IndexByte(payload[start:], '\r') end := bytes.IndexByte(payload[start:], ' ') - if len(payload) < start + end { - return []byte{} + if eol < end { + return payload[start : start + eol] } return payload[start : start+end] diff --git a/proto/proto_test.go b/proto/proto_test.go index 58e6062..4ff2dc5 100644 --- a/proto/proto_test.go +++ b/proto/proto_test.go @@ -65,13 +65,13 @@ func TestHeader(t *testing.T) { } func TestMIMEHeadersEndPos(t *testing.T) { - head := []byte("POST /post HTTP/1.1\r\nContent-Length: 7\r\nHost: www.w3.org") + head := []byte("POST /post HTTP/1.1\r\nContent-Length: 7\r\nHost: www.w3.org\r\n\r\n") payload := []byte("POST /post HTTP/1.1\r\nContent-Length: 7\r\nHost: www.w3.org\r\n\r\na=1&b=2") end := MIMEHeadersEndPos(payload) if !bytes.Equal(payload[:end], head) { - t.Error("Wrong headers end position:", end) + t.Error("Wrong headers end position:", end, head, payload[:end]) } } @@ -80,10 +80,10 @@ func TestMIMEHeadersStartPos(t *testing.T) { payload := []byte("POST /post HTTP/1.1\r\nContent-Length: 7\r\nHost: www.w3.org\r\n\r\na=1&b=2") start := MIMEHeadersStartPos(payload) - end := MIMEHeadersEndPos(payload) + end := MIMEHeadersEndPos(payload) - 4 if !bytes.Equal(payload[start:end], headers) { - t.Error("Wrong headers end position:", start, end) + t.Error("Wrong headers end position:", start, end, payload[start:end]) } } @@ -237,6 +237,12 @@ func TestPath(t *testing.T) { if path = Path(payload); !bytes.Equal(path, []byte("/post")) { t.Error("Should find path", string(path)) } + + payload = []byte("GET /get\r\n\r\nHost: www.w3.org\r\n\r\n") + + if path = Path(payload); !bytes.Equal(path, []byte("/get")) { + t.Error("Should find path", string(path)) + } } func TestSetPath(t *testing.T) { From 21531cea9adf93dce1a75885d883149a9540663a Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Tue, 27 Jun 2017 15:30:34 +0200 Subject: [PATCH 18/20] Add support for rewriting headers --- http_modifier.go | 15 +++++++++++++++ http_modifier_settings.go | 38 ++++++++++++++++++++++++++++++++++++++ http_modifier_test.go | 21 +++++++++++++++++++++ settings.go | 2 ++ 4 files changed, 76 insertions(+) diff --git a/http_modifier.go b/http_modifier.go index 8d000ee..776db6a 100644 --- a/http_modifier.go +++ b/http_modifier.go @@ -16,6 +16,7 @@ func NewHTTPModifier(config *HTTPModifierConfig) *HTTPModifier { if len(config.urlRegexp) == 0 && len(config.urlNegativeRegexp) == 0 && len(config.urlRewrite) == 0 && + len(config.headerRewrite) == 0 && len(config.headerFilters) == 0 && len(config.headerNegativeFilters) == 0 && len(config.headerHashFilters) == 0 && @@ -153,5 +154,19 @@ func (m *HTTPModifier) Rewrite(payload []byte) (response []byte) { } } + if len(m.config.headerRewrite) > 0 { + for _, f := range m.config.headerRewrite { + value := proto.Header(payload, f.header) + if len(value) == 0 { + break + } + + if f.src.Match(value) { + newValue := f.src.ReplaceAll(value, f.target) + payload = proto.SetHeader(payload, f.header, newValue) + } + } + } + return payload } diff --git a/http_modifier_settings.go b/http_modifier_settings.go index 3bea9f9..ba0f0e0 100644 --- a/http_modifier_settings.go +++ b/http_modifier_settings.go @@ -13,6 +13,7 @@ type HTTPModifierConfig struct { urlNegativeRegexp HTTPUrlRegexp urlRegexp HTTPUrlRegexp urlRewrite UrlRewriteMap + headerRewrite HeaderRewriteMap headerFilters HTTPHeaderFilters headerNegativeFilters HTTPHeaderFilters headerHashFilters HTTPHashFilters @@ -196,6 +197,43 @@ func (r *UrlRewriteMap) Set(value string) error { return nil } +// +// Handling of --http-rewrite-header option +// +type headerRewrite struct { + header []byte + src *regexp.Regexp + target []byte +} + +type HeaderRewriteMap []headerRewrite + +func (r *HeaderRewriteMap) String() string { + return fmt.Sprint(*r) +} + +func (r *HeaderRewriteMap) Set(value string) error { + headerArr := strings.SplitN(value, ":", 2) + if len(headerArr) < 2 { + return errors.New("need both header, regexp and rewrite target, colon-delimited (ex. Header: regexp,target)") + } + + header := headerArr[0] + valArr := strings.SplitN(strings.TrimSpace(headerArr[1]), ",", 2) + + if len(valArr) < 2 { + return errors.New("need both header, regexp and rewrite target, colon-delimited (ex. Header: regexp,target)") + } + + regexp, err := regexp.Compile(valArr[0]) + if err != nil { + return err + } + *r = append(*r, headerRewrite{header: []byte(header), src: regexp, target: []byte(valArr[1])}) + return nil +} + + // // Handling of --http-allow-url option // diff --git a/http_modifier_test.go b/http_modifier_test.go index 343be5f..6e4ee48 100644 --- a/http_modifier_test.go +++ b/http_modifier_test.go @@ -107,6 +107,27 @@ func TestHTTPModifierURLRewrite(t *testing.T) { } } +func TestHTTPModifierHeaderRewrite(t *testing.T) { + var header, newHeader []byte + + rewrites := HeaderRewriteMap{} + payload := []byte("GET / HTTP/1.1\r\nContent-Length: 7\r\nHost: www.w3.org\r\n\r\na=1&b=2") + + err := rewrites.Set("Host: (.*).w3.org,$1.beta.w3.org") + if err != nil { + t.Error("Should not error", err) + } + + modifier := NewHTTPModifier(&HTTPModifierConfig{ + headerRewrite: rewrites, + }) + + header = []byte("www.beta.w3.org") + if newHeader = proto.Header(modifier.Rewrite(payload), []byte("Host")); !bytes.Equal(newHeader, header) { + t.Error("Request header should have been rewritten, wasn't", string(newHeader), string(header)) + } +} + func TestHTTPModifierHeaderHashFilters(t *testing.T) { filters := HTTPHashFilters{} filters.Set("Header2:1/2") diff --git a/settings.go b/settings.go index a44aee1..654b1db 100644 --- a/settings.go +++ b/settings.go @@ -148,6 +148,8 @@ func init() { flag.Var(&Settings.modifierConfig.headers, "http-set-header", "Inject additional headers to http reqest:\n\tgor --input-raw :8080 --output-http staging.com --http-set-header 'User-Agent: Gor'") flag.Var(&Settings.modifierConfig.headers, "output-http-header", "WARNING: `--output-http-header` DEPRECATED, use `--http-set-header` instead") + flag.Var(&Settings.modifierConfig.headerRewrite, "http-rewrite-header", "Rewrite the request header based on a mapping:\n\tgor --input-raw :8080 --output-http staging.com --http-rewrite-header Host: (.*).example.com,$1.beta.example.com") + flag.Var(&Settings.modifierConfig.params, "http-set-param", "Set request url param, if param already exists it will be overwritten:\n\tgor --input-raw :8080 --output-http staging.com --http-set-param api_key=1") flag.Var(&Settings.modifierConfig.methods, "http-allow-method", "Whitelist of HTTP methods to replay. Anything else will be dropped:\n\tgor --input-raw :8080 --output-http staging.com --http-allow-method GET --http-allow-method OPTIONS") From 5aa1696680b6ed8fe4f7bd1a7e9682ec321b1d60 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Tue, 27 Jun 2017 17:11:34 +0200 Subject: [PATCH 19/20] Add TLS security support between --input-tcp and --output-tcp --- input_tcp.go | 37 +++++++++++++++---- input_tcp_test.go | 90 +++++++++++++++++++++++++++++++++++++++++++++- output_tcp.go | 15 ++++++-- output_tcp_test.go | 4 +-- plugins.go | 4 +-- settings.go | 14 ++++++-- 6 files changed, 147 insertions(+), 17 deletions(-) diff --git a/input_tcp.go b/input_tcp.go index f3c9553..025312a 100644 --- a/input_tcp.go +++ b/input_tcp.go @@ -4,6 +4,7 @@ import ( "bufio" "bytes" "fmt" + "crypto/tls" "io" "log" "net" @@ -13,15 +14,23 @@ import ( // TCPInput used for internal communication type TCPInput struct { data chan []byte - address string listener net.Listener + address string + config *TCPInputConfig +} + +type TCPInputConfig struct { + secure bool + certificatePath string + keyPath string } // NewTCPInput constructor for TCPInput, accepts address with port -func NewTCPInput(address string) (i *TCPInput) { +func NewTCPInput(address string, config *TCPInputConfig) (i *TCPInput) { i = new(TCPInput) i.data = make(chan []byte, 1000) i.address = address + i.config = config i.listen(address) @@ -36,16 +45,30 @@ func (i *TCPInput) Read(data []byte) (int, error) { } func (i *TCPInput) listen(address string) { - listener, err := net.Listen("tcp", address) - i.listener = listener + if i.config.secure { + cer, err := tls.LoadX509KeyPair(i.config.certificatePath, i.config.keyPath) + if err != nil { + log.Fatal("Error while loading --input-file certificate:", err) + } - if err != nil { - log.Fatal("Can't start:", err) + config := &tls.Config{Certificates: []tls.Certificate{cer}} + listener, err := tls.Listen("tcp", address, config) + if err != nil { + log.Fatal("Can't start --input-tcp with secure connection:", err) + } + i.listener = listener + } else { + listener, err := net.Listen("tcp", address) + if err != nil { + log.Fatal("Can't start:", err) + } + + i.listener = listener } go func() { for { - conn, err := listener.Accept() + conn, err := i.listener.Accept() if err != nil { log.Println("Error while Accept()", err) diff --git a/input_tcp_test.go b/input_tcp_test.go index 2dcd6c5..ef62b6b 100644 --- a/input_tcp_test.go +++ b/input_tcp_test.go @@ -2,8 +2,18 @@ package main import ( "io" + "os" "log" "net" + "io/ioutil" + "crypto/x509" + "crypto/rsa" + "crypto/rand" + "crypto/tls" + "encoding/pem" + "math/big" + "time" + "bytes" "sync" "testing" ) @@ -12,7 +22,7 @@ func TestTCPInput(t *testing.T) { wg := new(sync.WaitGroup) quit := make(chan int) - input := NewTCPInput("127.0.0.1:0") + input := NewTCPInput("127.0.0.1:0", &TCPInputConfig{}) output := NewTestOutput(func(data []byte) { wg.Done() }) @@ -46,3 +56,81 @@ func TestTCPInput(t *testing.T) { close(quit) } + +func genCertificate(template *x509.Certificate) ([]byte, []byte) { + priv, _ := rsa.GenerateKey(rand.Reader, 2048) + + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, _ := rand.Int(rand.Reader, serialNumberLimit) + template.SerialNumber = serialNumber + template.BasicConstraintsValid = true + template.NotBefore = time.Now() + template.NotAfter = time.Now().Add(time.Hour) + + derBytes, _ := x509.CreateCertificate(rand.Reader, template, template, &priv.PublicKey, priv) + + var certPem, keyPem bytes.Buffer + pem.Encode(&certPem, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) + pem.Encode(&keyPem, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) + + return certPem.Bytes(), keyPem.Bytes() +} + +func TestTCPInputSecure(t *testing.T) { + serverCertPem, serverPrivPem := genCertificate(&x509.Certificate{ + DNSNames: []string{"localhost"}, + IPAddresses: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::")}, + }) + + serverCertPemFile, _ := ioutil.TempFile("", "server.crt") + serverCertPemFile.Write(serverCertPem) + serverCertPemFile.Close() + + serverPrivPemFile, _ := ioutil.TempFile("", "server.key") + serverPrivPemFile.Write(serverPrivPem) + serverPrivPemFile.Close() + + defer func(){ + os.Remove(serverPrivPemFile.Name()) + os.Remove(serverCertPemFile.Name()) + }() + + wg := new(sync.WaitGroup) + quit := make(chan int) + + input := NewTCPInput("127.0.0.1:0", &TCPInputConfig{ + secure: true, + certificatePath: serverCertPemFile.Name(), + keyPath: serverPrivPemFile.Name(), + }) + output := NewTestOutput(func(data []byte) { + wg.Done() + }) + + Plugins.Inputs = []io.Reader{input} + Plugins.Outputs = []io.Writer{output} + + go Start(quit) + + conf := &tls.Config{ + InsecureSkipVerify: true, + } + + conn, err := tls.Dial("tcp", input.listener.Addr().String(), conf) + if err != nil { + t.Fatal(err) + } + defer conn.Close() + + msg := []byte("1 1 1\nGET / HTTP/1.1\r\n\r\n") + + for i := 0; i < 100; i++ { + wg.Add(1) + conn.Write(msg) + conn.Write([]byte(payloadSeparator)) + } + + wg.Wait() + + close(quit) +} \ No newline at end of file diff --git a/output_tcp.go b/output_tcp.go index 933dcb8..69ba05e 100644 --- a/output_tcp.go +++ b/output_tcp.go @@ -1,6 +1,7 @@ package main import ( + "crypto/tls" "fmt" "io" "log" @@ -16,14 +17,20 @@ type TCPOutput struct { limit int buf chan []byte bufStats *GorStat + config *TCPOutputConfig +} + +type TCPOutputConfig struct { + secure bool } // NewTCPOutput constructor for TCPOutput // Initialize 10 workers which hold keep-alive connection -func NewTCPOutput(address string) io.Writer { +func NewTCPOutput(address string, config *TCPOutputConfig) io.Writer { o := new(TCPOutput) o.address = address + o.config = config o.buf = make(chan []byte, 100) if Settings.outputTCPStats { @@ -89,7 +96,11 @@ func (o *TCPOutput) Write(data []byte) (n int, err error) { } func (o *TCPOutput) connect(address string) (conn net.Conn, err error) { - conn, err = net.Dial("tcp", address) + if o.config.secure { + conn, err = tls.Dial("tcp", address, &tls.Config{}) + } else { + conn, err = net.Dial("tcp", address) + } return } diff --git a/output_tcp_test.go b/output_tcp_test.go index a7efd38..64ef8ca 100644 --- a/output_tcp_test.go +++ b/output_tcp_test.go @@ -17,7 +17,7 @@ func TestTCPOutput(t *testing.T) { wg.Done() }) input := NewTestInput() - output := NewTCPOutput(listener.Addr().String()) + output := NewTCPOutput(listener.Addr().String(), &TCPOutputConfig{}) Plugins.Inputs = []io.Reader{input} Plugins.Outputs = []io.Writer{output} @@ -69,7 +69,7 @@ func BenchmarkTCPOutput(b *testing.B) { wg.Done() }) input := NewTestInput() - output := NewTCPOutput(listener.Addr().String()) + output := NewTCPOutput(listener.Addr().String(), &TCPOutputConfig{}) Plugins.Inputs = []io.Reader{input} Plugins.Outputs = []io.Writer{output} diff --git a/plugins.go b/plugins.go index 9cd1136..3685313 100644 --- a/plugins.go +++ b/plugins.go @@ -110,11 +110,11 @@ func InitPlugins() { } for _, options := range Settings.inputTCP { - registerPlugin(NewTCPInput, options) + registerPlugin(NewTCPInput, options, &Settings.inputTCPConfig) } for _, options := range Settings.outputTCP { - registerPlugin(NewTCPOutput, options) + registerPlugin(NewTCPOutput, options, &Settings.outputTCPConfig) } for _, options := range Settings.inputFile { diff --git a/settings.go b/settings.go index 654b1db..a55ca42 100644 --- a/settings.go +++ b/settings.go @@ -37,9 +37,11 @@ type AppSettings struct { outputStdout bool outputNull bool - inputTCP MultiOption - outputTCP MultiOption - outputTCPStats bool + inputTCP MultiOption + inputTCPConfig TCPInputConfig + outputTCP MultiOption + outputTCPConfig TCPOutputConfig + outputTCPStats bool inputFile MultiOption inputFileLoop bool @@ -93,7 +95,13 @@ func init() { flag.BoolVar(&Settings.outputNull, "output-null", false, "Used for testing inputs. Drops all requests.") flag.Var(&Settings.inputTCP, "input-tcp", "Used for internal communication between Gor instances. Example: \n\t# Receive requests from other Gor instances on 28020 port, and redirect output to staging\n\tgor --input-tcp :28020 --output-http staging.com") + flag.BoolVar(&Settings.inputTCPConfig.secure, "input-tcp-secure", false, "Turn on TLS security. Do not forget to specify certificate and key files.") + flag.StringVar(&Settings.inputTCPConfig.certificatePath, "input-tcp-certificate", "", "Path to PEM encoded certificate file. Used when TLS turned on.") + flag.StringVar(&Settings.inputTCPConfig.keyPath, "input-tcp-certificate-key", "", "Path to PEM encoded certificate key file. Used when TLS turned on.") + + flag.Var(&Settings.outputTCP, "output-tcp", "Used for internal communication between Gor instances. Example: \n\t# Listen for requests on 80 port and forward them to other Gor instance on 28020 port\n\tgor --input-raw :80 --output-tcp replay.local:28020") + flag.BoolVar(&Settings.outputTCPConfig.secure, "output-tcp-secure", false, "Use TLS secure connection. --input-file on another end should have TLS turned on as well.") flag.BoolVar(&Settings.outputTCPStats, "output-tcp-stats", false, "Report TCP output queue stats to console every 5 seconds.") flag.Var(&Settings.inputFile, "input-file", "Read requests from file: \n\tgor --input-file ./requests.gor --output-http staging.com") From 652e589e2b71d5dfa4d2a70431d21b108a5e471e Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Fri, 30 Jun 2017 15:58:45 +0200 Subject: [PATCH 20/20] fix proto.Path --- proto/proto.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto/proto.go b/proto/proto.go index 1ef2449..0bd83dc 100644 --- a/proto/proto.go +++ b/proto/proto.go @@ -346,7 +346,7 @@ func Path(payload []byte) []byte { eol := bytes.IndexByte(payload[start:], '\r') end := bytes.IndexByte(payload[start:], ' ') - if eol < end { + if eol > 0 && eol < end { return payload[start : start + eol] }