Skip to content
29 changes: 21 additions & 8 deletions echo.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"io"
"log"
"net/http"
"path/filepath"
spath "path"
"reflect"
"runtime"
"strings"
Expand Down Expand Up @@ -135,8 +135,7 @@ const (
Upgrade = "Upgrade"
Vary = "Vary"
WWWAuthenticate = "WWW-Authenticate"
XForwardedFor = "X-Forwarded-For"
XRealIP = "X-Real-IP"

//-----------
// Protocols
//-----------
Expand Down Expand Up @@ -170,6 +169,15 @@ var (
//----------------
// Error handlers
//----------------
// methodNotAllowedHandler - handler to respond with a http.StatusMethodNotAllowed status
// which is applicable when the route is correct, but the method for the route isn't allowed
// for the route
methodNotAllowedHandler = func(c *Context, allowedMethods ...string) func(c *Context) error {
return func(c *Context) error {
c.response.Header().Add("Allow", strings.Join(allowedMethods, ", "))
return NewHTTPError(http.StatusMethodNotAllowed)
}
}

notFoundHandler = func(c *Context) error {
return NewHTTPError(http.StatusNotFound)
Expand All @@ -180,6 +188,8 @@ var (
}
)

var runtimeGOOS = runtime.GOOS

// New creates an instance of Echo.
func New() (e *Echo) {
e = &Echo{maxParam: new(int)}
Expand All @@ -192,7 +202,7 @@ func New() (e *Echo) {
// Defaults
//----------

if runtime.GOOS == "windows" {
if runtimeGOOS == "windows" {
e.DisableColoredLog()
}
e.HTTP2()
Expand Down Expand Up @@ -221,9 +231,12 @@ func (e *Echo) Router() *Router {
return e.router
}

var colorDisable = color.Disable

// DisableColoredLog disables colored log.
func (e *Echo) DisableColoredLog() {
color.Disable()
colorDisable()

}

// HTTP2 enables HTTP2 support.
Expand Down Expand Up @@ -376,14 +389,14 @@ func (e *Echo) Static(path, dir string) {
// ServeDir serves files from a directory.
func (e *Echo) ServeDir(path, dir string) {
e.Get(path+"*", func(c *Context) error {
return serveFile(dir, c.P(0), c) // Param `_*`
return serveFile(dir, c.P(0), c) // Param `_name`
})
}

// ServeFile serves a file.
func (e *Echo) ServeFile(path, file string) {
e.Get(path, func(c *Context) error {
dir, file := filepath.Split(file)
dir, file := spath.Split(file)
return serveFile(dir, file, c)
})
}
Expand All @@ -397,7 +410,7 @@ func serveFile(dir, file string, c *Context) error {

fi, _ := f.Stat()
if fi.IsDir() {
file = filepath.Join(file, indexFile)
file = spath.Join(file, indexFile)
f, err = fs.Open(file)
if err != nil {
return NewHTTPError(http.StatusForbidden)
Expand Down
18 changes: 17 additions & 1 deletion echo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import (
"fmt"
"net/http"
"net/http/httptest"
"runtime"
"testing"

"reflect"
"strings"

"errors"

"github.com/labstack/gommon/color"
"github.com/stretchr/testify/assert"
"golang.org/x/net/websocket"
)
Expand All @@ -23,6 +25,20 @@ type (
}
)

func TestNewRuntimeGOOS(t *testing.T) {
changedColor := make(chan bool)
colorDisable = func() { changedColor <- true }
runtimeGOOS = "windows"
defer func() {
colorDisable = color.Disable
runtimeGOOS = runtime.GOOS
}()
go func() {
New()
}()
assert.True(t, <-changedColor)
}

func TestEcho(t *testing.T) {
e := New()
req, _ := http.NewRequest(GET, "/", nil)
Expand Down Expand Up @@ -387,7 +403,7 @@ func TestEchoBadRequest(t *testing.T) {
r, _ := http.NewRequest("INVALID", "/files", nil)
w := httptest.NewRecorder()
e.ServeHTTP(w, r)
assert.Equal(t, http.StatusBadRequest, w.Code)
assert.Equal(t, http.StatusMethodNotAllowed, w.Code)
}

func TestEchoHTTPError(t *testing.T) {
Expand Down
22 changes: 5 additions & 17 deletions middleware/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package middleware

import (
"log"
"net"
"time"

"github.com/labstack/echo"
Expand All @@ -12,30 +11,19 @@ import (
func Logger() echo.MiddlewareFunc {
return func(h echo.HandlerFunc) echo.HandlerFunc {
return func(c *echo.Context) error {
req := c.Request()
res := c.Response()

remoteAddr := req.RemoteAddr
if ip := req.Header.Get(echo.XRealIP); ip != "" {
remoteAddr = ip
} else if ip = req.Header.Get(echo.XForwardedFor); ip != "" {
remoteAddr = ip
}
remoteAddr, _, _ = net.SplitHostPort(remoteAddr)

start := time.Now()
if err := h(c); err != nil {
c.Error(err)
}
stop := time.Now()
method := req.Method
path := req.URL.Path
method := c.Request().Method
path := c.Request().URL.Path
if path == "" {
path = "/"
}
size := res.Size()
size := c.Response().Size()

n := res.Status()
n := c.Response().Status()
code := color.Green(n)
switch {
case n >= 500:
Expand All @@ -46,7 +34,7 @@ func Logger() echo.MiddlewareFunc {
code = color.Cyan(n)
}

log.Printf("%s %s %s %s %s %d", remoteAddr, method, path, code, stop.Sub(start), size)
log.Printf("%s %s %s %s %d", method, path, code, stop.Sub(start), size)
return nil
}
}
Expand Down
21 changes: 2 additions & 19 deletions middleware/logger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,20 @@ package middleware

import (
"errors"
"github.com/labstack/echo"
"net/http"
"net/http/httptest"
"testing"

"github.com/labstack/echo"
)

func TestLogger(t *testing.T) {
// Note: Just for the test coverage, not a real test.
e := echo.New()
req, _ := http.NewRequest(echo.GET, "/", nil)
rec := httptest.NewRecorder()
c := echo.NewContext(req, echo.NewResponse(rec), e)

// With X-Real-IP
req.Header.Add(echo.XRealIP, "127.0.0.1")
h := func(c *echo.Context) error {
return c.String(http.StatusOK, "test")
}
Logger()(h)(c)

// With X-Forwarded-For
req.Header.Del(echo.XRealIP)
req.Header.Add(echo.XForwardedFor, "127.0.0.1")
h = func(c *echo.Context) error {
return c.String(http.StatusOK, "test")
}
Logger()(h)(c)

// Status 2xx
h = func(c *echo.Context) error {
h := func(c *echo.Context) error {
return c.String(http.StatusOK, "test")
}
Logger()(h)(c)
Expand Down
Loading