Skip to content

Commit be9a3f0

Browse files
authored
Merge feature pull request
2 parents aac7cb1 + b6d2029 commit be9a3f0

File tree

5 files changed

+63
-21
lines changed

5 files changed

+63
-21
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ Parameters:
1111
use JSON log format
1212
-level string
1313
one of debug/warn/error/off (default "info")
14+
-path string
15+
path to search recursively for X-Erised-Response-File (default ".")
1416
-port int
1517
port to listen (default 8080)
1618
-read int
@@ -47,6 +49,7 @@ Response behaviour is controlled via custom headers in the http request:
4749
|X-Erised-Headers|Returns the value(s) in the response header. Values **must** be in a JSON key/value list|
4850
|X-Erised-Location|Sets the response _Location_ to the new (redirected) URL or path, when 300 ≤ _X-Erised-Status-Code_ < 310|
4951
|X-Erised-Response-Delay|Number of **milliseconds** to wait before sending response back to client|
52+
|X-Erised-Response-File|Returns the contents of **file** in the response body. If present, _X-Erised-Data_ is ignored|
5053
|X-Erised-Status-Code|Sets the HTTP Status Code|
5154

5255
By design, no validation is performed on _X-Erised-Data_ or _X-Erised-Location_.
@@ -89,6 +92,7 @@ NetworkAuthenticationRequired or 511
8992
Any other value will resolve to 200 (OK)
9093

9194
# Release History
95+
* v0.5.3 - Add file based responses
9296
* v0.4.1 - Add route concurrency, update tests and dependencies
9397
* v0.3.4 - Add [gomega](https://onsi.github.io/gomega/) assertion library, refactor tests to use Ω assertions and minor bug fixes
9498
* v0.3.0 - Add [goblin](https://github.com/franela/goblin) framework and unit tests

cmd/erised/main.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,20 @@ import (
1313
"github.com/rs/zerolog/log"
1414
)
1515

16-
const version = "v0.4.1"
16+
const version = "v0.5.3"
1717

1818
type server struct {
1919
mux *http.ServeMux
2020
cfg *http.Server
21+
pth *string
2122
}
2223

2324
func init() {
2425
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339})
2526
zerolog.SetGlobalLevel(zerolog.InfoLevel)
2627
}
2728

