Skip to content

Commit

Permalink
Merge pull request #53 from SpectoLabs/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
Karolis Rusenas committed Jan 7, 2016
2 parents 2ea4306 + 5460a5e commit feb7bd2
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 63 deletions.
30 changes: 23 additions & 7 deletions admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ func (d *DBClient) startAdminInterface() {

// admin interface starting message
log.WithFields(log.Fields{
"AdminPort": AppConfig.adminInterface,
"AdminPort": d.cfg.adminInterface,
}).Info("Admin interface is starting...")

n.Run(AppConfig.adminInterface)
n.Run(d.cfg.adminInterface)
}

// getBoneRouter returns mux for admin interface
Expand Down Expand Up @@ -197,8 +197,8 @@ func (d *DBClient) DeleteAllRecordsHandler(w http.ResponseWriter, req *http.Requ
// CurrentStateHandler returns current state
func (d *DBClient) CurrentStateHandler(w http.ResponseWriter, req *http.Request) {
var resp StateRequest
resp.Mode = AppConfig.mode
resp.Destination = AppConfig.destination
resp.Mode = d.cfg.GetMode()
resp.Destination = d.cfg.destination

b, _ := json.Marshal(resp)
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
Expand Down Expand Up @@ -228,17 +228,33 @@ func (d *DBClient) stateHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(422) // can't process this entity
return
}

availableModes := map[string]bool{
"virtualize": true,
"capture": true,
"modify": true,
"synthesize": true,
}

if !availableModes[stateRequest.Mode] {
log.WithFields(log.Fields{
"suppliedMode": stateRequest.Mode,
}).Error("Wrong mode found, can't change state")
http.Error(w, "Bad mode supplied, available modes: virtualize, capture, modify, synthesize.", 400)
return
}

log.WithFields(log.Fields{
"newState": stateRequest.Mode,
"body": string(body),
}).Info("Handling state change request!")

// setting new state
AppConfig.mode = stateRequest.Mode
d.cfg.SetMode(stateRequest.Mode)

var resp StateRequest
resp.Mode = stateRequest.Mode
resp.Destination = AppConfig.destination
resp.Mode = d.cfg.GetMode()
resp.Destination = d.cfg.destination
b, _ := json.Marshal(resp)
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.Write(b)
Expand Down
3 changes: 0 additions & 3 deletions cache.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// redis cache backend implementation for persistent storage

package main

import (
Expand All @@ -20,7 +18,6 @@ type Cache struct {
func getDB(name string) *bolt.DB {
log.WithFields(log.Fields{
"databaseName": name,
"Mode": AppConfig.mode,
}).Info("Initiating database")
db, err := bolt.Open(name, 0600, nil)
if err != nil {
Expand Down
70 changes: 35 additions & 35 deletions hoverfly.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,12 @@ import (

"bufio"
"flag"
"fmt"
"net"
"net/http"
"os"
"regexp"
)

const DefaultPort = ":8500"

// modes
const VirtualizeMode = "virtualize"
const SynthesizeMode = "synthesize"
Expand Down Expand Up @@ -46,16 +43,17 @@ func main() {
middleware := flag.String("middleware", "", "should proxy use middleware")
flag.Parse()

// getting settings
cfg := InitSettings()

if *verbose {
// Only log the warning severity or above.
log.SetLevel(log.DebugLevel)
}

// getting settings
initSettings()
cfg.verbose = *verbose

// overriding default middleware setting
AppConfig.middleware = *middleware
cfg.middleware = *middleware

// setting default mode
mode := VirtualizeMode
Expand All @@ -69,7 +67,7 @@ func main() {
} else if *synthesize {
mode = SynthesizeMode

if AppConfig.middleware == "" {
if cfg.middleware == "" {
log.Fatal("Synthesize mode chosen although middleware not supplied")
}

Expand All @@ -79,7 +77,7 @@ func main() {
} else if *modify {
mode = ModifyMode

if AppConfig.middleware == "" {
if cfg.middleware == "" {
log.Fatal("Modify mode chosen although middleware not supplied")
}

Expand All @@ -89,22 +87,22 @@ func main() {
}

// overriding default settings
AppConfig.mode = mode
cfg.mode = mode

// overriding destination
AppConfig.destination = *destination
cfg.destination = *destination

// getting default database
port := os.Getenv("ProxyPort")
if port == "" {
port = DefaultPort
} else {
port = fmt.Sprintf(":%s", port)
}
proxy, dbClient := getNewHoverfly(cfg)
defer dbClient.cache.db.Close()

log.Warn(http.ListenAndServe(cfg.proxyPort, proxy))
}

// getNewHoverfly returns a configured ProxyHttpServer and DBClient, also starts admin interface on configured port
func getNewHoverfly(cfg *Configuration) (*goproxy.ProxyHttpServer, DBClient) {

// getting boltDB
db := getDB(AppConfig.databaseName)
defer db.Close()
db := getDB(cfg.databaseName)

cache := Cache{
db: db,
Expand All @@ -115,16 +113,17 @@ func main() {
d := DBClient{
cache: cache,
http: &http.Client{},
cfg: cfg,
}

// creating proxy
proxy := goproxy.NewProxyHttpServer()

proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile("^.*$"))).
proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile(d.cfg.destination))).
HandleConnect(goproxy.AlwaysMitm)

// enable curl -p for all hosts on port 80
proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile(*destination))).
proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile(d.cfg.destination))).
HijackConnect(func(req *http.Request, client net.Conn, ctx *goproxy.ProxyCtx) {
defer func() {
if e := recover(); e != nil {
Expand All @@ -151,29 +150,30 @@ func main() {
})

// processing connections
proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile(*destination))).DoFunc(
proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile(cfg.destination))).DoFunc(
func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
return d.processRequest(r)
})

go d.startAdminInterface()

proxy.Verbose = *verbose
proxy.Verbose = d.cfg.verbose
// proxy starting message
log.WithFields(log.Fields{
"Destination": *destination,
"ProxyPort": port,
"Mode": AppConfig.mode,
}).Info("Proxy is starting...")
"Destination": d.cfg.destination,
"ProxyPort": d.cfg.proxyPort,
"Mode": d.cfg.GetMode(),
}).Info("Proxy prepared...")

log.Warn(http.ListenAndServe(port, proxy))
return proxy, d
}

