Skip to content

Commit

Permalink
Merge branch 'labstack:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
pwli0755 authored Aug 13, 2021
2 parents 7fe24d2 + 7d41537 commit e03b35e
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 10 deletions.
21 changes: 12 additions & 9 deletions echo.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,11 @@ func (e *Echo) Routers() map[string]*Router {
// DefaultHTTPErrorHandler is the default HTTP error handler. It sends a JSON response
// with status code.
func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {

if c.Response().Committed {
return
}

he, ok := err.(*HTTPError)
if ok {
if he.Internal != nil {
Expand All @@ -384,15 +389,13 @@ func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
}

// Send response
if !c.Response().Committed {
if c.Request().Method == http.MethodHead { // Issue #608
err = c.NoContent(he.Code)
} else {
err = c.JSON(code, message)
}
if err != nil {
e.Logger.Error(err)
}
if c.Request().Method == http.MethodHead { // Issue #608
err = c.NoContent(he.Code)
} else {
err = c.JSON(code, message)
}
if err != nil {
e.Logger.Error(err)
}
}

Expand Down
17 changes: 17 additions & 0 deletions echo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,15 @@ func TestDefaultHTTPErrorHandler(t *testing.T) {
"error": "stackinfo",
})
})
e.Any("/early-return", func(c Context) error {
c.String(http.StatusOK, "OK")
return errors.New("ERROR")
})
e.GET("/internal-error", func(c Context) error {
err := errors.New("internal error message body")
return NewHTTPError(http.StatusBadRequest).SetInternal(err)
})

// With Debug=true plain response contains error message
c, b := request(http.MethodGet, "/plain", e)
assert.Equal(t, http.StatusInternalServerError, c)
Expand All @@ -1136,6 +1145,14 @@ func TestDefaultHTTPErrorHandler(t *testing.T) {
c, b = request(http.MethodGet, "/servererror", e)
assert.Equal(t, http.StatusInternalServerError, c)
assert.Equal(t, "{\n \"code\": 33,\n \"error\": \"stackinfo\",\n \"message\": \"Something bad happened\"\n}\n", b)
// if the body is already set HTTPErrorHandler should not add anything to response body
c, b = request(http.MethodGet, "/early-return", e)
assert.Equal(t, http.StatusOK, c)
assert.Equal(t, "OK", b)
// internal error should be reflected in the message
c, b = request(http.MethodGet, "/internal-error", e)
assert.Equal(t, http.StatusBadRequest, c)
assert.Equal(t, "{\n \"error\": \"code=400, message=Bad Request, internal=internal error message body\",\n \"message\": \"Bad Request\"\n}\n", b)

e.Debug = false
// With Debug=false the error response is shortened
Expand Down
2 changes: 1 addition & 1 deletion middleware/jwt.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ func jwtFromHeader(header string, authScheme string) jwtExtractor {
return func(c echo.Context) (string, error) {
auth := c.Request().Header.Get(header)
l := len(authScheme)
if len(auth) > l+1 && auth[:l] == authScheme {
if len(auth) > l+1 && strings.EqualFold(auth[:l], authScheme) {
return auth[l+1:], nil
}
return "", ErrJWTMissing
Expand Down
5 changes: 5 additions & 0 deletions middleware/jwt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,11 @@ func TestJWT(t *testing.T) {
expErrCode: http.StatusUnauthorized,
info: "Token verification does not pass using a user-defined KeyFunc",
},
{
hdrAuth: strings.ToLower(DefaultJWTConfig.AuthScheme) + " " + token,
config: JWTConfig{SigningKey: validKey},
info: "Valid JWT with lower case AuthScheme",
},
} {
if tc.reqURL == "" {
tc.reqURL = "/"
Expand Down
15 changes: 15 additions & 0 deletions middleware/key_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package middleware

import (
"errors"
"fmt"
"net/http"
"strings"

Expand All @@ -21,6 +22,7 @@ type (
// - "header:<name>"
// - "query:<name>"
// - "form:<name>"
// - "cookie:<name>"
KeyLookup string `yaml:"key_lookup"`

// AuthScheme to be used in the Authorization header.
Expand Down Expand Up @@ -91,6 +93,8 @@ func KeyAuthWithConfig(config KeyAuthConfig) echo.MiddlewareFunc {
extractor = keyFromQuery(parts[1])
case "form":
extractor = keyFromForm(parts[1])
case "cookie":
extractor = keyFromCookie(parts[1])
}

return func(next echo.HandlerFunc) echo.HandlerFunc {
Expand Down Expand Up @@ -164,3 +168,14 @@ func keyFromForm(param string) keyExtractor {
return key, nil
}
}

// keyFromCookie returns a `keyExtractor` that extracts key from the form.
func keyFromCookie(cookieName string) keyExtractor {
return func(c echo.Context) (string, error) {
key, err := c.Cookie(cookieName)
if err != nil {
return "", fmt.Errorf("missing key in cookies: %w", err)
}
return key.Value, nil
}
}
24 changes: 24 additions & 0 deletions middleware/key_auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,30 @@ func TestKeyAuthWithConfig(t *testing.T) {
expectHandlerCalled: false,
expectError: "code=400, message=missing key in the form",
},
{
name: "ok, custom key lookup, cookie",
givenRequest: func(req *http.Request) {
req.AddCookie(&http.Cookie{
Name: "key",
Value: "valid-key",
})
q := req.URL.Query()
q.Add("key", "valid-key")
req.URL.RawQuery = q.Encode()
},
whenConfig: func(conf *KeyAuthConfig) {
conf.KeyLookup = "cookie:key"
},
expectHandlerCalled: true,
},
{
name: "nok, custom key lookup, missing cookie param",
whenConfig: func(conf *KeyAuthConfig) {
conf.KeyLookup = "cookie:key"
},
expectHandlerCalled: false,
expectError: "code=400, message=missing key in cookies: http: named cookie not present",
},
{
name: "nok, custom errorHandler, error from extractor",
whenConfig: func(conf *KeyAuthConfig) {
Expand Down

0 comments on commit e03b35e

Please sign in to comment.