diff options
| author | Shulhan <ms@kilabit.info> | 2018-12-18 01:39:13 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2018-12-18 01:43:17 +0700 |
| commit | f4d2a279cf7b6639b1228fa55c26f3b9f4a24c0d (patch) | |
| tree | bf1d1a2d9dfbb6734f800356fcbb4d847c3ec26c /lib/http | |
| parent | 6a3a65ec455aeb4b1b072f8f3a760f6593509a5d (diff) | |
| download | pakakeh.go-f4d2a279cf7b6639b1228fa55c26f3b9f4a24c0d.tar.xz | |
lib/http: add evaluator, a middleware between request and handler
Diffstat (limited to 'lib/http')
| -rw-r--r-- | lib/http/evaluator.go | 21 | ||||
| -rw-r--r-- | lib/http/handler.go | 12 | ||||
| -rw-r--r-- | lib/http/server.go | 13 | ||||
| -rw-r--r-- | lib/http/server_test.go | 64 |
4 files changed, 107 insertions, 3 deletions
diff --git a/lib/http/evaluator.go b/lib/http/evaluator.go new file mode 100644 index 00000000..16fcd477 --- /dev/null +++ b/lib/http/evaluator.go @@ -0,0 +1,21 @@ +// Copyright 2018, Shulhan <ms@kilabit.info>. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package http + +import ( + "net/http" +) + +// +// Evaluator is an interface for middleware between actual request and handler. +// +type Evaluator interface { + // + // Evaluate the request. If request is invalid, the error will tell + // the response code and the error message to be written back to + // client. + // + Evaluate(req *http.Request, reqBody []byte) error +} diff --git a/lib/http/handler.go b/lib/http/handler.go index 0328f6fc..f35a968c 100644 --- a/lib/http/handler.go +++ b/lib/http/handler.go @@ -21,7 +21,9 @@ type handler struct { cb Callback } -func (h *handler) call(res http.ResponseWriter, req *http.Request) { +func (h *handler) call(res http.ResponseWriter, req *http.Request, + evaluators []Evaluator, +) { var ( e error reqBody []byte @@ -56,6 +58,14 @@ func (h *handler) call(res http.ResponseWriter, req *http.Request) { log.Printf("> request body: %s\n", reqBody) } + for _, eval := range evaluators { + e := eval.Evaluate(req, reqBody) + if e != nil { + h.error(res, e) + return + } + } + rspb, e := h.cb(req, reqBody) if e != nil { log.Printf("handler.call: %d %s %s %s\n", diff --git a/lib/http/server.go b/lib/http/server.go index 5ae5808d..6f72b630 100644 --- a/lib/http/server.go +++ b/lib/http/server.go @@ -23,6 +23,7 @@ import ( // type Server struct { mfs *memfs.MemFS + evals []Evaluator conn *http.Server regDelete map[string]*handler regGet map[string]*handler @@ -80,6 +81,14 @@ func (srv *Server) RegisterDelete( } // +// RegisterEvaluator register HTTP middleware that will be called before +// handler callback is called. +// +func (srv *Server) RegisterEvaluator(eval Evaluator) { + srv.evals = append(srv.evals, eval) +} + +// // RegisterGet register HTTP method GET with callback to handle it. // func (srv *Server) RegisterGet( @@ -167,7 +176,7 @@ func (srv *Server) ServeHTTP(res http.ResponseWriter, req *http.Request) { return } - h.call(res, req) + h.call(res, req, srv.evals) } // @@ -238,7 +247,7 @@ func (srv *Server) handleFS( func (srv *Server) handleGet(res http.ResponseWriter, req *http.Request) { h, ok := srv.regGet[req.URL.Path] if ok { - h.call(res, req) + h.call(res, req, srv.evals) return } diff --git a/lib/http/server_test.go b/lib/http/server_test.go index beefad40..e40276e4 100644 --- a/lib/http/server_test.go +++ b/lib/http/server_test.go @@ -180,6 +180,70 @@ func TestRegisterDelete(t *testing.T) { } } +type testEvaluator struct{} + +func (te *testEvaluator) Evaluate(req *http.Request, reqBody []byte) error { + k := req.Form.Get("k") + + if len(k) == 0 { + return &errors.E{ + Code: http.StatusBadRequest, + Message: "Missing input value for k", + } + } + + return nil +} + +func TestRegisterEvaluator(t *testing.T) { + te := new(testEvaluator) + + testServer.RegisterDelete("/evaluate", ResponseTypeJSON, cbPlain) + + testServer.RegisterEvaluator(te) + + cases := []struct { + desc string + reqURL string + expStatusCode int + }{{ + desc: "With invalid evaluate", + reqURL: "http://127.0.0.1:8080/evaluate", + expStatusCode: http.StatusBadRequest, + }, { + desc: "With valid evaluate", + reqURL: "http://127.0.0.1:8080/evaluate?k=v", + expStatusCode: http.StatusOK, + }} + + for _, c := range cases { + t.Log(c.desc) + + req, e := http.NewRequest(http.MethodDelete, c.reqURL, nil) + if e != nil { + t.Fatal(e) + } + + res, e := client.Do(req) + if e != nil { + t.Fatal(e) + } + + _, e = ioutil.ReadAll(res.Body) + if e != nil { + t.Fatal(e) + } + + e = res.Body.Close() + if e != nil { + t.Fatal(e) + } + + test.Assert(t, "StatusCode", c.expStatusCode, res.StatusCode, + true) + } +} + func TestRegisterGet(t *testing.T) { testServer.RegisterGet("/get", ResponseTypePlain, cbPlain) |
