Skip to content

Commit ef92f86

Browse files
author
Karolis Rusenas
committed
Merge pull request #46 from SpectoLabs/develop
Develop
2 parents e16e355 + 44db997 commit ef92f86

File tree

10 files changed

+84
-44
lines changed

10 files changed

+84
-44
lines changed

.gitmodules

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
[submodule "redigo"]
2-
path = vendor/github.com/garyburd/redigo
3-
url = https://github.com/garyburd/redigo
1+
[submodule "boltdb"]
2+
path = vendor/github.com/boltdb/bolt
3+
url = https://github.com/boltdb/bolt
44
[submodule "logrus"]
55
path = vendor/github.com/Sirupsen/logrus
66
url = https://github.com/Sirupsen/logrus

admin.go

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,15 @@ import (
1212
"github.com/meatballhat/negroni-logrus"
1313
)
1414

15-
// jsonResponse struct encapsulates payload data
15+
// recordedRequests struct encapsulates payload data
1616
type recordedRequests struct {
1717
Data []Payload `json:"data"`
1818
}
1919

20+
type recordsCount struct {
21+
Count int `json:"count"`
22+
}
23+
2024
type StateRequest struct {
2125
Mode string `json:"mode"`
2226
Destination string `json:"destination"`
@@ -49,6 +53,8 @@ func getBoneRouter(d DBClient) *bone.Mux {
4953
mux.Delete("/records", http.HandlerFunc(d.DeleteAllRecordsHandler))
5054
mux.Post("/records", http.HandlerFunc(d.ImportRecordsHandler))
5155

56+
mux.Get("/count", http.HandlerFunc(d.RecordsCount))
57+
5258
mux.Get("/state", http.HandlerFunc(d.CurrentStateHandler))
5359
mux.Post("/state", http.HandlerFunc(d.stateHandler))
5460

@@ -87,6 +93,35 @@ func (d *DBClient) AllRecordsHandler(w http.ResponseWriter, req *http.Request) {
8793
}
8894
}
8995

96+
func (d *DBClient) RecordsCount(w http.ResponseWriter, req *http.Request) {
97+
records, err := d.cache.GetAllRequests()
98+
99+
if err == nil {
100+
101+
w.Header().Set("Content-Type", "application/json")
102+
103+
var response recordsCount
104+
response.Count = len(records)
105+
b, err := json.Marshal(response)
106+
107+
if err != nil {
108+
log.Error(err)
109+
http.Error(w, err.Error(), http.StatusInternalServerError)
110+
} else {
111+
w.Write(b)
112+
return
113+
}
114+
} else {
115+
log.WithFields(log.Fields{
116+
"Error": err.Error(),
117+
}).Error("Failed to get data from cache!")
118+
119+
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
120+
w.WriteHeader(500) // can't process this entity
121+
return
122+
}
123+
}
124+
90125
func (d *DBClient) ImportRecordsHandler(w http.ResponseWriter, req *http.Request) {
91126

92127
var requests recordedRequests

cache.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ type Cache struct {
1818
}
1919

2020
func getDB(name string) *bolt.DB {
21+
log.WithFields(log.Fields{
22+
"databaseName": name,
23+
"Mode": AppConfig.mode,
24+
}).Info("Initiating database")
2125
db, err := bolt.Open(name, 0600, nil)
2226
if err != nil {
2327
log.Fatal(err)

cache_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ func TestSetKey(t *testing.T) {
1111
server, dbClient := testTools(201, `{'message': 'here'}`)
1212
defer server.Close()
1313

14-
k := []byte("randomKey_here")
14+
k := []byte("randomkeyhere")
1515
v := []byte("value")
1616

1717
err := dbClient.cache.Set(k, v)
@@ -20,7 +20,6 @@ func TestSetKey(t *testing.T) {
2020
value, err := dbClient.cache.Get(k)
2121
expect(t, err, nil)
2222
refute(t, value, nil)
23-
// expect(t, value, v)
2423
dbClient.cache.DeleteBucket(dbClient.cache.requestsBucket)
2524
}
2625

readme.md

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
![Hoverfly](static/images/hf-logo-std-r-transparent-medium.png)
22
## Dependencies without the sting
33

4-
[Hoverfly](http://hoverfly.io) is a lightweight, open source [service virtualization](https://en.wikipedia.org/wiki/Service_virtualization) tool. Using Hoverfly, you can virtualize your application dependencies to create a self-contained development or test environment.
4+
[Hoverfly](http://hoverfly.io) is a lightweight, open source [service virtualization](https://en.wikipedia.org/wiki/Service_virtualization) tool.
5+
Using Hoverfly, you can virtualize your application dependencies to create a self-contained development or test environment.
56

6-
Hoverfly is a proxy written in [Go](https://github.com/golang/go). It can capture HTTP(s) traffic between an application under test and external services, and then replace the external services. Another powerful feature: middleware modules, where users can introduce their own custom logic. **Middleware modules can be written in any language**. Hoverfly uses [Redis](http://redis.io/) for persistence.
7+
Hoverfly is a proxy written in [Go](https://github.com/golang/go). It can capture HTTP(s) traffic between an application under test
8+
and external services, and then replace the external services. Another powerful feature: middleware modules, where users
9+
can introduce their own custom logic. **Middleware modules can be written in any language**.
710

811
More information about Hoverfly and how to use it:
912
* https://www.specto.io/speeding-up-your-slow-dependencies/
@@ -23,7 +26,7 @@ The Vagrant provisioning script will start hoverfly in the background in ["virtu
2326

2427
### Build it yourself
2528

26-
Ensure you have [Redis](http://redis.io), then use [Glide](https://github.com/Masterminds/glide) to fetch the dependencies with:
29+
Use [Glide](https://github.com/Masterminds/glide) to fetch the dependencies (or you can also use _git submodule init_) with:
2730

2831
glide up
2932

@@ -37,11 +40,15 @@ And run it:
3740

3841
### Pre-built binary
3942

40-
Pre-built Hoverfly binaries are available [here](https://github.com/SpectoLabs/hoverfly/releases/). You may find it easier to download a binary - however since the Hoverfly admin UI requires static files you will need to clone the Hoverfly repo first, and then copy the binary to the Hoverfly directory before executing it. You will also need [Redis](http://redis.io/).
43+
Pre-built Hoverfly binaries are available [here](https://github.com/SpectoLabs/hoverfly/releases/).
44+
You may find it easier to download a binary - however since the Hoverfly admin UI requires static files you will need
45+
to clone the Hoverfly repo first, and then copy the binary to the Hoverfly directory before executing it.
4146

4247
## Admin UI
4348

44-
The Hoverfly admin UI is available at [http://localhost:8888/](http://localhost:8888/). It uses the [API](api) (as described below) to change state. It also allows you to wipe the captured requests/responses and shows the number of captured records. For other functions, such as export/import, you can use the API directly.
49+
The Hoverfly admin UI is available at [http://localhost:8888/](http://localhost:8888/). It uses the [API](api)
50+
(as described below) to change state. It also allows you to wipe the captured requests/responses and shows the number
51+
of captured records. For other functions, such as export/import, you can use the API directly.
4552

4653
## Hoverfly is a proxy
4754

@@ -58,15 +65,17 @@ You can specify which site to capture or virtualize with a regular expression (b
5865
## Modes (Virtualize / Capture / Synthesize / Modify)
5966

6067
Hoverfly has different operating modes. Each mode changes the behavior of the proxy. Based on the selected mode, Hoverfly can
61-
either capture the requests and responses, look for them in the cache, or send them directly to the middleware and respond with a payload that is generated by the middleware (more on middleware below).
68+
either capture the requests and responses, look for them in the cache, or send them directly to the middleware and
69+
respond with a payload that is generated by the middleware (more on middleware below).
6270

6371
### Virtualize
6472

6573
By default, the proxy starts in virtualize mode. You can apply middleware to each response.
6674

6775
### Capture
6876

69-
When capture mode is active, Hoverfly acts as a "man-in-the-middle". It makes requests on behalf of a client and records the responses. The response is then sent back to the original client.
77+
When capture mode is active, Hoverfly acts as a "man-in-the-middle". It makes requests on behalf of a client and records
78+
the responses. The response is then sent back to the original client.
7079

7180
To switch to capture mode, you can add the "--capture" flag during startup:
7281

settings.go

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import (
44
"os"
55
)
66

7-
// Initial structure of configuration
7+
// Configuration - initial structure of configuration
88
type Configuration struct {
99
adminInterface string
1010
mode string
@@ -13,7 +13,7 @@ type Configuration struct {
1313
databaseName string
1414
}
1515

16-
// AppCondig stores application configuration
16+
// AppConfig stores application configuration
1717
var AppConfig Configuration
1818

1919
func initSettings() {
@@ -24,14 +24,8 @@ func initSettings() {
2424
if databaseName == "" {
2525
databaseName = "requests.db"
2626
}
27-
28-
// getting destination information
29-
// AppConfig.destination = "get this from cache"
30-
31-
// proxy state
32-
// should be taken from cache if we want to make it horizontally scalable (currently not needed)
27+
AppConfig.databaseName = databaseName
3328

3429
// middleware configuration
3530
AppConfig.middleware = os.Getenv("HoverflyMiddleware")
36-
3731
}

static/js/dist/home-bundle.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

static/js/src/home.jsx

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ let ModeInfoComponent = React.createClass({
3333
<div>
3434
<p>
3535
When capture mode is active, Hoverfly intercepts requests and then makes them on behalf of the client.
36-
In this mode, middleware is applied to outgoing traffic. Requests and responses are stored in Redis as JSON structures.
36+
In this mode, middleware is applied to outgoing traffic. Requests and responses are stored in
37+
embedded database as JSON structures.
3738
</p>
3839
</div>
3940
)
@@ -95,23 +96,17 @@ let StatsComponent = React.createClass({
9596
},
9697

9798
fetchData() {
98-
var url = '/records';
99+
var url = '/count';
99100
var that = this;
100101
request
101102
.get(url)
102103
.end(function (err, res) {
103104
if (err) throw err;
104105
if (that.isMounted()) {
105106
// checking whether there are any records
106-
if (res.body.data == null) {
107-
that.setState({
108-
'records': 0
109-
});
110-
} else {
111-
that.setState({
112-
'records': res.body.data.length
113-
});
114-
}
107+
that.setState({
108+
'records': res.body.count
109+
});
115110
}
116111
});
117112
},

test_tools.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,23 @@ import (
66
"net/http"
77
"net/http/httptest"
88
"net/url"
9+
"os"
910
"reflect"
1011
"testing"
1112
"time"
1213

1314
"github.com/boltdb/bolt"
1415
)
1516

17+
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
18+
const (
19+
letterIdxBits = 6 // 6 bits to represent a letter index
20+
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
21+
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
22+
)
23+
24+
const testingDatabaseName = "test.db" // very original
25+
1626
// Client structure to be injected into functions to perform HTTP calls
1727
type Client struct {
1828
HTTPClient *http.Client
@@ -57,13 +67,6 @@ func testTools(code int, body string) (*httptest.Server, *DBClient) {
5767
return server, dbClient
5868
}
5969

60-
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
61-
const (
62-
letterIdxBits = 6 // 6 bits to represent a letter index
63-
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
64-
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
65-
)
66-
6770
var src = rand.NewSource(time.Now().UnixNano())
6871

6972
func GetRandomName(n int) []byte {
@@ -84,11 +87,11 @@ func GetRandomName(n int) []byte {
8487
}
8588

8689
func setup() {
87-
db := getDB("test.db")
90+
db := getDB(testingDatabaseName)
8891
TestDB = db
8992
}
9093

9194
// teardown does some cleanup after tests
9295
func teardown() {
93-
// TODO: delete test.db file here
96+
os.Remove(testingDatabaseName)
9497
}

vendor/github.com/boltdb/bolt

Submodule bolt added at 34a0fa5

0 commit comments

Comments
 (0)