From 9650c39055a0c031791a61efdd2b19957f382f8c Mon Sep 17 00:00:00 2001 From: Vishal Rana Date: Tue, 1 Dec 2015 11:22:45 -0800 Subject: [PATCH] Bumped to v1.3 Signed-off-by: Vishal Rana --- context.go | 7 ++++- context_test.go | 39 +++++++++++++------------ echo.go | 40 +++++++++++++++----------- echo_test.go | 2 +- middleware/auth_test.go | 3 +- middleware/compress_test.go | 9 +++--- middleware/logger.go | 4 +-- middleware/logger_test.go | 18 ++++++------ middleware/recover_test.go | 2 +- recipes/websocket/server.go | 1 - response.go | 9 +++--- response_test.go | 3 +- website/content/guide/customization.md | 17 +++++++---- 13 files changed, 86 insertions(+), 68 deletions(-) diff --git a/context.go b/context.go index 1b531191..a63dbce1 100644 --- a/context.go +++ b/context.go @@ -142,7 +142,7 @@ func (c *Context) HTML(code int, html string) (err error) { // String sends a string response with status code. func (c *Context) String(code int, s string) (err error) { - c.response.Header().Set(ContentType, TextPlain) + c.response.Header().Set(ContentType, TextPlainCharsetUTF8) c.response.WriteHeader(code) c.response.Write([]byte(s)) return @@ -255,6 +255,11 @@ func (c *Context) Error(err error) { c.echo.httpErrorHandler(err, c) } +// Echo returns the `Echo` instance. +func (c *Context) Echo() *Echo { + return c.echo +} + func (c *Context) reset(r *http.Request, w http.ResponseWriter, e *Echo) { c.request = r c.response.reset(w) diff --git a/context_test.go b/context_test.go index 27f48989..460c0d36 100644 --- a/context_test.go +++ b/context_test.go @@ -37,9 +37,10 @@ func TestContext(t *testing.T) { var nonMarshallableChannel chan bool + e := New() req, _ := http.NewRequest(POST, "/", strings.NewReader(userJSON)) rec := httptest.NewRecorder() - c := NewContext(req, NewResponse(rec), New()) + c := NewContext(req, NewResponse(rec, e), e) // Request assert.NotNil(t, c.Request()) @@ -96,7 +97,7 @@ func TestContext(t *testing.T) { // JSON rec = httptest.NewRecorder() - c = NewContext(req, NewResponse(rec), New()) + c = NewContext(req, NewResponse(rec, e), e) err = c.JSON(http.StatusOK, user{"1", "Joe"}) if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) @@ -106,14 +107,14 @@ func TestContext(t *testing.T) { // JSON (error) rec = httptest.NewRecorder() - c = NewContext(req, NewResponse(rec), New()) + c = NewContext(req, NewResponse(rec, e), e) val := make(chan bool) err = c.JSON(http.StatusOK, val) assert.Error(t, err) // JSONIndent rec = httptest.NewRecorder() - c = NewContext(req, NewResponse(rec), New()) + c = NewContext(req, NewResponse(rec, e), e) err = c.JSONIndent(http.StatusOK, user{"1", "Joe"}, "_", "?") if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) @@ -123,13 +124,13 @@ func TestContext(t *testing.T) { // JSONIndent (error) rec = httptest.NewRecorder() - c = NewContext(req, NewResponse(rec), New()) + c = NewContext(req, NewResponse(rec, e), e) err = c.JSONIndent(http.StatusOK, nonMarshallableChannel, "_", "?") assert.Error(t, err) // JSONP rec = httptest.NewRecorder() - c = NewContext(req, NewResponse(rec), New()) + c = NewContext(req, NewResponse(rec, e), e) callback := "callback" err = c.JSONP(http.StatusOK, callback, user{"1", "Joe"}) if assert.NoError(t, err) { @@ -140,7 +141,7 @@ func TestContext(t *testing.T) { // XML rec = httptest.NewRecorder() - c = NewContext(req, NewResponse(rec), New()) + c = NewContext(req, NewResponse(rec, e), e) err = c.XML(http.StatusOK, user{"1", "Joe"}) if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) @@ -150,13 +151,13 @@ func TestContext(t *testing.T) { // XML (error) rec = httptest.NewRecorder() - c = NewContext(req, NewResponse(rec), New()) + c = NewContext(req, NewResponse(rec, e), e) err = c.XML(http.StatusOK, nonMarshallableChannel) assert.Error(t, err) // XMLIndent rec = httptest.NewRecorder() - c = NewContext(req, NewResponse(rec), New()) + c = NewContext(req, NewResponse(rec, e), e) err = c.XMLIndent(http.StatusOK, user{"1", "Joe"}, "_", "?") if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) @@ -166,23 +167,23 @@ func TestContext(t *testing.T) { // XMLIndent (error) rec = httptest.NewRecorder() - c = NewContext(req, NewResponse(rec), New()) + c = NewContext(req, NewResponse(rec, e), e) err = c.XMLIndent(http.StatusOK, nonMarshallableChannel, "_", "?") assert.Error(t, err) // String rec = httptest.NewRecorder() - c = NewContext(req, NewResponse(rec), New()) + c = NewContext(req, NewResponse(rec, e), e) err = c.String(http.StatusOK, "Hello, World!") if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) - assert.Equal(t, TextPlain, rec.Header().Get(ContentType)) + assert.Equal(t, TextPlainCharsetUTF8, rec.Header().Get(ContentType)) assert.Equal(t, "Hello, World!", rec.Body.String()) } // HTML rec = httptest.NewRecorder() - c = NewContext(req, NewResponse(rec), New()) + c = NewContext(req, NewResponse(rec, e), e) err = c.HTML(http.StatusOK, "Hello, World!") if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) @@ -192,7 +193,7 @@ func TestContext(t *testing.T) { // File rec = httptest.NewRecorder() - c = NewContext(req, NewResponse(rec), New()) + c = NewContext(req, NewResponse(rec, e), e) err = c.File("test/fixture/walle.png", "", false) if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) @@ -201,7 +202,7 @@ func TestContext(t *testing.T) { // File as attachment rec = httptest.NewRecorder() - c = NewContext(req, NewResponse(rec), New()) + c = NewContext(req, NewResponse(rec, e), e) err = c.File("test/fixture/walle.png", "WALLE.PNG", true) if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) @@ -211,23 +212,23 @@ func TestContext(t *testing.T) { // NoContent rec = httptest.NewRecorder() - c = NewContext(req, NewResponse(rec), New()) + c = NewContext(req, NewResponse(rec, e), e) c.NoContent(http.StatusOK) assert.Equal(t, http.StatusOK, c.response.status) // Redirect rec = httptest.NewRecorder() - c = NewContext(req, NewResponse(rec), New()) + c = NewContext(req, NewResponse(rec, e), e) assert.Equal(t, nil, c.Redirect(http.StatusMovedPermanently, "http://labstack.github.io/echo")) // Error rec = httptest.NewRecorder() - c = NewContext(req, NewResponse(rec), New()) + c = NewContext(req, NewResponse(rec, e), e) c.Error(errors.New("error")) assert.Equal(t, http.StatusInternalServerError, c.response.status) // reset - c.reset(req, NewResponse(httptest.NewRecorder()), New()) + c.reset(req, NewResponse(httptest.NewRecorder(), e), e) } func TestContextPath(t *testing.T) { diff --git a/echo.go b/echo.go index 9dcc7797..05617e05 100644 --- a/echo.go +++ b/echo.go @@ -36,6 +36,7 @@ type ( debug bool hook http.HandlerFunc autoIndex bool + logger *log.Logger router *Router } @@ -181,8 +182,6 @@ var ( } unixEpochTime = time.Unix(0, 0) - - logger = log.New("echo") ) // New creates an instance of Echo. @@ -211,14 +210,14 @@ func New() (e *Echo) { if !c.response.committed { http.Error(c.response, msg, code) } - log.Error(err) + e.logger.Error(err) } e.SetHTTPErrorHandler(e.defaultHTTPErrorHandler) e.SetBinder(&binder{}) // Logger - log.SetPrefix("echo") - log.SetLevel(log.INFO) + e.logger = log.New("echo") + e.logger.SetLevel(log.INFO) return } @@ -228,14 +227,24 @@ func (e *Echo) Router() *Router { return e.router } -// SetOutput sets the output destination for the logger. -func SetOutput(w io.Writer) { - log.SetOutput(w) +// SetLogPrefix sets the prefix for the logger. Default value is `echo`. +func (e *Echo) SetLogPrefix(prefix string) { + e.logger.SetPrefix(prefix) } -// SetLogLevel sets the log level for global logger. The default value is `log.INFO`. -func SetLogLevel(l log.Level) { - log.SetLevel(l) +// SetLogOutput sets the output destination for the logger. Default value is `os.Std*` +func (e *Echo) SetLogOutput(w io.Writer) { + e.logger.SetOutput(w) +} + +// SetLogLevel sets the log level for the logger. Default value is `log.INFO`. +func (e *Echo) SetLogLevel(l log.Level) { + e.logger.SetLevel(l) +} + +// Logger returns the logger instance. +func (e *Echo) Logger() *log.Logger { + return e.logger } // HTTP2 enables/disables HTTP2 support. @@ -273,8 +282,7 @@ func (e *Echo) Debug() bool { return e.debug } -// AutoIndex enables/disables automatically creates a directory listing if the directory -// doesn't contain an index page. +// AutoIndex enables/disables automatically creating an index page for the directory. func (e *Echo) AutoIndex(on bool) { e.autoIndex = on } @@ -575,11 +583,11 @@ func (e *Echo) run(s *http.Server, files ...string) { http2.ConfigureServer(s, nil) } if len(files) == 0 { - log.Fatal(s.ListenAndServe()) + e.logger.Fatal(s.ListenAndServe()) } else if len(files) == 2 { - log.Fatal(s.ListenAndServeTLS(files[0], files[1])) + e.logger.Fatal(s.ListenAndServeTLS(files[0], files[1])) } else { - log.Fatal("invalid TLS configuration") + e.logger.Fatal("invalid TLS configuration") } } diff --git a/echo_test.go b/echo_test.go index 1f523569..7bba3d7a 100644 --- a/echo_test.go +++ b/echo_test.go @@ -27,7 +27,7 @@ func TestEcho(t *testing.T) { e := New() req, _ := http.NewRequest(GET, "/", nil) rec := httptest.NewRecorder() - c := NewContext(req, NewResponse(rec), e) + c := NewContext(req, NewResponse(rec, e), e) // Router assert.NotNil(t, e.Router()) diff --git a/middleware/auth_test.go b/middleware/auth_test.go index 62482daa..d8b80c97 100644 --- a/middleware/auth_test.go +++ b/middleware/auth_test.go @@ -11,9 +11,10 @@ import ( ) func TestBasicAuth(t *testing.T) { + e := echo.New() req, _ := http.NewRequest(echo.GET, "/", nil) rec := httptest.NewRecorder() - c := echo.NewContext(req, echo.NewResponse(rec), echo.New()) + c := echo.NewContext(req, echo.NewResponse(rec, e), e) fn := func(u, p string) bool { if u == "joe" && p == "secret" { return true diff --git a/middleware/compress_test.go b/middleware/compress_test.go index fc727068..dc8b2a46 100644 --- a/middleware/compress_test.go +++ b/middleware/compress_test.go @@ -33,9 +33,10 @@ func (c *closeNotifyingRecorder) CloseNotify() <-chan bool { } func TestGzip(t *testing.T) { + e := echo.New() req, _ := http.NewRequest(echo.GET, "/", nil) rec := httptest.NewRecorder() - c := echo.NewContext(req, echo.NewResponse(rec), echo.New()) + c := echo.NewContext(req, echo.NewResponse(rec, e), e) h := func(c *echo.Context) error { c.Response().Write([]byte("test")) // For Content-Type sniffing return nil @@ -49,7 +50,7 @@ func TestGzip(t *testing.T) { req, _ = http.NewRequest(echo.GET, "/", nil) req.Header.Set(echo.AcceptEncoding, "gzip") rec = httptest.NewRecorder() - c = echo.NewContext(req, echo.NewResponse(rec), echo.New()) + c = echo.NewContext(req, echo.NewResponse(rec, e), e) // Gzip Gzip()(h)(c) @@ -121,7 +122,6 @@ func TestGzipCloseNotify(t *testing.T) { } func BenchmarkGzip(b *testing.B) { - b.StopTimer() b.ReportAllocs() @@ -135,8 +135,9 @@ func BenchmarkGzip(b *testing.B) { b.StartTimer() for i := 0; i < b.N; i++ { + e := echo.New() rec := httptest.NewRecorder() - c := echo.NewContext(req, echo.NewResponse(rec), echo.New()) + c := echo.NewContext(req, echo.NewResponse(rec, e), e) Gzip()(h)(c) } diff --git a/middleware/logger.go b/middleware/logger.go index a5538e26..9b88980c 100644 --- a/middleware/logger.go +++ b/middleware/logger.go @@ -6,7 +6,6 @@ import ( "github.com/labstack/echo" "github.com/labstack/gommon/color" - "github.com/labstack/gommon/log" ) func Logger() echo.MiddlewareFunc { @@ -14,6 +13,7 @@ func Logger() echo.MiddlewareFunc { return func(c *echo.Context) error { req := c.Request() res := c.Response() + logger := c.Echo().Logger() remoteAddr := req.RemoteAddr if ip := req.Header.Get(echo.XRealIP); ip != "" { @@ -47,7 +47,7 @@ func Logger() echo.MiddlewareFunc { code = color.Cyan(n) } - log.Info("%s %s %s %s %s %d", remoteAddr, method, path, code, stop.Sub(start), size) + logger.Info("%s %s %s %s %s %d", remoteAddr, method, path, code, stop.Sub(start), size) return nil } } diff --git a/middleware/logger_test.go b/middleware/logger_test.go index 2e576c33..298154b4 100644 --- a/middleware/logger_test.go +++ b/middleware/logger_test.go @@ -8,7 +8,6 @@ import ( "testing" "github.com/labstack/echo" - "github.com/labstack/gommon/log" "github.com/stretchr/testify/assert" ) @@ -17,7 +16,7 @@ func TestLogger(t *testing.T) { e := echo.New() req, _ := http.NewRequest(echo.GET, "/", nil) rec := httptest.NewRecorder() - c := echo.NewContext(req, echo.NewResponse(rec), e) + c := echo.NewContext(req, echo.NewResponse(rec, e), e) // Status 2xx h := func(c *echo.Context) error { @@ -27,7 +26,7 @@ func TestLogger(t *testing.T) { // Status 3xx rec = httptest.NewRecorder() - c = echo.NewContext(req, echo.NewResponse(rec), e) + c = echo.NewContext(req, echo.NewResponse(rec, e), e) h = func(c *echo.Context) error { return c.String(http.StatusTemporaryRedirect, "test") } @@ -35,7 +34,7 @@ func TestLogger(t *testing.T) { // Status 4xx rec = httptest.NewRecorder() - c = echo.NewContext(req, echo.NewResponse(rec), e) + c = echo.NewContext(req, echo.NewResponse(rec, e), e) h = func(c *echo.Context) error { return c.String(http.StatusNotFound, "test") } @@ -44,7 +43,7 @@ func TestLogger(t *testing.T) { // Status 5xx with empty path req, _ = http.NewRequest(echo.GET, "", nil) rec = httptest.NewRecorder() - c = echo.NewContext(req, echo.NewResponse(rec), e) + c = echo.NewContext(req, echo.NewResponse(rec, e), e) h = func(c *echo.Context) error { return errors.New("error") } @@ -52,14 +51,13 @@ func TestLogger(t *testing.T) { } func TestLoggerIPAddress(t *testing.T) { - buf := &bytes.Buffer{} - log.SetOutput(buf) - ip := "127.0.0.1" - e := echo.New() req, _ := http.NewRequest(echo.GET, "/", nil) rec := httptest.NewRecorder() - c := echo.NewContext(req, echo.NewResponse(rec), e) + c := echo.NewContext(req, echo.NewResponse(rec, e), e) + buf := new(bytes.Buffer) + e.Logger().SetOutput(buf) + ip := "127.0.0.1" h := func(c *echo.Context) error { return c.String(http.StatusOK, "test") } diff --git a/middleware/recover_test.go b/middleware/recover_test.go index 003c7519..3adedebb 100644 --- a/middleware/recover_test.go +++ b/middleware/recover_test.go @@ -14,7 +14,7 @@ func TestRecover(t *testing.T) { e.SetDebug(true) req, _ := http.NewRequest(echo.GET, "/", nil) rec := httptest.NewRecorder() - c := echo.NewContext(req, echo.NewResponse(rec), e) + c := echo.NewContext(req, echo.NewResponse(rec, e), e) h := func(c *echo.Context) error { panic("test") } diff --git a/recipes/websocket/server.go b/recipes/websocket/server.go index b98acb85..52d074fa 100644 --- a/recipes/websocket/server.go +++ b/recipes/websocket/server.go @@ -28,7 +28,6 @@ func main() { } fmt.Println(msg) } - return }) e.Run(":1323") diff --git a/response.go b/response.go index 2eacc72c..45afa0c4 100644 --- a/response.go +++ b/response.go @@ -4,8 +4,6 @@ import ( "bufio" "net" "net/http" - - "github.com/labstack/gommon/log" ) type ( @@ -14,11 +12,12 @@ type ( status int size int64 committed bool + echo *Echo } ) -func NewResponse(w http.ResponseWriter) *Response { - return &Response{writer: w} +func NewResponse(w http.ResponseWriter, e *Echo) *Response { + return &Response{writer: w, echo: e} } func (r *Response) SetWriter(w http.ResponseWriter) { @@ -35,7 +34,7 @@ func (r *Response) Writer() http.ResponseWriter { func (r *Response) WriteHeader(code int) { if r.committed { - log.Warn("response already committed") + r.echo.Logger().Warn("response already committed") return } r.status = code diff --git a/response_test.go b/response_test.go index a691686d..0960760d 100644 --- a/response_test.go +++ b/response_test.go @@ -9,8 +9,9 @@ import ( ) func TestResponse(t *testing.T) { + e := New() w := httptest.NewRecorder() - r := NewResponse(w) + r := NewResponse(w, e) // SetWriter r.SetWriter(w) diff --git a/website/content/guide/customization.md b/website/content/guide/customization.md index 26548f25..e27c9868 100644 --- a/website/content/guide/customization.md +++ b/website/content/guide/customization.md @@ -25,17 +25,23 @@ and message `HTTPError.Message`. Enables/disables debug mode. +## Log prefix + +`echo#SetLogPrefix(prefix string)` + +SetLogPrefix sets the prefix for the logger. Default value is `echo`. + ### Log output -`echo#SetOutput(w io.Writer)` +`echo#SetLogOutput(w io.Writer)` -SetOutput sets the output destination for the global logger. +SetLogOutput sets the output destination for the logger. Default value is `os.Std*` ### Log level `echo#SetLogLevel(l log.Level)` -SetLogLevel sets the log level for global logger. The default value is `log.INFO`. +SetLogLevel sets the log level for the logger. Default value is `log.INFO`. ### HTTP2 @@ -47,8 +53,7 @@ HTTP2 enables/disables HTTP2 support. `Echo#AutoIndex(on bool)` -AutoIndex enables/disables automatically creates a directory listing if the directory doesn't -contain an index page. +AutoIndex enables/disables automatically creating an index page for the directory. *Example* @@ -63,7 +68,7 @@ Browse to `http://localhost:1323/` to see the directory listing. ### Hook -`Echo#Hook(http.HandlerFunc)` +`Echo#Hook(h http.HandlerFunc)` Hook registers a callback which is invoked from `Echo#ServerHTTP` as the first statement. Hook is useful if you want to modify response/response objects even