// processRequest - processes incoming requests and based on proxy state (record/playback)
// returns HTTP response.
func (d *DBClient) processRequest(req *http.Request) (*http.Request, *http.Response) {

if AppConfig.mode == CaptureMode {
mode := d.cfg.GetMode()
if mode == CaptureMode {
log.Info("*** Capture ***")
newResponse, err := d.captureRequest(req)
if err != nil {
Expand All @@ -184,19 +184,19 @@ func (d *DBClient) processRequest(req *http.Request) (*http.Request, *http.Respo
return req, newResponse
}

} else if AppConfig.mode == SynthesizeMode {
} else if mode == SynthesizeMode {
log.Info("*** Sinthesize ***")
response := synthesizeResponse(req, AppConfig.middleware)
response := synthesizeResponse(req, d.cfg.middleware)
return req, response

} else if AppConfig.mode == ModifyMode {
} else if mode == ModifyMode {
log.Info("*** Modify ***")
response, err := d.modifyRequestResponse(req, AppConfig.middleware)
response, err := d.modifyRequestResponse(req, d.cfg.middleware)

if err != nil {
log.WithFields(log.Fields{
"error": err.Error(),
"middleware": AppConfig.middleware,
"middleware": d.cfg.middleware,
}).Error("Got error when performing request modification")
return req, nil
}
Expand Down
4 changes: 2 additions & 2 deletions manipulation.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ func (c *Constructor) ApplyMiddleware(middleware string) error {
if err != nil {
log.WithFields(log.Fields{
"error": err.Error(),
"middleware": AppConfig.middleware,
"middleware": middleware,
}).Error("Error during middleware transformation, not modifying payload!")

return err
} else {

log.WithFields(log.Fields{
"middleware": AppConfig.middleware,
"middleware": middleware,
}).Info("Middleware transformation complete!")
// override payload with transformed new payload
c.payload = newPayload
Expand Down
14 changes: 6 additions & 8 deletions models.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ import (
"io/ioutil"
)

// DBClient provides access to cache, http client and configuration
type DBClient struct {
cache Cache
http *http.Client
cfg *Configuration
}

// request holds structure for request
Expand Down Expand Up @@ -73,7 +75,6 @@ func (d *DBClient) captureRequest(req *http.Request) (*http.Response, error) {
if err != nil {
log.WithFields(log.Fields{
"error": err.Error(),
"mode": AppConfig.mode,
}).Error("Got error when reading request body")
}
log.WithFields(log.Fields{
Expand Down Expand Up @@ -139,11 +140,11 @@ func (d *DBClient) doRequest(request *http.Request) (*http.Response, error) {
// We can't have this set. And it only contains "/pkg/net/http/" anyway
request.RequestURI = ""

if AppConfig.middleware != "" {
if d.cfg.middleware != "" {
var payload Payload

c := NewConstructor(request, payload)
c.ApplyMiddleware(AppConfig.middleware)
c.ApplyMiddleware(d.cfg.middleware)

request = c.reconstructRequest()

Expand Down Expand Up @@ -250,8 +251,8 @@ func (d *DBClient) getResponse(req *http.Request) *http.Response {

c := NewConstructor(req, payload)

if AppConfig.middleware != "" {
_ = c.ApplyMiddleware(AppConfig.middleware)
if d.cfg.middleware != "" {
_ = c.ApplyMiddleware(d.cfg.middleware)
}

response := c.reconstructResponse()
Expand All @@ -260,15 +261,13 @@ func (d *DBClient) getResponse(req *http.Request) *http.Response {
"key": key,
"status": payload.Response.Status,
"bodyLength": response.ContentLength,
"mode": AppConfig.mode,
}).Info("Response found, returning")

return response

} else {
log.WithFields(log.Fields{
"error": err.Error(),
"mode": AppConfig.mode,
"query": req.URL.RawQuery,
"path": req.URL.RawPath,
"destination": req.Host,
Expand Down Expand Up @@ -324,7 +323,6 @@ func (d *DBClient) modifyRequestResponse(req *http.Request, middleware string) (
log.WithFields(log.Fields{
"status": newResponse.StatusCode,
"middleware": middleware,
"mode": AppConfig.mode,
}).Info("Response modified, returning")

return newResponse, nil
Expand Down
Loading

0 comments on commit feb7bd2

Please sign in to comment.