28-
func newServer(port, read, write, idle int) *server {
29+
func newServer(port, read, write, idle int, path string) *server {
2930
log.Debug().Msg("entering newServer")
3031

3132
s := &server{}
@@ -37,6 +38,7 @@ func newServer(port, read, write, idle int) *server {
3738
WriteTimeout: time.Duration(write) * time.Second,
3839
IdleTimeout: time.Duration(idle) * time.Second,
3940
}
41+
s.pth = &path
4042
s.routes()
4143

4244
log.Log().
@@ -45,6 +47,7 @@ func newServer(port, read, write, idle int) *server {
4547
Str("readTimeout", s.cfg.ReadTimeout.String()).
4648
Str("writeTimeout", s.cfg.WriteTimeout.String()).
4749
Str("idleTimeout", s.cfg.IdleTimeout.String()).
50+
Str("path", path).
4851
Msg("erised server running")
4952

5053
log.Debug().Msg("leaving newServer")
@@ -66,6 +69,7 @@ func setupFlags(f *flag.FlagSet) {
6669
fmt.Println("X-Erised-Headers:\t\tReturns the value(s) in the response header(s). Values must be in a JSON array")
6770
fmt.Println("X-Erised-Location:\t\tSets the response Location when 300 ≤ X-Erised-Status-Code < 310")
6871
fmt.Println("X-Erised-Response-Delay:\tNumber of milliseconds to wait before sending response back to client")
72+
fmt.Println("X-Erised-Response-File:\t\tReturns the contents of file in the response body. If present, X-Erised-Data is ignored")
6973
fmt.Println("X-Erised-Status-Code:\t\tSets the HTTP Status Code")
7074
fmt.Println()
7175
}
@@ -82,6 +86,7 @@ func main() {
8286
it := flag.Int("idle", 120, "maximum time in seconds to wait for the next request when keep-alive is enabled")
8387
lv := flag.String("level", "info", "one of debug/info/warn/error/off")
8488
lf := flag.Bool("json", false, "use JSON log format")
89+
ph := flag.String("path", ".", "path to search recursively for X-Erised-Response-File")
8590

8691
setupFlags(flag.CommandLine)
8792
flag.Parse()
@@ -103,7 +108,7 @@ func main() {
103108
log.Logger = zerolog.New(os.Stderr).With().Timestamp().Logger()
104109
}
105110

106-
srv := newServer(*pt, *rt, *wt, *it)
111+
srv := newServer(*pt, *rt, *wt, *it, *ph)
107112

108113
if err := srv.cfg.ListenAndServe(); err != nil {
109114
switch err {

cmd/erised/serverRoutes.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7+
"io/ioutil"
78
"net/http"
9+
"os"
10+
"path/filepath"
811
"strconv"
912
"strings"
1013
"time"
@@ -34,6 +37,7 @@ func (s *server) handleLanding() http.HandlerFunc {
3437
Str("method", req.Method).
3538
Str("host", req.Host).
3639
Str("uri", req.RequestURI).
40+
Str("searchPath", *s.pth).
3741
Msg("handleLanding")
3842

3943
delay := time.Duration(0)
@@ -64,7 +68,35 @@ func (s *server) handleLanding() http.HandlerFunc {
6468
}
6569

6670
res.WriteHeader(sc)
67-
data := req.Header.Get("X-Erised-Data")
71+
72+
data := ""
73+
if fn := req.Header.Get("X-Erised-Response-File"); fn != "" {
74+
75+
err := filepath.Walk(*s.pth, func(path string, info os.FileInfo, err error) error {
76+
77+
if err != nil {
78+
log.Error().Msg("Invalid path: " + path)
79+
return nil
80+
}
81+
82+
if !info.IsDir() && filepath.Base(path) == fn {
83+
if ct, err := ioutil.ReadFile(path); err != nil {
84+
log.Error().Msg("Unable to open the file: " + path)
85+
} else {
86+
data = string(ct)
87+
}
88+
}
89+
90+
return nil
91+
})
92+
93+
if data == "" || err != nil {
94+
log.Error().Msg("File not found: " + fn)
95+
}
96+
97+
} else {
98+
data = req.Header.Get("X-Erised-Data")
99+
}
68100
s.respond(res, enc, delay, data)
69101

70102
log.Debug().Msg("leaving handleLanding")

cmd/erised/serverRoutes_test.go

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,12 @@ func TestErisedHeadersRoute(t *testing.T) {
8686
})
8787
}
8888

89-
func TestErisedLandingRouteNoWait(t *testing.T) {
89+
func TestErisedLandingRoute(t *testing.T) {
9090
zerolog.SetGlobalLevel(zerolog.Disabled)
9191
g := goblin.Goblin(t)
9292
RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) })
93-
svr := server{}
93+
path := "."
94+
svr := server{pth: &path}
9495

9596
g.Describe("Test /", func() {
9697
g.It("Should return StatusOK", func() {
@@ -183,6 +184,20 @@ func TestErisedLandingRouteNoWait(t *testing.T) {
183184
Ω(res.Header().Get("X-Headers-Two")).Should(Equal("I'm header two"))
184185
})
185186

187+
g.It("Should return serverRoutes_test.json file content in body", func() {
188+
exp := `{"Name":"serverRoutes_test"}`
189+
res := httptest.NewRecorder()
190+
req := httptest.NewRequest(http.MethodGet, "http://localhost:8080/", nil)
191+
req.Header.Set("X-Erised-Content-Type", "json")
192+
req.Header.Set("X-Erised-Response-File", "serverRoutes_test.json")
193+
svr.handleLanding().ServeHTTP(res, req)
194+
195+
Ω(res).Should(HaveHTTPStatus(http.StatusOK))
196+
Ω(res.Header().Get("Content-Type")).Should(Equal("application/json"))
197+
Ω(res.Header().Get("Content-Encoding")).Should(Equal("identity"))
198+
Ω(res.Body.String()).Should(Equal(exp))
199+
})
200+
186201
g.It("Should not fail", func() {
187202
exp := `{"hello":"world"}`
188203
res := httptest.NewRecorder()
@@ -201,21 +216,6 @@ func TestErisedLandingRouteNoWait(t *testing.T) {
201216
Ω(res.Header().Get("hello")).Should(Equal("world"))
202217
Ω(res.Body.String()).Should(Equal(exp))
203218
})
204-
})
205-
}
206-
207-
func TestErisedLandingRouteWait(t *testing.T) {
208-
zerolog.SetGlobalLevel(zerolog.Disabled)
209-
g := goblin.Goblin(t)
210-
RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) })
211-
svr := server{}
212-
213-
g.Describe("Test /", func() {
214-
215-
res := httptest.NewRecorder()
216-
req := httptest.NewRequest(http.MethodGet, "http://localhost:8080/", nil)
217-
req.Header.Set("X-Erised-Response-Delay", "2000")
218-
svr.handleLanding().ServeHTTP(res, req)
219219

220220
g.It("Should wait about 2000ms (±10ms)", func() {
221221
res := httptest.NewRecorder()

cmd/erised/serverRoutes_test.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"Name":"serverRoutes_test"}

0 commit comments

Comments
 (0)