1
0
mirror of https://github.com/labstack/echo.git synced 2025-03-19 21:17:58 +02:00

Logging middleware fixes

Signed-off-by: Vishal Rana <vr@labstack.com>
This commit is contained in:
Vishal Rana 2016-03-21 17:27:14 -07:00
parent 703174e58f
commit a66162a3d2
16 changed files with 153 additions and 155 deletions

View File

@ -157,10 +157,10 @@ const (
) )
// NewContext creates a Context object. // NewContext creates a Context object.
func NewContext(req engine.Request, res engine.Response, e *Echo) Context { func NewContext(rq engine.Request, rs engine.Response, e *Echo) Context {
return &context{ return &context{
request: req, request: rq,
response: res, response: rs,
echo: e, echo: e,
pvalues: make([]string, *e.maxParam), pvalues: make([]string, *e.maxParam),
store: make(store), store: make(store),
@ -408,11 +408,11 @@ func (c *context) Object() *context {
// ServeContent sends a response from `io.Reader`. It automatically sets the `Content-Type` // ServeContent sends a response from `io.Reader`. It automatically sets the `Content-Type`
// and `Last-Modified` headers. // and `Last-Modified` headers.
func ServeContent(req engine.Request, res engine.Response, f http.File, fi os.FileInfo) error { func ServeContent(rq engine.Request, rs engine.Response, f http.File, fi os.FileInfo) error {
res.Header().Set(ContentType, detectContentType(fi.Name())) rs.Header().Set(ContentType, detectContentType(fi.Name()))
res.Header().Set(LastModified, fi.ModTime().UTC().Format(http.TimeFormat)) rs.Header().Set(LastModified, fi.ModTime().UTC().Format(http.TimeFormat))
res.WriteHeader(http.StatusOK) rs.WriteHeader(http.StatusOK)
_, err := io.Copy(res, f) _, err := io.Copy(rs, f)
return err return err
} }
@ -423,10 +423,10 @@ func detectContentType(name string) (t string) {
return return
} }
func (c *context) Reset(req engine.Request, res engine.Response) { func (c *context) Reset(rq engine.Request, rs engine.Response) {
c.netContext = nil c.netContext = nil
c.request = req c.request = rq
c.response = res c.response = rs
c.query = nil c.query = nil
c.store = nil c.store = nil
c.handler = notFoundHandler c.handler = notFoundHandler

View File

@ -34,9 +34,9 @@ func TestContext(t *testing.T) {
invalidContent := "invalid content" invalidContent := "invalid content"
e := New() e := New()
req := test.NewRequest(POST, "/", strings.NewReader(userJSON)) rq := test.NewRequest(POST, "/", strings.NewReader(userJSON))
rec := test.NewResponseRecorder() rec := test.NewResponseRecorder()
c := NewContext(req, rec, e) c := NewContext(rq, rec, e)
// Request // Request
assert.NotNil(t, c.Request()) assert.NotNil(t, c.Request())
@ -98,7 +98,7 @@ func TestContext(t *testing.T) {
// JSON // JSON
rec = test.NewResponseRecorder() rec = test.NewResponseRecorder()
c = NewContext(req, rec, e) c = NewContext(rq, rec, e)
err = c.JSON(http.StatusOK, user{"1", "Joe"}) err = c.JSON(http.StatusOK, user{"1", "Joe"})
if assert.NoError(t, err) { if assert.NoError(t, err) {
assert.Equal(t, http.StatusOK, rec.Status()) assert.Equal(t, http.StatusOK, rec.Status())
@ -108,13 +108,13 @@ func TestContext(t *testing.T) {
// JSON (error) // JSON (error)
rec = test.NewResponseRecorder() rec = test.NewResponseRecorder()
c = NewContext(req, rec, e) c = NewContext(rq, rec, e)
err = c.JSON(http.StatusOK, make(chan bool)) err = c.JSON(http.StatusOK, make(chan bool))
assert.Error(t, err) assert.Error(t, err)
// JSONP // JSONP
rec = test.NewResponseRecorder() rec = test.NewResponseRecorder()
c = NewContext(req, rec, e) c = NewContext(rq, rec, e)
callback := "callback" callback := "callback"
err = c.JSONP(http.StatusOK, callback, user{"1", "Joe"}) err = c.JSONP(http.StatusOK, callback, user{"1", "Joe"})
if assert.NoError(t, err) { if assert.NoError(t, err) {
@ -125,7 +125,7 @@ func TestContext(t *testing.T) {
// XML // XML
rec = test.NewResponseRecorder() rec = test.NewResponseRecorder()
c = NewContext(req, rec, e) c = NewContext(rq, rec, e)
err = c.XML(http.StatusOK, user{"1", "Joe"}) err = c.XML(http.StatusOK, user{"1", "Joe"})
if assert.NoError(t, err) { if assert.NoError(t, err) {
assert.Equal(t, http.StatusOK, rec.Status()) assert.Equal(t, http.StatusOK, rec.Status())
@ -135,13 +135,13 @@ func TestContext(t *testing.T) {
// XML (error) // XML (error)
rec = test.NewResponseRecorder() rec = test.NewResponseRecorder()
c = NewContext(req, rec, e) c = NewContext(rq, rec, e)
err = c.XML(http.StatusOK, make(chan bool)) err = c.XML(http.StatusOK, make(chan bool))
assert.Error(t, err) assert.Error(t, err)
// String // String
rec = test.NewResponseRecorder() rec = test.NewResponseRecorder()
c = NewContext(req, rec, e) c = NewContext(rq, rec, e)
err = c.String(http.StatusOK, "Hello, World!") err = c.String(http.StatusOK, "Hello, World!")
if assert.NoError(t, err) { if assert.NoError(t, err) {
assert.Equal(t, http.StatusOK, rec.Status()) assert.Equal(t, http.StatusOK, rec.Status())
@ -151,7 +151,7 @@ func TestContext(t *testing.T) {
// HTML // HTML
rec = test.NewResponseRecorder() rec = test.NewResponseRecorder()
c = NewContext(req, rec, e) c = NewContext(rq, rec, e)
err = c.HTML(http.StatusOK, "Hello, <strong>World!</strong>") err = c.HTML(http.StatusOK, "Hello, <strong>World!</strong>")
if assert.NoError(t, err) { if assert.NoError(t, err) {
assert.Equal(t, http.StatusOK, rec.Status()) assert.Equal(t, http.StatusOK, rec.Status())
@ -161,7 +161,7 @@ func TestContext(t *testing.T) {
// Attachment // Attachment
rec = test.NewResponseRecorder() rec = test.NewResponseRecorder()
c = NewContext(req, rec, e) c = NewContext(rq, rec, e)
file, err := os.Open("_fixture/images/walle.png") file, err := os.Open("_fixture/images/walle.png")
if assert.NoError(t, err) { if assert.NoError(t, err) {
err = c.Attachment(file, "walle.png") err = c.Attachment(file, "walle.png")
@ -174,25 +174,25 @@ func TestContext(t *testing.T) {
// NoContent // NoContent
rec = test.NewResponseRecorder() rec = test.NewResponseRecorder()
c = NewContext(req, rec, e) c = NewContext(rq, rec, e)
c.NoContent(http.StatusOK) c.NoContent(http.StatusOK)
assert.Equal(t, http.StatusOK, rec.Status()) assert.Equal(t, http.StatusOK, rec.Status())
// Redirect // Redirect
rec = test.NewResponseRecorder() rec = test.NewResponseRecorder()
c = NewContext(req, rec, e) c = NewContext(rq, rec, e)
assert.Equal(t, nil, c.Redirect(http.StatusMovedPermanently, "http://labstack.github.io/echo")) assert.Equal(t, nil, c.Redirect(http.StatusMovedPermanently, "http://labstack.github.io/echo"))
assert.Equal(t, "http://labstack.github.io/echo", rec.Header().Get(Location)) assert.Equal(t, "http://labstack.github.io/echo", rec.Header().Get(Location))
assert.Equal(t, http.StatusMovedPermanently, rec.Status()) assert.Equal(t, http.StatusMovedPermanently, rec.Status())
// Error // Error
rec = test.NewResponseRecorder() rec = test.NewResponseRecorder()
c = NewContext(req, rec, e) c = NewContext(rq, rec, e)
c.Error(errors.New("error")) c.Error(errors.New("error"))
assert.Equal(t, http.StatusInternalServerError, rec.Status()) assert.Equal(t, http.StatusInternalServerError, rec.Status())
// Reset // Reset
c.Object().Reset(req, test.NewResponseRecorder()) c.Object().Reset(rq, test.NewResponseRecorder())
} }
func TestContextPath(t *testing.T) { func TestContextPath(t *testing.T) {
@ -214,8 +214,8 @@ func TestContextQueryParam(t *testing.T) {
q := make(url.Values) q := make(url.Values)
q.Set("name", "joe") q.Set("name", "joe")
q.Set("email", "joe@labstack.com") q.Set("email", "joe@labstack.com")
req := test.NewRequest(GET, "/?"+q.Encode(), nil) rq := test.NewRequest(GET, "/?"+q.Encode(), nil)
c := NewContext(req, nil, New()) c := NewContext(rq, nil, New())
assert.Equal(t, "joe", c.QueryParam("name")) assert.Equal(t, "joe", c.QueryParam("name"))
assert.Equal(t, "joe@labstack.com", c.QueryParam("email")) assert.Equal(t, "joe@labstack.com", c.QueryParam("email"))
} }
@ -225,10 +225,10 @@ func TestContextFormValue(t *testing.T) {
f.Set("name", "joe") f.Set("name", "joe")
f.Set("email", "joe@labstack.com") f.Set("email", "joe@labstack.com")
req := test.NewRequest(POST, "/", strings.NewReader(f.Encode())) rq := test.NewRequest(POST, "/", strings.NewReader(f.Encode()))
req.Header().Add(ContentType, ApplicationForm) rq.Header().Add(ContentType, ApplicationForm)
c := NewContext(req, nil, New()) c := NewContext(rq, nil, New())
assert.Equal(t, "joe", c.FormValue("name")) assert.Equal(t, "joe", c.FormValue("name"))
assert.Equal(t, "joe@labstack.com", c.FormValue("email")) assert.Equal(t, "joe@labstack.com", c.FormValue("email"))
} }

12
echo.go
View File

@ -496,9 +496,9 @@ func (e *Echo) PutContext(c Context) {
e.pool.Put(c) e.pool.Put(c)
} }
func (e *Echo) ServeHTTP(req engine.Request, res engine.Response) { func (e *Echo) ServeHTTP(rq engine.Request, rs engine.Response) {
c := e.pool.Get().(*context) c := e.pool.Get().(*context)
c.Reset(req, res) c.Reset(rq, rs)
// Execute chain // Execute chain
if err := e.head.Handle(c); err != nil { if err := e.head.Handle(c); err != nil {
@ -531,15 +531,15 @@ func (e *HTTPError) Error() string {
} }
func (binder) Bind(i interface{}, c Context) (err error) { func (binder) Bind(i interface{}, c Context) (err error) {
req := c.Request() rq := c.Request()
ct := req.Header().Get(ContentType) ct := rq.Header().Get(ContentType)
err = ErrUnsupportedMediaType err = ErrUnsupportedMediaType
if strings.HasPrefix(ct, ApplicationJSON) { if strings.HasPrefix(ct, ApplicationJSON) {
if err = json.NewDecoder(req.Body()).Decode(i); err != nil { if err = json.NewDecoder(rq.Body()).Decode(i); err != nil {
err = NewHTTPError(http.StatusBadRequest, err.Error()) err = NewHTTPError(http.StatusBadRequest, err.Error())
} }
} else if strings.HasPrefix(ct, ApplicationXML) { } else if strings.HasPrefix(ct, ApplicationXML) {
if err = xml.NewDecoder(req.Body()).Decode(i); err != nil { if err = xml.NewDecoder(rq.Body()).Decode(i); err != nil {
err = NewHTTPError(http.StatusBadRequest, err.Error()) err = NewHTTPError(http.StatusBadRequest, err.Error())
} }
} }

View File

@ -24,9 +24,9 @@ type (
func TestEcho(t *testing.T) { func TestEcho(t *testing.T) {
e := New() e := New()
req := test.NewRequest(GET, "/", nil) rq := test.NewRequest(GET, "/", nil)
rec := test.NewResponseRecorder() rec := test.NewResponseRecorder()
c := NewContext(req, rec, e) c := NewContext(rq, rec, e)
// Router // Router
assert.NotNil(t, e.Router()) assert.NotNil(t, e.Router())
@ -290,9 +290,9 @@ func TestEchoGroup(t *testing.T) {
func TestEchoNotFound(t *testing.T) { func TestEchoNotFound(t *testing.T) {
e := New() e := New()
req := test.NewRequest(GET, "/files", nil) rq := test.NewRequest(GET, "/files", nil)
rec := test.NewResponseRecorder() rec := test.NewResponseRecorder()
e.ServeHTTP(req, rec) e.ServeHTTP(rq, rec)
assert.Equal(t, http.StatusNotFound, rec.Status()) assert.Equal(t, http.StatusNotFound, rec.Status())
} }
@ -301,9 +301,9 @@ func TestEchoMethodNotAllowed(t *testing.T) {
e.Get("/", HandlerFunc(func(c Context) error { e.Get("/", HandlerFunc(func(c Context) error {
return c.String(http.StatusOK, "Echo!") return c.String(http.StatusOK, "Echo!")
})) }))
req := test.NewRequest(POST, "/", nil) rq := test.NewRequest(POST, "/", nil)
rec := test.NewResponseRecorder() rec := test.NewResponseRecorder()
e.ServeHTTP(req, rec) e.ServeHTTP(rq, rec)
assert.Equal(t, http.StatusMethodNotAllowed, rec.Status()) assert.Equal(t, http.StatusMethodNotAllowed, rec.Status())
} }
@ -329,8 +329,8 @@ func testMethod(t *testing.T, method, path string, e *Echo) {
} }
func request(method, path string, e *Echo) (int, string) { func request(method, path string, e *Echo) (int, string) {
req := test.NewRequest(method, path, nil) rq := test.NewRequest(method, path, nil)
rec := test.NewResponseRecorder() rec := test.NewResponseRecorder()
e.ServeHTTP(req, rec) e.ServeHTTP(rq, rec)
return rec.Status(), rec.Body.String() return rec.Status(), rec.Body.String()
} }

View File

@ -158,6 +158,6 @@ type (
) )
// ServeHTTP serves HTTP request. // ServeHTTP serves HTTP request.
func (h HandlerFunc) ServeHTTP(req Request, res Response) { func (h HandlerFunc) ServeHTTP(rq Request, rs Response) {
h(req, res) h(rq, rs)
} }

View File

@ -78,7 +78,7 @@ func NewFromConfig(c engine.Config) (s *Server) {
}, },
}, },
}, },
handler: engine.HandlerFunc(func(req engine.Request, res engine.Response) { handler: engine.HandlerFunc(func(rq engine.Request, rs engine.Response) {
s.logger.Error("handler not set, use `SetHandler()` to set it.") s.logger.Error("handler not set, use `SetHandler()` to set it.")
}), }),
logger: log.New("echo"), logger: log.New("echo"),
@ -124,25 +124,25 @@ func (s *Server) startCustomListener() error {
func (s *Server) ServeHTTP(c *fasthttp.RequestCtx) { func (s *Server) ServeHTTP(c *fasthttp.RequestCtx) {
// Request // Request
req := s.pool.request.Get().(*Request) rq := s.pool.request.Get().(*Request)
reqHdr := s.pool.requestHeader.Get().(*RequestHeader) reqHdr := s.pool.requestHeader.Get().(*RequestHeader)
reqURL := s.pool.url.Get().(*URL) reqURL := s.pool.url.Get().(*URL)
reqHdr.reset(&c.Request.Header) reqHdr.reset(&c.Request.Header)
reqURL.reset(c.URI()) reqURL.reset(c.URI())
req.reset(c, reqHdr, reqURL) rq.reset(c, reqHdr, reqURL)
// Response // Response
res := s.pool.response.Get().(*Response) rs := s.pool.response.Get().(*Response)
resHdr := s.pool.responseHeader.Get().(*ResponseHeader) resHdr := s.pool.responseHeader.Get().(*ResponseHeader)
resHdr.reset(&c.Response.Header) resHdr.reset(&c.Response.Header)
res.reset(c, resHdr) rs.reset(c, resHdr)
s.handler.ServeHTTP(req, res) s.handler.ServeHTTP(rq, rs)
s.pool.request.Put(req) s.pool.request.Put(rq)
s.pool.requestHeader.Put(reqHdr) s.pool.requestHeader.Put(reqHdr)
s.pool.url.Put(reqURL) s.pool.url.Put(reqURL)
s.pool.response.Put(res) s.pool.response.Put(rs)
s.pool.responseHeader.Put(resHdr) s.pool.responseHeader.Put(resHdr)
} }

View File

@ -104,8 +104,8 @@ func (r *Request) MultipartForm() (*multipart.Form, error) {
return r.Request.MultipartForm, err return r.Request.MultipartForm, err
} }
func (r *Request) reset(req *http.Request, h engine.Header, u engine.URL) { func (r *Request) reset(rq *http.Request, h engine.Header, u engine.URL) {
r.Request = req r.Request = rq
r.header = h r.header = h
r.url = u r.url = u
} }

View File

@ -70,7 +70,7 @@ func NewFromConfig(c engine.Config) (s *Server) {
}, },
}, },
}, },
handler: engine.HandlerFunc(func(req engine.Request, res engine.Response) { handler: engine.HandlerFunc(func(rq engine.Request, rs engine.Response) {
s.logger.Error("handler not set, use `SetHandler()` to set it.") s.logger.Error("handler not set, use `SetHandler()` to set it.")
}), }),
logger: log.New("echo"), logger: log.New("echo"),
@ -113,25 +113,25 @@ func (s *Server) startCustomListener() error {
// ServeHTTP implements `http.Handler` interface. // ServeHTTP implements `http.Handler` interface.
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Request // Request
req := s.pool.request.Get().(*Request) rq := s.pool.request.Get().(*Request)
reqHdr := s.pool.header.Get().(*Header) reqHdr := s.pool.header.Get().(*Header)
reqURL := s.pool.url.Get().(*URL) reqURL := s.pool.url.Get().(*URL)
reqHdr.reset(r.Header) reqHdr.reset(r.Header)
reqURL.reset(r.URL) reqURL.reset(r.URL)
req.reset(r, reqHdr, reqURL) rq.reset(r, reqHdr, reqURL)
// Response // Response
res := s.pool.response.Get().(*Response) rs := s.pool.response.Get().(*Response)
resHdr := s.pool.header.Get().(*Header) resHdr := s.pool.header.Get().(*Header)
resHdr.reset(w.Header()) resHdr.reset(w.Header())
res.reset(w, resHdr) rs.reset(w, resHdr)
s.handler.ServeHTTP(req, res) s.handler.ServeHTTP(rq, rs)
s.pool.request.Put(req) s.pool.request.Put(rq)
s.pool.header.Put(reqHdr) s.pool.header.Put(reqHdr)
s.pool.url.Put(reqURL) s.pool.url.Put(reqURL)
s.pool.response.Put(res) s.pool.response.Put(rs)
s.pool.header.Put(resHdr) s.pool.header.Put(resHdr)
} }
@ -152,16 +152,16 @@ func WrapHandler(h http.Handler) echo.HandlerFunc {
func WrapMiddleware(m func(http.Handler) http.Handler) echo.MiddlewareFunc { func WrapMiddleware(m func(http.Handler) http.Handler) echo.MiddlewareFunc {
return func(next echo.Handler) echo.Handler { return func(next echo.Handler) echo.Handler {
return echo.HandlerFunc(func(c echo.Context) (err error) { return echo.HandlerFunc(func(c echo.Context) (err error) {
req := c.Request().(*Request) rq := c.Request().(*Request)
res := c.Response().(*Response) rs := c.Response().(*Response)
m(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { m(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
res.ResponseWriter = &responseAdapter{ rs.ResponseWriter = &responseAdapter{
ResponseWriter: res.ResponseWriter, ResponseWriter: rs.ResponseWriter,
writer: c.Response(), writer: c.Response(),
} }
req.Request = r rq.Request = r
err = next.Handle(c) err = next.Handle(c)
})).ServeHTTP(res.ResponseWriter, req.Request) })).ServeHTTP(rs.ResponseWriter, rq.Request)
return return
}) })
} }

View File

@ -12,9 +12,9 @@ import (
func TestBasicAuth(t *testing.T) { func TestBasicAuth(t *testing.T) {
e := echo.New() e := echo.New()
req := test.NewRequest(echo.GET, "/", nil) rq := test.NewRequest(echo.GET, "/", nil)
res := test.NewResponseRecorder() rs := test.NewResponseRecorder()
c := echo.NewContext(req, res, e) c := echo.NewContext(rq, rs, e)
f := func(u, p string) bool { f := func(u, p string) bool {
if u == "joe" && p == "secret" { if u == "joe" && p == "secret" {
return true return true
@ -27,7 +27,7 @@ func TestBasicAuth(t *testing.T) {
// Valid credentials // Valid credentials
auth := basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:secret")) auth := basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:secret"))
req.Header().Set(echo.Authorization, auth) rq.Header().Set(echo.Authorization, auth)
assert.NoError(t, h.Handle(c)) assert.NoError(t, h.Handle(c))
//--------------------- //---------------------
@ -36,21 +36,21 @@ func TestBasicAuth(t *testing.T) {
// Incorrect password // Incorrect password
auth = basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:password")) auth = basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:password"))
req.Header().Set(echo.Authorization, auth) rq.Header().Set(echo.Authorization, auth)
he := h.Handle(c).(*echo.HTTPError) he := h.Handle(c).(*echo.HTTPError)
assert.Equal(t, http.StatusUnauthorized, he.Code) assert.Equal(t, http.StatusUnauthorized, he.Code)
assert.Equal(t, basic+" realm=Restricted", res.Header().Get(echo.WWWAuthenticate)) assert.Equal(t, basic+" realm=Restricted", rs.Header().Get(echo.WWWAuthenticate))
// Empty Authorization header // Empty Authorization header
req.Header().Set(echo.Authorization, "") rq.Header().Set(echo.Authorization, "")
he = h.Handle(c).(*echo.HTTPError) he = h.Handle(c).(*echo.HTTPError)
assert.Equal(t, http.StatusUnauthorized, he.Code) assert.Equal(t, http.StatusUnauthorized, he.Code)
assert.Equal(t, basic+" realm=Restricted", res.Header().Get(echo.WWWAuthenticate)) assert.Equal(t, basic+" realm=Restricted", rs.Header().Get(echo.WWWAuthenticate))
// Invalid Authorization header // Invalid Authorization header
auth = base64.StdEncoding.EncodeToString([]byte("invalid")) auth = base64.StdEncoding.EncodeToString([]byte("invalid"))
req.Header().Set(echo.Authorization, auth) rq.Header().Set(echo.Authorization, auth)
he = h.Handle(c).(*echo.HTTPError) he = h.Handle(c).(*echo.HTTPError)
assert.Equal(t, http.StatusUnauthorized, he.Code) assert.Equal(t, http.StatusUnauthorized, he.Code)
assert.Equal(t, basic+" realm=Restricted", res.Header().Get(echo.WWWAuthenticate)) assert.Equal(t, basic+" realm=Restricted", rs.Header().Get(echo.WWWAuthenticate))
} }

View File

@ -14,9 +14,9 @@ import (
func TestGzip(t *testing.T) { func TestGzip(t *testing.T) {
e := echo.New() e := echo.New()
req := test.NewRequest(echo.GET, "/", nil) rq := test.NewRequest(echo.GET, "/", nil)
rec := test.NewResponseRecorder() rec := test.NewResponseRecorder()
c := echo.NewContext(req, rec, e) c := echo.NewContext(rq, rec, e)
// Skip if no Accept-Encoding header // Skip if no Accept-Encoding header
h := Gzip()(echo.HandlerFunc(func(c echo.Context) error { h := Gzip()(echo.HandlerFunc(func(c echo.Context) error {
@ -26,10 +26,10 @@ func TestGzip(t *testing.T) {
h.Handle(c) h.Handle(c)
assert.Equal(t, "test", rec.Body.String()) assert.Equal(t, "test", rec.Body.String())
req = test.NewRequest(echo.GET, "/", nil) rq = test.NewRequest(echo.GET, "/", nil)
req.Header().Set(echo.AcceptEncoding, "gzip") rq.Header().Set(echo.AcceptEncoding, "gzip")
rec = test.NewResponseRecorder() rec = test.NewResponseRecorder()
c = echo.NewContext(req, rec, e) c = echo.NewContext(rq, rec, e)
// Gzip // Gzip
h.Handle(c) h.Handle(c)
@ -46,9 +46,9 @@ func TestGzip(t *testing.T) {
func TestGzipNoContent(t *testing.T) { func TestGzipNoContent(t *testing.T) {
e := echo.New() e := echo.New()
req := test.NewRequest(echo.GET, "/", nil) rq := test.NewRequest(echo.GET, "/", nil)
rec := test.NewResponseRecorder() rec := test.NewResponseRecorder()
c := echo.NewContext(req, rec, e) c := echo.NewContext(rq, rec, e)
h := Gzip()(echo.HandlerFunc(func(c echo.Context) error { h := Gzip()(echo.HandlerFunc(func(c echo.Context) error {
return c.NoContent(http.StatusOK) return c.NoContent(http.StatusOK)
})) }))
@ -68,9 +68,9 @@ func TestGzipErrorReturned(t *testing.T) {
e.Get("/", echo.HandlerFunc(func(c echo.Context) error { e.Get("/", echo.HandlerFunc(func(c echo.Context) error {
return echo.NewHTTPError(http.StatusInternalServerError, "error") return echo.NewHTTPError(http.StatusInternalServerError, "error")
})) }))
req := test.NewRequest(echo.GET, "/", nil) rq := test.NewRequest(echo.GET, "/", nil)
rec := test.NewResponseRecorder() rec := test.NewResponseRecorder()
e.ServeHTTP(req, rec) e.ServeHTTP(rq, rec)
assert.Empty(t, rec.Header().Get(echo.ContentEncoding)) assert.Empty(t, rec.Header().Get(echo.ContentEncoding))
b, err := ioutil.ReadAll(rec.Body) b, err := ioutil.ReadAll(rec.Body)

View File

@ -24,6 +24,7 @@ type (
// Available tags: // Available tags:
// - time_rfc3339 // - time_rfc3339
// - remote_ip // - remote_ip
// - uri
// - method // - method
// - path // - path
// - status // - status
@ -42,7 +43,8 @@ type (
var ( var (
// DefaultLoggerConfig is the default logger middleware config. // DefaultLoggerConfig is the default logger middleware config.
DefaultLoggerConfig = LoggerConfig{ DefaultLoggerConfig = LoggerConfig{
Format: "time=${time_rfc3339}, remote_ip=${remote_ip}, method=${method}, path=${path}, status=${status}, response_time=${response_time}, response_size=${response_size} bytes\n", Format: "time=${time_rfc3339}, remote_ip=${remote_ip}, method=${method}, " +
"path=${path}, status=${status}, took=${response_time}, sent=t=${response_size} bytes\n",
color: color.New(), color: color.New(),
Output: os.Stdout, Output: os.Stdout,
} }
@ -64,58 +66,54 @@ func LoggerFromConfig(config LoggerConfig) echo.MiddlewareFunc {
return func(next echo.Handler) echo.Handler { return func(next echo.Handler) echo.Handler {
return echo.HandlerFunc(func(c echo.Context) (err error) { return echo.HandlerFunc(func(c echo.Context) (err error) {
req := c.Request() rq := c.Request()
res := c.Response() rs := c.Response()
remoteAddr := req.RemoteAddress()
if ip := req.Header().Get(echo.XRealIP); ip != "" {
remoteAddr = ip
} else if ip = req.Header().Get(echo.XForwardedFor); ip != "" {
remoteAddr = ip
} else {
remoteAddr, _, _ = net.SplitHostPort(remoteAddr)
}
start := time.Now() start := time.Now()
if err := next.Handle(c); err != nil { if err := next.Handle(c); err != nil {
c.Error(err) c.Error(err)
} }
stop := time.Now() stop := time.Now()
method := []byte(req.Method())
path := req.URL().Path()
if path == "" {
path = "/"
}
took := stop.Sub(start)
size := strconv.FormatInt(res.Size(), 10)
n := res.Status()
status := color.Green(n)
switch {
case n >= 500:
status = color.Red(n)
case n >= 400:
status = color.Yellow(n)
case n >= 300:
status = color.Cyan(n)
}
_, err = config.template.ExecuteFunc(config.Output, func(w io.Writer, tag string) (int, error) { _, err = config.template.ExecuteFunc(config.Output, func(w io.Writer, tag string) (int, error) {
switch tag { switch tag {
case "time_rfc3339": case "time_rfc3339":
return w.Write([]byte(time.Now().Format(time.RFC3339))) return w.Write([]byte(time.Now().Format(time.RFC3339)))
case "remote_ip": case "remote_ip":
return w.Write([]byte(remoteAddr)) ra := rq.RemoteAddress()
if ip := rq.Header().Get(echo.XRealIP); ip != "" {
ra = ip
} else if ip = rq.Header().Get(echo.XForwardedFor); ip != "" {
ra = ip
} else {
ra, _, _ = net.SplitHostPort(ra)
}
return w.Write([]byte(ra))
case "uri":
return w.Write([]byte(rq.URI()))
case "method": case "method":
return w.Write(method) return w.Write([]byte(rq.Method()))
case "path": case "path":
return w.Write([]byte(path)) p := rq.URL().Path()
if p == "" {
p = "/"
}
return w.Write([]byte(p))
case "status": case "status":
return w.Write([]byte(status)) n := rs.Status()
s := color.Green(n)
switch {
case n >= 500:
s = color.Red(n)
case n >= 400:
s = color.Yellow(n)
case n >= 300:
s = color.Cyan(n)
}
return w.Write([]byte(s))
case "response_time": case "response_time":
return w.Write([]byte(took.String())) return w.Write([]byte(stop.Sub(start).String()))
case "response_size": case "response_size":
return w.Write([]byte(size)) return w.Write([]byte(strconv.FormatInt(rs.Size(), 10)))
default: default:
return w.Write([]byte(fmt.Sprintf("[unknown tag %s]", tag))) return w.Write([]byte(fmt.Sprintf("[unknown tag %s]", tag)))
} }

View File

@ -14,9 +14,9 @@ import (
func TestLogger(t *testing.T) { func TestLogger(t *testing.T) {
// Note: Just for the test coverage, not a real test. // Note: Just for the test coverage, not a real test.
e := echo.New() e := echo.New()
req := test.NewRequest(echo.GET, "/", nil) rq := test.NewRequest(echo.GET, "/", nil)
rec := test.NewResponseRecorder() rec := test.NewResponseRecorder()
c := echo.NewContext(req, rec, e) c := echo.NewContext(rq, rec, e)
h := Logger()(echo.HandlerFunc(func(c echo.Context) error { h := Logger()(echo.HandlerFunc(func(c echo.Context) error {
return c.String(http.StatusOK, "test") return c.String(http.StatusOK, "test")
})) }))
@ -26,7 +26,7 @@ func TestLogger(t *testing.T) {
// Status 3xx // Status 3xx
rec = test.NewResponseRecorder() rec = test.NewResponseRecorder()
c = echo.NewContext(req, rec, e) c = echo.NewContext(rq, rec, e)
h = Logger()(echo.HandlerFunc(func(c echo.Context) error { h = Logger()(echo.HandlerFunc(func(c echo.Context) error {
return c.String(http.StatusTemporaryRedirect, "test") return c.String(http.StatusTemporaryRedirect, "test")
})) }))
@ -34,16 +34,16 @@ func TestLogger(t *testing.T) {
// Status 4xx // Status 4xx
rec = test.NewResponseRecorder() rec = test.NewResponseRecorder()
c = echo.NewContext(req, rec, e) c = echo.NewContext(rq, rec, e)
h = Logger()(echo.HandlerFunc(func(c echo.Context) error { h = Logger()(echo.HandlerFunc(func(c echo.Context) error {
return c.String(http.StatusNotFound, "test") return c.String(http.StatusNotFound, "test")
})) }))
h.Handle(c) h.Handle(c)
// Status 5xx with empty path // Status 5xx with empty path
req = test.NewRequest(echo.GET, "", nil) rq = test.NewRequest(echo.GET, "", nil)
rec = test.NewResponseRecorder() rec = test.NewResponseRecorder()
c = echo.NewContext(req, rec, e) c = echo.NewContext(rq, rec, e)
h = Logger()(echo.HandlerFunc(func(c echo.Context) error { h = Logger()(echo.HandlerFunc(func(c echo.Context) error {
return errors.New("error") return errors.New("error")
})) }))
@ -52,9 +52,9 @@ func TestLogger(t *testing.T) {
func TestLoggerIPAddress(t *testing.T) { func TestLoggerIPAddress(t *testing.T) {
e := echo.New() e := echo.New()
req := test.NewRequest(echo.GET, "/", nil) rq := test.NewRequest(echo.GET, "/", nil)
rec := test.NewResponseRecorder() rec := test.NewResponseRecorder()
c := echo.NewContext(req, rec, e) c := echo.NewContext(rq, rec, e)
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
e.Logger().SetOutput(buf) e.Logger().SetOutput(buf)
ip := "127.0.0.1" ip := "127.0.0.1"
@ -63,18 +63,18 @@ func TestLoggerIPAddress(t *testing.T) {
})) }))
// With X-Real-IP // With X-Real-IP
req.Header().Add(echo.XRealIP, ip) rq.Header().Add(echo.XRealIP, ip)
h.Handle(c) h.Handle(c)
assert.Contains(t, ip, buf.String()) assert.Contains(t, ip, buf.String())
// With X-Forwarded-For // With X-Forwarded-For
buf.Reset() buf.Reset()
req.Header().Del(echo.XRealIP) rq.Header().Del(echo.XRealIP)
req.Header().Add(echo.XForwardedFor, ip) rq.Header().Add(echo.XForwardedFor, ip)
h.Handle(c) h.Handle(c)
assert.Contains(t, ip, buf.String()) assert.Contains(t, ip, buf.String())
// with req.RemoteAddr // with rq.RemoteAddr
buf.Reset() buf.Reset()
h.Handle(c) h.Handle(c)
assert.Contains(t, ip, buf.String()) assert.Contains(t, ip, buf.String())

View File

@ -15,9 +15,9 @@ func TestRecover(t *testing.T) {
e.SetDebug(true) e.SetDebug(true)
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
e.SetLogOutput(buf) e.SetLogOutput(buf)
req := test.NewRequest(echo.GET, "/", nil) rq := test.NewRequest(echo.GET, "/", nil)
rec := test.NewResponseRecorder() rec := test.NewResponseRecorder()
c := echo.NewContext(req, rec, e) c := echo.NewContext(rq, rec, e)
h := Recover()(echo.HandlerFunc(func(c echo.Context) error { h := Recover()(echo.HandlerFunc(func(c echo.Context) error {
panic("test") panic("test")
})) }))

View File

@ -75,9 +75,9 @@ func StaticFromConfig(config StaticConfig) echo.MiddlewareFunc {
} }
// Create a directory index // Create a directory index
res := c.Response() rs := c.Response()
res.Header().Set(echo.ContentType, echo.TextHTMLCharsetUTF8) rs.Header().Set(echo.ContentType, echo.TextHTMLCharsetUTF8)
if _, err = fmt.Fprintf(res, "<pre>\n"); err != nil { if _, err = fmt.Fprintf(rs, "<pre>\n"); err != nil {
return err return err
} }
for _, d := range dirs { for _, d := range dirs {
@ -87,11 +87,11 @@ func StaticFromConfig(config StaticConfig) echo.MiddlewareFunc {
color = "#e91e63" color = "#e91e63"
name += "/" name += "/"
} }
if _, err = fmt.Fprintf(res, "<a href=\"%s\" style=\"color: %s;\">%s</a>\n", name, color, name); err != nil { if _, err = fmt.Fprintf(rs, "<a href=\"%s\" style=\"color: %s;\">%s</a>\n", name, color, name); err != nil {
return err return err
} }
} }
_, err = fmt.Fprintf(res, "</pre>\n") _, err = fmt.Fprintf(rs, "</pre>\n")
return err return err
} }
return next.Handle(c) return next.Handle(c)

View File

@ -98,8 +98,8 @@ func (r *Request) MultipartForm() (*multipart.Form, error) {
return r.request.MultipartForm, err return r.request.MultipartForm, err
} }
func (r *Request) reset(req *http.Request, h engine.Header, u engine.URL) { func (r *Request) reset(rq *http.Request, h engine.Header, u engine.URL) {
r.request = req r.request = rq
r.header = h r.header = h
r.url = u r.url = u
} }

View File

@ -65,7 +65,7 @@ func NewConfig(c *engine.Config) (s *Server) {
}, },
}, },
}, },
handler: engine.HandlerFunc(func(req engine.Request, res engine.Response) { handler: engine.HandlerFunc(func(rq engine.Request, rs engine.Response) {
s.logger.Fatal("handler not set") s.logger.Fatal("handler not set")
}), }),
logger: log.New("echo"), logger: log.New("echo"),
@ -95,24 +95,24 @@ func (s *Server) Start() {
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Request // Request
req := s.pool.request.Get().(*Request) rq := s.pool.request.Get().(*Request)
reqHdr := s.pool.header.Get().(*Header) reqHdr := s.pool.header.Get().(*Header)
reqURL := s.pool.url.Get().(*URL) reqURL := s.pool.url.Get().(*URL)
reqHdr.reset(r.Header) reqHdr.reset(r.Header)
reqURL.reset(r.URL) reqURL.reset(r.URL)
req.reset(r, reqHdr, reqURL) rq.reset(r, reqHdr, reqURL)
// Response // Response
res := s.pool.response.Get().(*Response) rs := s.pool.response.Get().(*Response)
resHdr := s.pool.header.Get().(*Header) resHdr := s.pool.header.Get().(*Header)
resHdr.reset(w.Header()) resHdr.reset(w.Header())
res.reset(w, resHdr) rs.reset(w, resHdr)
s.handler.ServeHTTP(req, res) s.handler.ServeHTTP(rq, rs)
s.pool.request.Put(req) s.pool.request.Put(rq)
s.pool.header.Put(reqHdr) s.pool.header.Put(reqHdr)
s.pool.url.Put(reqURL) s.pool.url.Put(reqURL)
s.pool.response.Put(res) s.pool.response.Put(rs)
s.pool.header.Put(resHdr) s.pool.header.Put(resHdr)
} }