mirror of
https://github.com/labstack/echo.git
synced 2024-12-22 20:06:21 +02:00
commit
28b1b9d57b
14
.gitattributes
vendored
14
.gitattributes
vendored
@ -2,19 +2,21 @@
|
||||
# http://git-scm.com/docs/gitattributes#_end_of_line_conversion
|
||||
* text=auto
|
||||
|
||||
# For the following file types, normalize line endings to LF on checking and
|
||||
# For the following file types, normalize line endings to LF on checkin and
|
||||
# prevent conversion to CRLF when they are checked out (this is required in
|
||||
# order to prevent newline related issues)
|
||||
.* text eol=lf
|
||||
*.go text eol=lf
|
||||
*.yml text eol=lf
|
||||
*.html text eol=lf
|
||||
*.css text eol=lf
|
||||
*.go text eol=lf
|
||||
*.html text eol=lf
|
||||
*.js text eol=lf
|
||||
*.json text eol=lf
|
||||
*.md text eol=lf
|
||||
*.yml text eol=lf
|
||||
*.yaml text eol=lf
|
||||
LICENSE text eol=lf
|
||||
|
||||
# Exclude `website` and `recipes` from Github's language statistics
|
||||
# Exclude documentation-related directories from Github's language statistics
|
||||
# https://github.com/github/linguist#using-gitattributes
|
||||
recipes/* linguist-documentation
|
||||
_fixture/* linguist-documentation
|
||||
website/* linguist-documentation
|
||||
|
41
.gitignore
vendored
41
.gitignore
vendored
@ -1,13 +1,42 @@
|
||||
# Website
|
||||
# gitignore - Specifies intentionally untracked files to ignore
|
||||
# http://git-scm.com/docs/gitignore
|
||||
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
||||
|
||||
# submodule properties
|
||||
.gitmodules
|
||||
|
||||
# compiled web files
|
||||
website/public
|
||||
website/make
|
||||
website/Makefile
|
||||
website/marathon*
|
||||
.gitmodules
|
||||
|
||||
# Node.js
|
||||
# node.js web dependencies
|
||||
node_modules
|
||||
|
||||
# IntelliJ
|
||||
.idea
|
||||
*.iml
|
||||
# code coverage output files
|
||||
*.coverprofile
|
||||
|
44
.travis.yml
44
.travis.yml
@ -1,13 +1,39 @@
|
||||
language: go
|
||||
sudo: false
|
||||
|
||||
go:
|
||||
- 1.4
|
||||
- tip
|
||||
- 1.4
|
||||
- 1.5
|
||||
- 1.6rc1
|
||||
- tip
|
||||
env:
|
||||
global:
|
||||
- GO15VENDOREXPERIMENT=1
|
||||
|
||||
before_install:
|
||||
- go get github.com/modocache/gover
|
||||
- go get github.com/mattn/goveralls
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
- export PATH=$PATH:$GOPATH/bin
|
||||
- go get golang.org/x/tools/cmd/vet
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
- go get github.com/modocache/gover
|
||||
- go get github.com/mattn/goveralls
|
||||
|
||||
install:
|
||||
- go get -t -v ./...
|
||||
|
||||
script:
|
||||
- go test -coverprofile=echo.coverprofile
|
||||
- go test -coverprofile=middleware.coverprofile ./middleware
|
||||
- $HOME/gopath/bin/gover
|
||||
- $HOME/gopath/bin/goveralls -coverprofile=gover.coverprofile -service=travis-ci
|
||||
- go vet ./...
|
||||
- go test -v -race ./...
|
||||
- diff -u <(echo -n) <(gofmt -d -s .)
|
||||
- go test -v -coverprofile=echo.coverprofile
|
||||
- go test -v -coverprofile=middleware.coverprofile ./middleware
|
||||
- gover
|
||||
- goveralls -coverprofile=gover.coverprofile -service=travis-ci
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: change
|
||||
on_failure: always
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: tip
|
||||
|
3
LICENSE
3
LICENSE
@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 LabStack
|
||||
Copyright (c) 2016 LabStack
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -19,4 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
@ -120,7 +120,7 @@ func (c *Context) Bind(i interface{}) error {
|
||||
// code. Templates can be registered using `Echo.SetRenderer()`.
|
||||
func (c *Context) Render(code int, name string, data interface{}) (err error) {
|
||||
if c.echo.renderer == nil {
|
||||
return RendererNotRegistered
|
||||
return ErrRendererNotRegistered
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
if err = c.echo.renderer.Render(buf, name, data); err != nil {
|
||||
@ -244,7 +244,7 @@ func (c *Context) NoContent(code int) error {
|
||||
// Redirect redirects the request using http.Redirect with status code.
|
||||
func (c *Context) Redirect(code int, url string) error {
|
||||
if code < http.StatusMultipleChoices || code > http.StatusTemporaryRedirect {
|
||||
return InvalidRedirectCode
|
||||
return ErrInvalidRedirectCode
|
||||
}
|
||||
http.Redirect(c.response, c.request, url, code)
|
||||
return nil
|
||||
|
@ -234,6 +234,10 @@ func TestContext(t *testing.T) {
|
||||
|
||||
// reset
|
||||
c.reset(req, NewResponse(httptest.NewRecorder(), e), e)
|
||||
|
||||
// after reset (nil store) set test
|
||||
c.Set("user", "Joe")
|
||||
assert.Equal(t, "Joe", c.Get("user"))
|
||||
}
|
||||
|
||||
func TestContextPath(t *testing.T) {
|
||||
@ -285,6 +289,13 @@ func TestContextNetContext(t *testing.T) {
|
||||
assert.Equal(t, "val", c.Value("key"))
|
||||
}
|
||||
|
||||
func TestContextEcho(t *testing.T) {
|
||||
c := new(Context)
|
||||
|
||||
// Should be null when initialized without one
|
||||
assert.Nil(t, c.Echo())
|
||||
}
|
||||
|
||||
func testBindOk(t *testing.T, c *Context, ct string) {
|
||||
c.request.Header.Set(ContentType, ct)
|
||||
u := new(user)
|
||||
@ -307,7 +318,7 @@ func testBindError(t *testing.T, c *Context, ct string) {
|
||||
}
|
||||
default:
|
||||
if assert.IsType(t, new(HTTPError), err) {
|
||||
assert.Equal(t, UnsupportedMediaType, err)
|
||||
assert.Equal(t, ErrUnsupportedMediaType, err)
|
||||
}
|
||||
|
||||
}
|
||||
|
59
echo.go
59
echo.go
@ -1,8 +1,40 @@
|
||||
/*
|
||||
Package echo implements a fast and unfancy micro web framework for Go.
|
||||
|
||||
Example:
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
mw "github.com/labstack/echo/middleware"
|
||||
)
|
||||
|
||||
func hello(c *echo.Context) error {
|
||||
return c.String(http.StatusOK, "Hello, World!\n")
|
||||
}
|
||||
|
||||
func main() {
|
||||
e := echo.New()
|
||||
|
||||
e.Use(mw.Logger())
|
||||
e.Use(mw.Recover())
|
||||
|
||||
e.Get("/", hello)
|
||||
|
||||
e.Run(":1323")
|
||||
}
|
||||
|
||||
Learn more at https://labstack.com/echo
|
||||
*/
|
||||
package echo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -14,14 +46,13 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"encoding/xml"
|
||||
|
||||
"github.com/labstack/gommon/log"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/websocket"
|
||||
)
|
||||
|
||||
type (
|
||||
// Echo is the top-level framework instance.
|
||||
Echo struct {
|
||||
prefix string
|
||||
middleware []MiddlewareFunc
|
||||
@ -39,21 +70,30 @@ type (
|
||||
router *Router
|
||||
}
|
||||
|
||||
// Route contains a handler and information for matching against requests.
|
||||
Route struct {
|
||||
Method string
|
||||
Path string
|
||||
Handler Handler
|
||||
}
|
||||
|
||||
// HTTPError represents an error that occured while handling a request.
|
||||
HTTPError struct {
|
||||
code int
|
||||
message string
|
||||
}
|
||||
|
||||
Middleware interface{}
|
||||
// Middleware ...
|
||||
Middleware interface{}
|
||||
|
||||
// MiddlewareFunc ...
|
||||
MiddlewareFunc func(HandlerFunc) HandlerFunc
|
||||
Handler interface{}
|
||||
HandlerFunc func(*Context) error
|
||||
|
||||
// Handler ...
|
||||
Handler interface{}
|
||||
|
||||
// HandlerFunc ...
|
||||
HandlerFunc func(*Context) error
|
||||
|
||||
// HTTPErrorHandler is a centralized HTTP error handler.
|
||||
HTTPErrorHandler func(error, *Context)
|
||||
@ -164,9 +204,9 @@ var (
|
||||
// Errors
|
||||
//--------
|
||||
|
||||
UnsupportedMediaType = NewHTTPError(http.StatusUnsupportedMediaType)
|
||||
RendererNotRegistered = errors.New("renderer not registered")
|
||||
InvalidRedirectCode = errors.New("invalid redirect status code")
|
||||
ErrUnsupportedMediaType = NewHTTPError(http.StatusUnsupportedMediaType)
|
||||
ErrRendererNotRegistered = errors.New("renderer not registered")
|
||||
ErrInvalidRedirectCode = errors.New("invalid redirect status code")
|
||||
|
||||
//----------------
|
||||
// Error handlers
|
||||
@ -588,6 +628,7 @@ func (e *Echo) run(s *http.Server, files ...string) {
|
||||
}
|
||||
}
|
||||
|
||||
// NewHTTPError creates a new HTTPError instance.
|
||||
func NewHTTPError(code int, msg ...string) *HTTPError {
|
||||
he := &HTTPError{code: code, message: http.StatusText(code)}
|
||||
if len(msg) > 0 {
|
||||
@ -691,7 +732,7 @@ func wrapHandler(h Handler) HandlerFunc {
|
||||
|
||||
func (binder) Bind(r *http.Request, i interface{}) (err error) {
|
||||
ct := r.Header.Get(ContentType)
|
||||
err = UnsupportedMediaType
|
||||
err = ErrUnsupportedMediaType
|
||||
if strings.HasPrefix(ct, ApplicationJSON) {
|
||||
if err = json.NewDecoder(r.Body).Decode(i); err != nil {
|
||||
err = NewHTTPError(http.StatusBadRequest, err.Error())
|
||||
|
31
group.go
31
group.go
@ -1,81 +1,102 @@
|
||||
package echo
|
||||
|
||||
type (
|
||||
Group struct {
|
||||
echo Echo
|
||||
}
|
||||
)
|
||||
// Group is a set of subroutes for a specified route. It can be used for inner
|
||||
// routes that share a common middlware or functionality that should be separate
|
||||
// from the parent echo instance while still inheriting from it.
|
||||
type Group struct {
|
||||
echo Echo
|
||||
}
|
||||
|
||||
// Use implements the echo.Use interface for subroutes within the Group.
|
||||
func (g *Group) Use(m ...Middleware) {
|
||||
for _, h := range m {
|
||||
g.echo.middleware = append(g.echo.middleware, wrapMiddleware(h))
|
||||
}
|
||||
}
|
||||
|
||||
// Connect implements the echo.Connect interface for subroutes within the Group.
|
||||
func (g *Group) Connect(path string, h Handler) {
|
||||
g.echo.Connect(path, h)
|
||||
}
|
||||
|
||||
// Delete implements the echo.Delete interface for subroutes within the Group.
|
||||
func (g *Group) Delete(path string, h Handler) {
|
||||
g.echo.Delete(path, h)
|
||||
}
|
||||
|
||||
// Get implements the echo.Get interface for subroutes within the Group.
|
||||
func (g *Group) Get(path string, h Handler) {
|
||||
g.echo.Get(path, h)
|
||||
}
|
||||
|
||||
// Head implements the echo.Head interface for subroutes within the Group.
|
||||
func (g *Group) Head(path string, h Handler) {
|
||||
g.echo.Head(path, h)
|
||||
}
|
||||
|
||||
// Options implements the echo.Options interface for subroutes within the Group.
|
||||
func (g *Group) Options(path string, h Handler) {
|
||||
g.echo.Options(path, h)
|
||||
}
|
||||
|
||||
// Patch implements the echo.Patch interface for subroutes within the Group.
|
||||
func (g *Group) Patch(path string, h Handler) {
|
||||
g.echo.Patch(path, h)
|
||||
}
|
||||
|
||||
// Post implements the echo.Post interface for subroutes within the Group.
|
||||
func (g *Group) Post(path string, h Handler) {
|
||||
g.echo.Post(path, h)
|
||||
}
|
||||
|
||||
// Put implements the echo.Put interface for subroutes within the Group.
|
||||
func (g *Group) Put(path string, h Handler) {
|
||||
g.echo.Put(path, h)
|
||||
}
|
||||
|
||||
// Trace implements the echo.Trace interface for subroutes within the Group.
|
||||
func (g *Group) Trace(path string, h Handler) {
|
||||
g.echo.Trace(path, h)
|
||||
}
|
||||
|
||||
// Any implements the echo.Any interface for subroutes within the Group.
|
||||
func (g *Group) Any(path string, h Handler) {
|
||||
for _, m := range methods {
|
||||
g.echo.add(m, path, h)
|
||||
}
|
||||
}
|
||||
|
||||
// Match implements the echo.Match interface for subroutes within the Group.
|
||||
func (g *Group) Match(methods []string, path string, h Handler) {
|
||||
for _, m := range methods {
|
||||
g.echo.add(m, path, h)
|
||||
}
|
||||
}
|
||||
|
||||
// WebSocket implements the echo.WebSocket interface for subroutes within the
|
||||
// Group.
|
||||
func (g *Group) WebSocket(path string, h HandlerFunc) {
|
||||
g.echo.WebSocket(path, h)
|
||||
}
|
||||
|
||||
// Static implements the echo.Static interface for subroutes within the Group.
|
||||
func (g *Group) Static(path, root string) {
|
||||
g.echo.Static(path, root)
|
||||
}
|
||||
|
||||
// ServeDir implements the echo.ServeDir interface for subroutes within the
|
||||
// Group.
|
||||
func (g *Group) ServeDir(path, root string) {
|
||||
g.echo.ServeDir(path, root)
|
||||
}
|
||||
|
||||
// ServeFile implements the echo.ServeFile interface for subroutes within the
|
||||
// Group.
|
||||
func (g *Group) ServeFile(path, file string) {
|
||||
g.echo.ServeFile(path, file)
|
||||
}
|
||||
|
||||
// Group implements the echo.Group interface for subroutes within the Group.
|
||||
func (g *Group) Group(prefix string, m ...Middleware) *Group {
|
||||
return g.echo.Group(prefix, m...)
|
||||
}
|
||||
|
@ -8,17 +8,19 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
// BasicValidateFunc is the expected format a BasicAuth fn argument is
|
||||
// expected to implement.
|
||||
BasicValidateFunc func(string, string) bool
|
||||
)
|
||||
|
||||
const (
|
||||
// Basic is the authentication scheme implemented by the middleware.
|
||||
Basic = "Basic"
|
||||
)
|
||||
|
||||
// BasicAuth returns an HTTP basic authentication middleware.
|
||||
//
|
||||
// For valid credentials it calls the next handler.
|
||||
// For invalid credentials, it sends "401 - Unauthorized" response.
|
||||
// BasicAuth returns a HTTP basic authentication middleware.
|
||||
// For valid credentials, it calls the next handler.
|
||||
// For invalid credentials, it returns a "401 Unauthorized" HTTP error.
|
||||
func BasicAuth(fn BasicValidateFunc) echo.HandlerFunc {
|
||||
return func(c *echo.Context) error {
|
||||
// Skip WebSocket
|
||||
|
@ -8,6 +8,9 @@ import (
|
||||
"github.com/labstack/gommon/color"
|
||||
)
|
||||
|
||||
const loggerFormat = "%s %s %s %s %s %d"
|
||||
|
||||
// Logger returns a Middleware that logs requests.
|
||||
func Logger() echo.MiddlewareFunc {
|
||||
return func(h echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c *echo.Context) error {
|
||||
@ -47,7 +50,7 @@ func Logger() echo.MiddlewareFunc {
|
||||
code = color.Cyan(n)
|
||||
}
|
||||
|
||||
logger.Info("%s %s %s %s %s %d", remoteAddr, method, path, code, stop.Sub(start), size)
|
||||
logger.Info(loggerFormat, remoteAddr, method, path, code, stop.Sub(start), size)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
60
response.go
60
response.go
@ -6,32 +6,46 @@ import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type (
|
||||
Response struct {
|
||||
writer http.ResponseWriter
|
||||
status int
|
||||
size int64
|
||||
committed bool
|
||||
echo *Echo
|
||||
}
|
||||
)
|
||||
// Response wraps an http.ResponseWriter and implements its interface to be used
|
||||
// by an HTTP handler to construct an HTTP response.
|
||||
// See [http.ResponseWriter](https://golang.org/pkg/net/http/#ResponseWriter)
|
||||
type Response struct {
|
||||
writer http.ResponseWriter
|
||||
status int
|
||||
size int64
|
||||
committed bool
|
||||
echo *Echo
|
||||
}
|
||||
|
||||
// NewResponse creates a new instance of Response.
|
||||
func NewResponse(w http.ResponseWriter, e *Echo) *Response {
|
||||
return &Response{writer: w, echo: e}
|
||||
}
|
||||
|
||||
// SetWriter sets the http.ResponseWriter instance for this Response.
|
||||
func (r *Response) SetWriter(w http.ResponseWriter) {
|
||||
r.writer = w
|
||||
}
|
||||
|
||||
func (r *Response) Header() http.Header {
|
||||
return r.writer.Header()
|
||||
}
|
||||
|
||||
// Writer returns the http.ResponseWriter instance for this Response.
|
||||
func (r *Response) Writer() http.ResponseWriter {
|
||||
return r.writer
|
||||
}
|
||||
|
||||
// Header returns the header map for the writer that will be sent by
|
||||
// WriteHeader. Changing the header after a call to WriteHeader (or Write) has
|
||||
// no effect unless the modified headers were declared as trailers by setting
|
||||
// the "Trailer" header before the call to WriteHeader (see example)
|
||||
// To suppress implicit response headers, set their value to nil.
|
||||
// Example [ResponseWriter.Trailers](https://golang.org/pkg/net/http/#example_ResponseWriter_trailers)
|
||||
func (r *Response) Header() http.Header {
|
||||
return r.writer.Header()
|
||||
}
|
||||
|
||||
// WriteHeader sends an HTTP response header with status code. If WriteHeader is
|
||||
// not called explicitly, the first call to Write will trigger an implicit
|
||||
// WriteHeader(http.StatusOK). Thus explicit calls to WriteHeader are mainly
|
||||
// used to send error codes.
|
||||
func (r *Response) WriteHeader(code int) {
|
||||
if r.committed {
|
||||
r.echo.Logger().Warn("response already committed")
|
||||
@ -42,35 +56,49 @@ func (r *Response) WriteHeader(code int) {
|
||||
r.committed = true
|
||||
}
|
||||
|
||||
// Write wraps and implements the http.Response.Write specification.
|
||||
// Additionally, Write will increment the size of the current response.
|
||||
// See [http.Response.Write](https://golang.org/pkg/net/http/#Response.Write)
|
||||
func (r *Response) Write(b []byte) (n int, err error) {
|
||||
n, err = r.writer.Write(b)
|
||||
r.size += int64(n)
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Flush wraps response writer's Flush function.
|
||||
// Flush implements the http.Flusher interface to allow an HTTP handler to flush
|
||||
// buffered data to the client.
|
||||
// See [http.Flusher](https://golang.org/pkg/net/http/#Flusher)
|
||||
func (r *Response) Flush() {
|
||||
r.writer.(http.Flusher).Flush()
|
||||
}
|
||||
|
||||
// Hijack wraps response writer's Hijack function.
|
||||
// Hijack implements the http.Hijacker interface to allow an HTTP handler to
|
||||
// take over the connection.
|
||||
// See [http.Hijacker](https://golang.org/pkg/net/http/#Hijacker)
|
||||
func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||
return r.writer.(http.Hijacker).Hijack()
|
||||
}
|
||||
|
||||
// CloseNotify wraps response writer's CloseNotify function.
|
||||
// CloseNotify implements the http.CloseNotifier interface to allow detecting
|
||||
// when the underlying connection has gone away.
|
||||
// This mechanism can be used to cancel long operations on the server if the
|
||||
// client has disconnected before the response is ready.
|
||||
// See [http.CloseNotifier](https://golang.org/pkg/net/http/#CloseNotifier)
|
||||
func (r *Response) CloseNotify() <-chan bool {
|
||||
return r.writer.(http.CloseNotifier).CloseNotify()
|
||||
}
|
||||
|
||||
// Status returns the HTTP status code of the response.
|
||||
func (r *Response) Status() int {
|
||||
return r.status
|
||||
}
|
||||
|
||||
// Size returns the current size, in bytes, of the response.
|
||||
func (r *Response) Size() int64 {
|
||||
return r.size
|
||||
}
|
||||
|
||||
// Committed asserts whether or not the response has been committed to.
|
||||
func (r *Response) Committed() bool {
|
||||
return r.committed
|
||||
}
|
||||
|
13
router.go
13
router.go
@ -3,6 +3,12 @@ package echo
|
||||
import "net/http"
|
||||
|
||||
type (
|
||||
|
||||
// Router is the registry of all registered routes for an Echo instance for
|
||||
// request matching and handler dispatching.
|
||||
//
|
||||
// Router implements the http.Handler specification and can be registered
|
||||
// to serve requests.
|
||||
Router struct {
|
||||
tree *node
|
||||
routes []Route
|
||||
@ -40,6 +46,7 @@ const (
|
||||
mkind
|
||||
)
|
||||
|
||||
// NewRouter returns a new Router instance.
|
||||
func NewRouter(e *Echo) *Router {
|
||||
return &Router{
|
||||
tree: &node{
|
||||
@ -50,6 +57,7 @@ func NewRouter(e *Echo) *Router {
|
||||
}
|
||||
}
|
||||
|
||||
// Add registers a new route with a matcher for the URL path.
|
||||
func (r *Router) Add(method, path string, h HandlerFunc, e *Echo) {
|
||||
ppath := path // Pristine path
|
||||
pnames := []string{} // Param names
|
||||
@ -275,6 +283,8 @@ func (n *node) check405() HandlerFunc {
|
||||
return notFoundHandler
|
||||
}
|
||||
|
||||
// Find dispatches the request to the handler whos route is matched with the
|
||||
// specified request path.
|
||||
func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo) {
|
||||
h = notFoundHandler
|
||||
e = r.echo
|
||||
@ -400,6 +410,9 @@ End:
|
||||
return
|
||||
}
|
||||
|
||||
// ServeHTTP implements the Handler interface and can be registered to serve a
|
||||
// particular path or subtree in an HTTP server.
|
||||
// See Router.Find()
|
||||
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
c := r.echo.pool.Get().(*Context)
|
||||
h, _ := r.Find(req.Method, req.URL.Path, c)
|
||||
|
Loading…
Reference in New Issue
Block a user