Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding a new config to dump the incoming requests #101

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions cmd/killgrave/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,16 @@ const (

func main() {
var (
host = flag.String("host", _defaultHost, "if you run your server on a different host")
port = flag.Int("port", _defaultPort, "port to run the server")
secure = flag.Bool("secure", _defaultSecure, "if you run your server using TLS (https)")
imposters = flag.String("imposters", _defaultImpostersPath, "directory where your imposters are saved")
showVersion = flag.Bool("version", false, "show the _version of the application")
configFilePath = flag.String("config", _defaultConfigFile, "path with configuration file")
watcherFlag = flag.Bool("watcher", false, "file watcher, reload the server with each file change")
proxyModeFlag = flag.String("proxy-mode", _defaultProxyMode.String(), "proxy mode you can choose between (all, missing or none)")
proxyURLFlag = flag.String("proxy-url", "", "proxy url, you need to choose a proxy-mode")
host = flag.String("host", _defaultHost, "if you run your server on a different host")
port = flag.Int("port", _defaultPort, "port to run the server")
secure = flag.Bool("secure", _defaultSecure, "if you run your server using TLS (https)")
imposters = flag.String("imposters", _defaultImpostersPath, "directory where your imposters are saved")
showVersion = flag.Bool("version", false, "show the _version of the application")
configFilePath = flag.String("config", _defaultConfigFile, "path with configuration file")
watcherFlag = flag.Bool("watcher", false, "file watcher, reload the server with each file change")
proxyModeFlag = flag.String("proxy-mode", _defaultProxyMode.String(), "proxy mode you can choose between (all, missing or none)")
proxyURLFlag = flag.String("proxy-url", "", "proxy url, you need to choose a proxy-mode")
dumpRequestsFlag = flag.Bool("dump-requests", false, "dumps the request performed against the the server")
)

flag.Parse()
Expand All @@ -60,6 +61,7 @@ func main() {
killgrave.WithProxyConfiguration(*proxyModeFlag, *proxyURLFlag),
killgrave.WithWatcherConfiguration(*watcherFlag),
killgrave.WithConfigFile(*configFilePath),
killgrave.WithDumpRequestsConfiguration(*dumpRequestsFlag),
)
if err != nil {
log.Println(err)
Expand All @@ -69,8 +71,7 @@ func main() {

signal.Notify(done, syscall.SIGINT, syscall.SIGTERM)

var srv server.Server
srv = runServer(cfg.Host, cfg.Port, cfg)
srv := runServer(cfg.Host, cfg.Port, cfg)
srv.Run()

// Initialize and start the file watcher if the watcher option is true
Expand Down Expand Up @@ -125,6 +126,7 @@ func runServer(host string, port int, cfg killgrave.Config) server.Server {
httpServer,
proxyServer,
cfg.Secure,
cfg.DumpRequests,
)
if err := s.Build(); err != nil {
log.Fatal(err)
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
Expand All @@ -34,4 +35,5 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
10 changes: 10 additions & 0 deletions internal/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type Config struct {
Proxy ConfigProxy `yaml:"proxy"`
Secure bool `yaml:"secure"`
Watcher bool `yaml:"watcher"`
DumpRequests bool `yaml:"dump_requests"`
}

// ConfigCORS representation of section CORS of the yaml
Expand Down Expand Up @@ -157,3 +158,12 @@ func WithWatcherConfiguration(watcher bool) ConfigOpt {
return nil
}
}

// WithDumpRequestConfiguration preparing server to dump the received requests
func WithDumpRequestsConfiguration(dumpRequests bool) ConfigOpt {
return func(cfg *Config) error {

cfg.DumpRequests = dumpRequests
return nil
}
}
6 changes: 4 additions & 2 deletions internal/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ func TestNewConfig(t *testing.T) {
false,
WithProxyConfiguration(ProxyNone.String(), ""),
WithConfigFile(tc.input),
WithWatcherConfiguration(tc.expected.Watcher))
WithWatcherConfiguration(tc.expected.Watcher),
WithDumpRequestsConfiguration(tc.expected.DumpRequests))

if err != nil && tc.err == nil {
t.Fatalf("not expected any erros and got %v", err)
Expand Down Expand Up @@ -121,7 +122,8 @@ func validConfig() Config {
ExposedHeaders: []string{"Cache-Control"},
AllowCredentials: true,
},
Watcher: true,
Watcher: true,
DumpRequests: true,
}
}

Expand Down
7 changes: 7 additions & 0 deletions internal/server/http/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,20 @@ import (
"io/ioutil"
"log"
"net/http"
"net/http/httputil"
"os"
"time"
)

// ImposterHandler create specific handler for the received imposter
func ImposterHandler(imposter Imposter) http.HandlerFunc {
shouldDumpRequest := imposter.Request.Dump
return func(w http.ResponseWriter, r *http.Request) {
if shouldDumpRequest {
if dumped, err := httputil.DumpRequest(r, true); err == nil {
log.Print(string(dumped))
}
}
if imposter.Delay() > 0 {
time.Sleep(imposter.Delay())
}
Expand Down
1 change: 1 addition & 0 deletions internal/server/http/imposter.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ type Request struct {
SchemaFile *string `json:"schemaFile"`
Params *map[string]string `json:"params"`
Headers *map[string]string `json:"headers"`
Dump bool `json:"dump"`
}

// Response represent the structure of real response
Expand Down
7 changes: 6 additions & 1 deletion internal/server/http/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,18 @@ type Server struct {
httpServer *http.Server
proxy *Proxy
secure bool
dumpRequests bool
}

// NewServer initialize the mock server
func NewServer(p string, r *mux.Router, httpServer *http.Server, proxyServer *Proxy, secure bool) Server {
func NewServer(p string, r *mux.Router, httpServer *http.Server, proxyServer *Proxy, secure bool, dumpRequests bool) Server {
return Server{
impostersPath: p,
router: r,
httpServer: httpServer,
proxy: proxyServer,
secure: secure,
dumpRequests: dumpRequests,
}
}

Expand Down Expand Up @@ -165,6 +167,9 @@ func (s *Server) Shutdown() error {
func (s *Server) addImposterHandler(imposters []Imposter, imposterConfig ImposterConfig) {
for _, imposter := range imposters {
imposter.BasePath = filepath.Dir(imposterConfig.FilePath)
if s.dumpRequests {
imposter.Request.Dump = true // Override imposter configuration
}
r := s.router.HandleFunc(imposter.Request.Endpoint, ImposterHandler(imposter)).
Methods(imposter.Request.Method).
MatcherFunc(MatcherBySchema(imposter))
Expand Down
66 changes: 61 additions & 5 deletions internal/server/http/server_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package http

import (
"bytes"
"crypto/tls"
"errors"
"io"
Expand All @@ -9,6 +10,7 @@ import (
"net/http"
"net/http/httptest"
"os"
"strings"
"testing"
"time"

Expand All @@ -28,9 +30,9 @@ func TestServer_Build(t *testing.T) {
server Server
err error
}{
{"imposter directory not found", NewServer("failImposterPath", nil, &http.Server{}, &Proxy{}, false), errors.New("hello")},
{"malformatted json", NewServer("test/testdata/malformatted_imposters", nil, &http.Server{}, &Proxy{}, false), nil},
{"valid imposter", NewServer("test/testdata/imposters", mux.NewRouter(), &http.Server{}, &Proxy{}, false), nil},
{"imposter directory not found", NewServer("failImposterPath", nil, &http.Server{}, &Proxy{}, false, false), errors.New("hello")},
{"malformatted json", NewServer("test/testdata/malformatted_imposters", nil, &http.Server{}, &Proxy{}, false, false), nil},
{"valid imposter", NewServer("test/testdata/imposters", mux.NewRouter(), &http.Server{}, &Proxy{}, false, false), nil},
}

for _, tt := range serverData {
Expand Down Expand Up @@ -64,7 +66,7 @@ func TestBuildProxyMode(t *testing.T) {
if err != nil {
t.Fatal("NewProxy failed: ", err)
}
server := NewServer("test/testdata/imposters", router, httpServer, proxyServer, false)
server := NewServer("test/testdata/imposters", router, httpServer, proxyServer, false, false)
return &server, func() {
httpServer.Close()
}
Expand Down Expand Up @@ -145,7 +147,7 @@ func TestBuildSecureMode(t *testing.T) {
if err != nil {
t.Fatal("NewProxy failed: ", err)
}
server := NewServer("test/testdata/imposters_secure", router, httpServer, proxyServer, true)
server := NewServer("test/testdata/imposters_secure", router, httpServer, proxyServer, true, false)
return &server, func() {
httpServer.Close()
}
Expand Down Expand Up @@ -208,3 +210,57 @@ func TestBuildSecureMode(t *testing.T) {
})
}
}

func TestBuildDumpRequests(t *testing.T) {
var buf bytes.Buffer
log.SetOutput(&buf)
defer func() {
log.SetOutput(os.Stderr)
}()

server := NewServer("test/testdata/imposters", mux.NewRouter(), &http.Server{}, &Proxy{}, false, false)
if err := server.Build(); err != nil {
t.Fatalf("not expected any erros and got %+v", err)
}

expectedBody := "Dumped"
req := httptest.NewRequest("GET", "/yamlTestDumpRequest", strings.NewReader(expectedBody))
w := httptest.NewRecorder()

server.router.ServeHTTP(w, req)
response := w.Result()
if response.StatusCode != http.StatusOK {
t.Errorf("Expected status code: %v, got: %v", http.StatusOK, response.StatusCode)
}

if !strings.Contains(buf.String(), expectedBody) {
t.Errorf("Expect request dumped on logs failed")
}
}

func TestBuildDumpRequestsOverride(t *testing.T) {
var buf bytes.Buffer
log.SetOutput(&buf)
defer func() {
log.SetOutput(os.Stderr)
}()

server := NewServer("test/testdata/imposters", mux.NewRouter(), &http.Server{}, &Proxy{}, false, true)
if err := server.Build(); err != nil {
t.Fatalf("not expected any erros and got %+v", err)
}

expectedBody := "Dumped"
req := httptest.NewRequest("GET", "/yamlTestRequest", strings.NewReader(expectedBody))
w := httptest.NewRecorder()

server.router.ServeHTTP(w, req)
response := w.Result()
if response.StatusCode != http.StatusOK {
t.Errorf("Expected status code: %v, got: %v", http.StatusOK, response.StatusCode)
}

if !strings.Contains(buf.String(), expectedBody) {
t.Errorf("Expect request dumped on logs failed")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,11 @@
endpoint: /yamlTestRequest
response:
status: 200
body: "Yaml Handled"
body: "Yaml Handled"
- request:
method: GET
endpoint: /yamlTestDumpRequest
dump: true
response:
status: 200
body: "Yaml Dump Handled"
1 change: 1 addition & 0 deletions internal/test/testdata/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ cors:
origins: ["*"]
allow_credentials: true
watcher: true
dump_requests: true