1
0
mirror of https://github.com/labstack/echo.git synced 2024-12-24 20:14:31 +02:00

HTTPError#Message is now interface

Signed-off-by: Vishal Rana <vr@labstack.com>
This commit is contained in:
Vishal Rana 2016-12-10 22:05:41 -08:00
parent 0e7a9c1d49
commit 5706940bc8
4 changed files with 54 additions and 51 deletions

83
echo.go
View File

@ -42,7 +42,7 @@ import (
"errors"
"fmt"
"io"
"log"
slog "log"
"net/http"
"path"
"reflect"
@ -51,7 +51,7 @@ import (
"time"
"github.com/labstack/gommon/color"
glog "github.com/labstack/gommon/log"
"github.com/labstack/gommon/log"
"github.com/tylerb/graceful"
"golang.org/x/crypto/acme/autocert"
)
@ -59,23 +59,23 @@ import (
type (
// Echo is the top-level framework instance.
Echo struct {
DisableHTTP2 bool
Debug bool
HTTPErrorHandler
Binder Binder
Renderer Renderer
AutoTLSManager autocert.Manager
ShutdownTimeout time.Duration
Color *color.Color
Logger Logger
server *graceful.Server
tlsServer *graceful.Server
premiddleware []MiddlewareFunc
middleware []MiddlewareFunc
maxParam *int
router *Router
notFoundHandler HandlerFunc
pool sync.Pool
DisableHTTP2 bool
Debug bool
HTTPErrorHandler HTTPErrorHandler
Binder Binder
Renderer Renderer
AutoTLSManager autocert.Manager
ShutdownTimeout time.Duration
Color *color.Color
Logger Logger
server *graceful.Server
tlsServer *graceful.Server
premiddleware []MiddlewareFunc
middleware []MiddlewareFunc
maxParam *int
router *Router
notFoundHandler HandlerFunc
pool sync.Pool
}
// Route contains a handler and information for matching against requests.
@ -88,7 +88,7 @@ type (
// HTTPError represents an error that occurred while handling a request.
HTTPError struct {
Code int
Message string
Message interface{}
}
// MiddlewareFunc defines a function to process middleware.
@ -240,13 +240,13 @@ func New() (e *Echo) {
Prompt: autocert.AcceptTOS,
},
ShutdownTimeout: 15 * time.Second,
Logger: glog.New("echo"),
Logger: log.New("echo"),
maxParam: new(int),
Color: color.New(),
}
e.HTTPErrorHandler = e.DefaultHTTPErrorHandler
e.Binder = &DefaultBinder{}
e.Logger.SetLevel(glog.OFF)
e.Logger.SetLevel(log.OFF)
e.pool.New = func() interface{} {
return e.NewContext(nil, nil)
}
@ -271,24 +271,33 @@ func (e *Echo) Router() *Router {
return e.router
}
// DefaultHTTPErrorHandler invokes the default HTTP error handler.
// DefaultHTTPErrorHandler is the default HTTP error handler. It sends a JSON response
// with status code.
func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
code := http.StatusInternalServerError
msg := http.StatusText(code)
var (
code = http.StatusInternalServerError
msg interface{}
)
if he, ok := err.(*HTTPError); ok {
code = he.Code
msg = he.Message
} else {
msg = Map{"message": err}
}
if e.Debug {
msg = err.Error()
}
if !c.Response().Committed {
if c.Request().Method == HEAD { // Issue #608
c.NoContent(code)
if err := c.NoContent(code); err != nil {
goto ERROR
}
} else {
c.String(code, msg)
if err := c.JSON(code, msg); err != nil {
goto ERROR
}
}
}
ERROR:
e.Logger.Error(err)
}
@ -545,7 +554,7 @@ func (e *Echo) StartServer(s *http.Server) error {
gs := &graceful.Server{
Server: s,
Timeout: e.ShutdownTimeout,
Logger: log.New(e.Logger.Output(), e.Logger.Prefix()+": ", 0),
Logger: slog.New(e.Logger.Output(), e.Logger.Prefix()+": ", 0),
}
if s.TLSConfig == nil {
e.server = gs
@ -568,17 +577,17 @@ func (e *Echo) ShutdownTLS(timeout time.Duration) {
}
// NewHTTPError creates a new HTTPError instance.
func NewHTTPError(code int, msg ...interface{}) *HTTPError {
he := &HTTPError{Code: code, Message: http.StatusText(code)}
if len(msg) > 0 {
he.Message = fmt.Sprint(msg...)
func NewHTTPError(code int, message ...interface{}) *HTTPError {
he := &HTTPError{Code: code, Message: Map{"message": http.StatusText(code)}}
if len(message) > 0 {
he.Message = message[0]
}
return he
}
// Error makes it compatible with `error` interface.
func (e *HTTPError) Error() string {
return e.Message
func (he *HTTPError) Error() string {
return fmt.Sprintf("code=%d, message=%s", he.Code, he.Message)
}
// WrapHandler wraps `http.Handler` into `echo.HandlerFunc`.

View File

@ -380,13 +380,6 @@ func TestEchoMethodNotAllowed(t *testing.T) {
assert.Equal(t, http.StatusMethodNotAllowed, rec.Code)
}
func TestEchoHTTPError(t *testing.T) {
m := http.StatusText(http.StatusBadRequest)
he := NewHTTPError(http.StatusBadRequest, m)
assert.Equal(t, http.StatusBadRequest, he.Code)
assert.Equal(t, m, he.Error())
}
func TestEchoContext(t *testing.T) {
e := New()
c := e.AcquireContext()

View File

@ -62,11 +62,11 @@ func TestGzipErrorReturned(t *testing.T) {
e := echo.New()
e.Use(Gzip())
e.GET("/", func(c echo.Context) error {
return echo.NewHTTPError(http.StatusInternalServerError, "error")
return echo.ErrNotFound
})
req, _ := http.NewRequest(echo.GET, "/", nil)
rec := httptest.NewRecorder()
e.ServeHTTP(rec, req)
assert.Equal(t, http.StatusNotFound, rec.Code)
assert.Empty(t, rec.Header().Get(echo.HeaderContentEncoding))
assert.Equal(t, "error", rec.Body.String())
}

View File

@ -9,14 +9,15 @@ description = "Customizing Echo"
## HTTP Error Handler
Default HTTP error handler rules:
Default HTTP error handler sends an error as JSON with the following rules:
- If error is of type `Echo#HTTPError` it sends HTTP response with status code `HTTPError.Code`
- If error is `Echo#HTTPError` it sends HTTP response with status code `HTTPError.Code`
and message `HTTPError.Message`.
- Else it sends `500 - Internal Server Error`.
- If debug mode is enabled, it uses `error.Error()` as status message.
- If error is `error` it sends HTTP response with status code `500 - Internal Server Error`
and message `error.Error()`.
- It logs the error.
You can also set a custom HTTP error handler using `Echo#HTTPErrorHandler`.
You can set a custom HTTP error handler using `Echo#HTTPErrorHandler`.
## Debugging