mirror of
https://github.com/labstack/echo.git
synced 2024-11-28 08:38:39 +02:00
more godoc
Signed-off-by: Vishal Rana <vr@labstack.com>
This commit is contained in:
parent
d01e856db6
commit
c4caeb8ffb
107
context.go
107
context.go
@ -22,40 +22,108 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
// Context represents context for the current request. It holds request and
|
||||
// response objects, path parameters, data and registered handler.
|
||||
// Context represents the context of the current HTTP request. It holds request and
|
||||
// response objects, path, path parameters, data and registered handler.
|
||||
Context interface {
|
||||
netContext.Context
|
||||
|
||||
// NetContext returns `http://blog.golang.org/context.Context` interface.
|
||||
NetContext() netContext.Context
|
||||
|
||||
// SetNetContext sets `http://blog.golang.org/context.Context` interface.
|
||||
SetNetContext(netContext.Context)
|
||||
|
||||
// Request returns `engine.Request` interface.
|
||||
Request() engine.Request
|
||||
|
||||
// Request returns `engine.Response` interface.
|
||||
Response() engine.Response
|
||||
|
||||
// Path returns the registered path for the handler.
|
||||
Path() string
|
||||
|
||||
// P returns path parameter by index.
|
||||
P(int) string
|
||||
|
||||
// Param returns path parameter by name.
|
||||
Param(string) string
|
||||
|
||||
// ParamNames returns path parameter names.
|
||||
ParamNames() []string
|
||||
|
||||
// Query returns query parameter by name.
|
||||
Query(string) string
|
||||
|
||||
// Form returns form parameter by name.
|
||||
Form(string) string
|
||||
|
||||
// Get retrieves data from the context.
|
||||
Get(string) interface{}
|
||||
|
||||
// Set saves data in the context.
|
||||
Set(string, interface{})
|
||||
|
||||
// Bind binds the request body into provided type `i`. The default binder does
|
||||
// it based on Content-Type header.
|
||||
Bind(interface{}) error
|
||||
|
||||
// Render renders a template with data and sends a text/html response with status
|
||||
// code. Templates can be registered using `Echo.SetRenderer()`.
|
||||
Render(int, string, interface{}) error
|
||||
|
||||
// HTML sends an HTTP response with status code.
|
||||
HTML(int, string) error
|
||||
|
||||
// String sends a string response with status code.
|
||||
String(int, string) error
|
||||
|
||||
// JSON sends a JSON response with status code.
|
||||
JSON(int, interface{}) error
|
||||
|
||||
// JSONBlob sends a JSON blob response with status code.
|
||||
JSONBlob(int, []byte) error
|
||||
|
||||
// JSONP sends a JSONP response with status code. It uses `callback` to construct
|
||||
// the JSONP payload.
|
||||
JSONP(int, string, interface{}) error
|
||||
|
||||
// XML sends an XML response with status code.
|
||||
XML(int, interface{}) error
|
||||
|
||||
// XMLBlob sends a XML blob response with status code.
|
||||
XMLBlob(int, []byte) error
|
||||
|
||||
// File sends a response with the content of the file.
|
||||
File(string) error
|
||||
|
||||
// Attachment sends a response from `io.Reader` as attachment, prompting client
|
||||
// to save the file.
|
||||
Attachment(io.Reader, string) error
|
||||
|
||||
// NoContent sends a response with no body and a status code.
|
||||
NoContent(int) error
|
||||
|
||||
// Redirect redirects the request with status code.
|
||||
Redirect(int, string) error
|
||||
|
||||
// Error invokes the registered HTTP error handler. Generally used by middleware.
|
||||
Error(err error)
|
||||
|
||||
// Handler implements `Handler` interface.
|
||||
Handle(Context) error
|
||||
|
||||
// Logger returns the `Logger` instance.
|
||||
Logger() *log.Logger
|
||||
|
||||
// Echo returns the `Echo` instance.
|
||||
Echo() *Echo
|
||||
|
||||
// Object returns the `context` instance.
|
||||
Object() *context
|
||||
|
||||
// Reset resets the context after request completes. It must be called along
|
||||
// with `Echo#GetContext()` and `Echo#PutContext()`. See `Echo#ServeHTTP()`
|
||||
Reset(engine.Request, engine.Response)
|
||||
}
|
||||
|
||||
context struct {
|
||||
@ -118,22 +186,18 @@ func (c *context) Handle(ctx Context) error {
|
||||
return c.handler.Handle(ctx)
|
||||
}
|
||||
|
||||
// Request returns *http.Request.
|
||||
func (c *context) Request() engine.Request {
|
||||
return c.request
|
||||
}
|
||||
|
||||
// Response returns `engine.Response`.
|
||||
func (c *context) Response() engine.Response {
|
||||
return c.response
|
||||
}
|
||||
|
||||
// Path returns the registered path for the handler.
|
||||
func (c *context) Path() string {
|
||||
return c.path
|
||||
}
|
||||
|
||||
// P returns path parameter by index.
|
||||
func (c *context) P(i int) (value string) {
|
||||
l := len(c.pnames)
|
||||
if i < l {
|
||||
@ -142,7 +206,6 @@ func (c *context) P(i int) (value string) {
|
||||
return
|
||||
}
|
||||
|
||||
// Param returns path parameter by name.
|
||||
func (c *context) Param(name string) (value string) {
|
||||
l := len(c.pnames)
|
||||
for i, n := range c.pnames {
|
||||
@ -154,22 +217,18 @@ func (c *context) Param(name string) (value string) {
|
||||
return
|
||||
}
|
||||
|
||||
// ParamNames returns path parameter names.
|
||||
func (c *context) ParamNames() []string {
|
||||
return c.pnames
|
||||
}
|
||||
|
||||
// Query returns query parameter by name.
|
||||
func (c *context) Query(name string) string {
|
||||
return c.request.URL().QueryValue(name)
|
||||
}
|
||||
|
||||
// Form returns form parameter by name.
|
||||
func (c *context) Form(name string) string {
|
||||
return c.request.FormValue(name)
|
||||
}
|
||||
|
||||
// Set saves data in the context.
|
||||
func (c *context) Set(key string, val interface{}) {
|
||||
if c.store == nil {
|
||||
c.store = make(store)
|
||||
@ -177,19 +236,14 @@ func (c *context) Set(key string, val interface{}) {
|
||||
c.store[key] = val
|
||||
}
|
||||
|
||||
// Get retrieves data from the context.
|
||||
func (c *context) Get(key string) interface{} {
|
||||
return c.store[key]
|
||||
}
|
||||
|
||||
// Bind binds the request body into provided type `i`. The default binder does
|
||||
// it based on Content-Type header.
|
||||
func (c *context) Bind(i interface{}) error {
|
||||
return c.echo.binder.Bind(i, c)
|
||||
}
|
||||
|
||||
// Render renders a template with data and sends a text/html response with status
|
||||
// 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 ErrRendererNotRegistered
|
||||
@ -204,7 +258,6 @@ func (c *context) Render(code int, name string, data interface{}) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// HTML sends an HTTP response with status code.
|
||||
func (c *context) HTML(code int, html string) (err error) {
|
||||
c.response.Header().Set(ContentType, TextHTMLCharsetUTF8)
|
||||
c.response.WriteHeader(code)
|
||||
@ -212,7 +265,6 @@ func (c *context) HTML(code int, html string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// String sends a string response with status code.
|
||||
func (c *context) String(code int, s string) (err error) {
|
||||
c.response.Header().Set(ContentType, TextPlainCharsetUTF8)
|
||||
c.response.WriteHeader(code)
|
||||
@ -220,7 +272,6 @@ func (c *context) String(code int, s string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// JSON sends a JSON response with status code.
|
||||
func (c *context) JSON(code int, i interface{}) (err error) {
|
||||
b, err := json.Marshal(i)
|
||||
if c.echo.Debug() {
|
||||
@ -232,7 +283,6 @@ func (c *context) JSON(code int, i interface{}) (err error) {
|
||||
return c.JSONBlob(code, b)
|
||||
}
|
||||
|
||||
// JSONBlob sends a JSON blob response with status code.
|
||||
func (c *context) JSONBlob(code int, b []byte) (err error) {
|
||||
c.response.Header().Set(ContentType, ApplicationJSONCharsetUTF8)
|
||||
c.response.WriteHeader(code)
|
||||
@ -240,8 +290,6 @@ func (c *context) JSONBlob(code int, b []byte) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// JSONP sends a JSONP response with status code. It uses `callback` to construct
|
||||
// the JSONP payload.
|
||||
func (c *context) JSONP(code int, callback string, i interface{}) (err error) {
|
||||
b, err := json.Marshal(i)
|
||||
if err != nil {
|
||||
@ -259,7 +307,6 @@ func (c *context) JSONP(code int, callback string, i interface{}) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// XML sends an XML response with status code.
|
||||
func (c *context) XML(code int, i interface{}) (err error) {
|
||||
b, err := xml.Marshal(i)
|
||||
if c.echo.Debug() {
|
||||
@ -271,7 +318,6 @@ func (c *context) XML(code int, i interface{}) (err error) {
|
||||
return c.XMLBlob(code, b)
|
||||
}
|
||||
|
||||
// XMLBlob sends a XML blob response with status code.
|
||||
func (c *context) XMLBlob(code int, b []byte) (err error) {
|
||||
c.response.Header().Set(ContentType, ApplicationXMLCharsetUTF8)
|
||||
c.response.WriteHeader(code)
|
||||
@ -282,7 +328,6 @@ func (c *context) XMLBlob(code int, b []byte) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// File sends a response with the content of the file.
|
||||
func (c *context) File(file string) error {
|
||||
root, file := filepath.Split(file)
|
||||
fs := http.Dir(root)
|
||||
@ -305,8 +350,6 @@ func (c *context) File(file string) error {
|
||||
return ServeContent(c.Request(), c.Response(), f, fi)
|
||||
}
|
||||
|
||||
// Attachment sends a response from `io.Reader` as attachment, prompting client
|
||||
// to save the file.
|
||||
func (c *context) Attachment(r io.Reader, name string) (err error) {
|
||||
c.response.Header().Set(ContentType, detectContentType(name))
|
||||
c.response.Header().Set(ContentDisposition, "attachment; filename="+name)
|
||||
@ -315,13 +358,11 @@ func (c *context) Attachment(r io.Reader, name string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// NoContent sends a response with no body and a status code.
|
||||
func (c *context) NoContent(code int) error {
|
||||
c.response.WriteHeader(code)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Redirect redirects the request with status code.
|
||||
func (c *context) Redirect(code int, url string) error {
|
||||
if code < http.StatusMultipleChoices || code > http.StatusTemporaryRedirect {
|
||||
return ErrInvalidRedirectCode
|
||||
@ -331,26 +372,24 @@ func (c *context) Redirect(code int, url string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Error invokes the registered HTTP error handler. Generally used by middleware.
|
||||
func (c *context) Error(err error) {
|
||||
c.echo.httpErrorHandler(err, c)
|
||||
}
|
||||
|
||||
// Echo returns the `Echo` instance.
|
||||
func (c *context) Echo() *Echo {
|
||||
return c.echo
|
||||
}
|
||||
|
||||
// Logger returns the `Logger` instance.
|
||||
func (c *context) Logger() *log.Logger {
|
||||
return c.echo.logger
|
||||
}
|
||||
|
||||
// Object returns the `context` object.
|
||||
func (c *context) Object() *context {
|
||||
return c
|
||||
}
|
||||
|
||||
// ServeContent sends a response from `io.Reader`. It automatically sets the `Content-Type`
|
||||
// and `Last-Modified` headers.
|
||||
func ServeContent(req engine.Request, res engine.Response, f http.File, fi os.FileInfo) error {
|
||||
res.Header().Set(ContentType, detectContentType(fi.Name()))
|
||||
res.Header().Set(LastModified, fi.ModTime().UTC().Format(http.TimeFormat))
|
||||
@ -366,7 +405,7 @@ func detectContentType(name string) (t string) {
|
||||
return
|
||||
}
|
||||
|
||||
func (c *context) reset(req engine.Request, res engine.Response) {
|
||||
func (c *context) Reset(req engine.Request, res engine.Response) {
|
||||
c.netContext = nil
|
||||
c.request = req
|
||||
c.response = res
|
||||
|
@ -191,8 +191,8 @@ func TestContext(t *testing.T) {
|
||||
c.Error(errors.New("error"))
|
||||
assert.Equal(t, http.StatusInternalServerError, rec.Status())
|
||||
|
||||
// reset
|
||||
c.Object().reset(req, test.NewResponseRecorder())
|
||||
// Reset
|
||||
c.Object().Reset(req, test.NewResponseRecorder())
|
||||
}
|
||||
|
||||
func TestContextPath(t *testing.T) {
|
||||
|
179
echo.go
179
echo.go
@ -1,3 +1,42 @@
|
||||
/*
|
||||
Package echo implements a fast and unfancy micro web framework for Go.
|
||||
|
||||
Example:
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/engine/standard"
|
||||
"github.com/labstack/echo/middleware"
|
||||
)
|
||||
|
||||
// Handler
|
||||
func hello() echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
return c.String(http.StatusOK, "Hello, World!\n")
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Echo instance
|
||||
e := echo.New()
|
||||
|
||||
// Middleware
|
||||
e.Use(middleware.Logger())
|
||||
e.Use(middleware.Recover())
|
||||
|
||||
// Routes
|
||||
e.Get("/", hello())
|
||||
|
||||
// Start server
|
||||
e.Run(standard.New(":1323"))
|
||||
}
|
||||
|
||||
Learn more at https://labstack.com/echo
|
||||
*/
|
||||
package echo
|
||||
|
||||
import (
|
||||
@ -20,6 +59,7 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
// Echo is the top-level framework instance.
|
||||
Echo struct {
|
||||
prefix string
|
||||
middleware []Middleware
|
||||
@ -36,33 +76,43 @@ type (
|
||||
logger *log.Logger
|
||||
}
|
||||
|
||||
// Route contains a handler and information for matching against requests.
|
||||
Route struct {
|
||||
Method string
|
||||
Path string
|
||||
Handler string
|
||||
}
|
||||
|
||||
// HTTPError represents an error that occured while handling a request.
|
||||
HTTPError struct {
|
||||
Code int
|
||||
Message string
|
||||
}
|
||||
|
||||
// Middleware defines an interface for middleware via `Handle(Handler) Handler`
|
||||
// function.
|
||||
Middleware interface {
|
||||
Handle(Handler) Handler
|
||||
}
|
||||
|
||||
// MiddlewareFunc is an adapter to allow the use of `func(Handler) Handler` as
|
||||
// middleware.
|
||||
MiddlewareFunc func(Handler) Handler
|
||||
|
||||
// Handler defines an interface to server HTTP requests via `Handle(Context)`
|
||||
// function.
|
||||
Handler interface {
|
||||
Handle(Context) error
|
||||
}
|
||||
|
||||
// HandlerFunc is an adapter to allow the use of `func(Context)` as an HTTP
|
||||
// handler.
|
||||
HandlerFunc func(Context) error
|
||||
|
||||
// HTTPErrorHandler is a centralized HTTP error handler.
|
||||
HTTPErrorHandler func(error, Context)
|
||||
|
||||
// Binder is the interface that wraps the Bind method.
|
||||
// Binder is the interface that wraps the Bind function.
|
||||
Binder interface {
|
||||
Bind(interface{}, Context) error
|
||||
}
|
||||
@ -70,41 +120,36 @@ type (
|
||||
binder struct {
|
||||
}
|
||||
|
||||
// Validator is the interface that wraps the Validate method.
|
||||
// Validator is the interface that wraps the Validate function.
|
||||
Validator interface {
|
||||
Validate() error
|
||||
}
|
||||
|
||||
// Renderer is the interface that wraps the Render method.
|
||||
// Renderer is the interface that wraps the Render function.
|
||||
Renderer interface {
|
||||
Render(io.Writer, string, interface{}, Context) error
|
||||
}
|
||||
)
|
||||
|
||||
//--------------
|
||||
// HTTP methods
|
||||
//--------------
|
||||
const (
|
||||
// CONNECT HTTP method
|
||||
CONNECT = "CONNECT"
|
||||
// DELETE HTTP method
|
||||
DELETE = "DELETE"
|
||||
// GET HTTP method
|
||||
GET = "GET"
|
||||
// HEAD HTTP method
|
||||
HEAD = "HEAD"
|
||||
// OPTIONS HTTP method
|
||||
DELETE = "DELETE"
|
||||
GET = "GET"
|
||||
HEAD = "HEAD"
|
||||
OPTIONS = "OPTIONS"
|
||||
// PATCH HTTP method
|
||||
PATCH = "PATCH"
|
||||
// POST HTTP method
|
||||
POST = "POST"
|
||||
// PUT HTTP method
|
||||
PUT = "PUT"
|
||||
// TRACE HTTP method
|
||||
TRACE = "TRACE"
|
||||
|
||||
//-------------
|
||||
// Media types
|
||||
//-------------
|
||||
PATCH = "PATCH"
|
||||
POST = "POST"
|
||||
PUT = "PUT"
|
||||
TRACE = "TRACE"
|
||||
)
|
||||
|
||||
//-------------
|
||||
// Media types
|
||||
//-------------
|
||||
const (
|
||||
ApplicationJSON = "application/json"
|
||||
ApplicationJSONCharsetUTF8 = ApplicationJSON + "; " + CharsetUTF8
|
||||
ApplicationJavaScript = "application/javascript"
|
||||
@ -120,17 +165,19 @@ const (
|
||||
TextPlainCharsetUTF8 = TextPlain + "; " + CharsetUTF8
|
||||
MultipartForm = "multipart/form-data"
|
||||
OctetStream = "application/octet-stream"
|
||||
)
|
||||
|
||||
//---------
|
||||
// Charset
|
||||
//---------
|
||||
|
||||
//---------
|
||||
// Charset
|
||||
//---------
|
||||
const (
|
||||
CharsetUTF8 = "charset=utf-8"
|
||||
)
|
||||
|
||||
//---------
|
||||
// Headers
|
||||
//---------
|
||||
|
||||
//---------
|
||||
// Headers
|
||||
//---------
|
||||
const (
|
||||
AcceptEncoding = "Accept-Encoding"
|
||||
Authorization = "Authorization"
|
||||
ContentDisposition = "Content-Disposition"
|
||||
@ -158,22 +205,24 @@ var (
|
||||
PUT,
|
||||
TRACE,
|
||||
}
|
||||
)
|
||||
|
||||
//--------
|
||||
// Errors
|
||||
//--------
|
||||
|
||||
//--------
|
||||
// Errors
|
||||
//--------
|
||||
var (
|
||||
ErrUnsupportedMediaType = NewHTTPError(http.StatusUnsupportedMediaType)
|
||||
ErrNotFound = NewHTTPError(http.StatusNotFound)
|
||||
ErrUnauthorized = NewHTTPError(http.StatusUnauthorized)
|
||||
ErrMethodNotAllowed = NewHTTPError(http.StatusMethodNotAllowed)
|
||||
ErrRendererNotRegistered = errors.New("renderer not registered")
|
||||
ErrInvalidRedirectCode = errors.New("invalid redirect status code")
|
||||
)
|
||||
|
||||
//----------------
|
||||
// Error handlers
|
||||
//----------------
|
||||
|
||||
//----------------
|
||||
// Error handlers
|
||||
//----------------
|
||||
var (
|
||||
notFoundHandler = HandlerFunc(func(c Context) error {
|
||||
return ErrNotFound
|
||||
})
|
||||
@ -206,12 +255,14 @@ func New() (e *Echo) {
|
||||
return
|
||||
}
|
||||
|
||||
func (m MiddlewareFunc) Handle(h Handler) Handler {
|
||||
return m(h)
|
||||
// Handle chains middleware.
|
||||
func (f MiddlewareFunc) Handle(h Handler) Handler {
|
||||
return f(h)
|
||||
}
|
||||
|
||||
func (h HandlerFunc) Handle(c Context) error {
|
||||
return h(c)
|
||||
// Handle serves HTTP request.
|
||||
func (f HandlerFunc) Handle(c Context) error {
|
||||
return f(c)
|
||||
}
|
||||
|
||||
// Router returns router.
|
||||
@ -261,12 +312,12 @@ func (e *Echo) SetHTTPErrorHandler(h HTTPErrorHandler) {
|
||||
e.httpErrorHandler = h
|
||||
}
|
||||
|
||||
// SetBinder registers a custom binder. It's invoked by Context.Bind().
|
||||
// SetBinder registers a custom binder. It's invoked by `Context#Bind()`.
|
||||
func (e *Echo) SetBinder(b Binder) {
|
||||
e.binder = b
|
||||
}
|
||||
|
||||
// SetRenderer registers an HTML template renderer. It's invoked by Context.Render().
|
||||
// SetRenderer registers an HTML template renderer. It's invoked by `Context#Render()`.
|
||||
func (e *Echo) SetRenderer(r Renderer) {
|
||||
e.renderer = r
|
||||
}
|
||||
@ -301,59 +352,70 @@ func (e *Echo) chainMiddleware() {
|
||||
}
|
||||
}
|
||||
|
||||
// Connect adds a CONNECT route > handler to the router.
|
||||
// Connect registers a new CONNECT route for a path with matching handler in the
|
||||
// router with optional route-level middleware.
|
||||
func (e *Echo) Connect(path string, h Handler, m ...Middleware) {
|
||||
e.add(CONNECT, path, h, m...)
|
||||
}
|
||||
|
||||
// Delete adds a DELETE route > handler to the router.
|
||||
// Delete registers a new DELETE route for a path with matching handler in the router
|
||||
// with optional route-level middleware.
|
||||
func (e *Echo) Delete(path string, h Handler, m ...Middleware) {
|
||||
e.add(DELETE, path, h, m...)
|
||||
}
|
||||
|
||||
// Get adds a GET route > handler to the router.
|
||||
// Get registers a new GET route for a path with matching handler in the router
|
||||
// with optional route-level middleware.
|
||||
func (e *Echo) Get(path string, h Handler, m ...Middleware) {
|
||||
e.add(GET, path, h, m...)
|
||||
}
|
||||
|
||||
// Head adds a HEAD route > handler to the router.
|
||||
// Head registers a new HEAD route for a path with matching handler in the
|
||||
// router with optional route-level middleware.
|
||||
func (e *Echo) Head(path string, h Handler, m ...Middleware) {
|
||||
e.add(HEAD, path, h, m...)
|
||||
}
|
||||
|
||||
// Options adds an OPTIONS route > handler to the router.
|
||||
// Options registers a new OPTIONS route for a path with matching handler in the
|
||||
// router with optional route-level middleware.
|
||||
func (e *Echo) Options(path string, h Handler, m ...Middleware) {
|
||||
e.add(OPTIONS, path, h, m...)
|
||||
}
|
||||
|
||||
// Patch adds a PATCH route > handler to the router.
|
||||
// Patch registers a new PATCH route for a path with matching handler in the
|
||||
// router with optional route-level middleware.
|
||||
func (e *Echo) Patch(path string, h Handler, m ...Middleware) {
|
||||
e.add(PATCH, path, h, m...)
|
||||
}
|
||||
|
||||
// Post adds a POST route > handler to the router.
|
||||
// Post registers a new POST route for a path with matching handler in the
|
||||
// router with optional route-level middleware.
|
||||
func (e *Echo) Post(path string, h Handler, m ...Middleware) {
|
||||
e.add(POST, path, h, m...)
|
||||
}
|
||||
|
||||
// Put adds a PUT route > handler to the router.
|
||||
// Put registers a new PUT route for a path with matching handler in the
|
||||
// router with optional route-level middleware.
|
||||
func (e *Echo) Put(path string, h Handler, m ...Middleware) {
|
||||
e.add(PUT, path, h, m...)
|
||||
}
|
||||
|
||||
// Trace adds a TRACE route > handler to the router.
|
||||
// Trace registers a new TRACE route for a path with matching handler in the
|
||||
// router with optional route-level middleware.
|
||||
func (e *Echo) Trace(path string, h Handler, m ...Middleware) {
|
||||
e.add(TRACE, path, h, m...)
|
||||
}
|
||||
|
||||
// Any adds a route > handler to the router for all HTTP methods.
|
||||
// Any registers a new route for all HTTP methods and path with matching handler
|
||||
// in the router with optional route-level middleware.
|
||||
func (e *Echo) Any(path string, handler Handler, middleware ...Middleware) {
|
||||
for _, m := range methods {
|
||||
e.add(m, path, handler, middleware...)
|
||||
}
|
||||
}
|
||||
|
||||
// Match adds a route > handler to the router for multiple HTTP methods provided.
|
||||
// Match registers a new route for multiple HTTP methods and path with matching
|
||||
// handler in the router with optional route-level middleware.
|
||||
func (e *Echo) Match(methods []string, path string, handler Handler, middleware ...Middleware) {
|
||||
for _, m := range methods {
|
||||
e.add(m, path, handler, middleware...)
|
||||
@ -392,7 +454,7 @@ func (e *Echo) add(method, path string, handler Handler, middleware ...Middlewar
|
||||
e.router.routes = append(e.router.routes, r)
|
||||
}
|
||||
|
||||
// Group creates a new router group with prefix.
|
||||
// Group creates a new router group with prefix and optional group-level middleware.
|
||||
func (e *Echo) Group(prefix string, m ...Middleware) (g *Group) {
|
||||
g = &Group{prefix: prefix, echo: e}
|
||||
g.Use(m...)
|
||||
@ -448,7 +510,7 @@ func (e *Echo) PutContext(c Context) {
|
||||
|
||||
func (e *Echo) ServeHTTP(req engine.Request, res engine.Response) {
|
||||
c := e.pool.Get().(*context)
|
||||
c.reset(req, res)
|
||||
c.Reset(req, res)
|
||||
|
||||
// Execute chain
|
||||
if err := e.head.Handle(c); err != nil {
|
||||
@ -465,6 +527,7 @@ func (e *Echo) Run(s engine.Server) error {
|
||||
return s.Start()
|
||||
}
|
||||
|
||||
// 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 {
|
||||
|
@ -54,7 +54,7 @@ type (
|
||||
// RemoteAddress returns the client's network address.
|
||||
RemoteAddress() string
|
||||
|
||||
// Method returns the request's HTTP method.
|
||||
// Method returns the request's HTTP function.
|
||||
Method() string
|
||||
|
||||
// SetMethod sets the HTTP method of the request.
|
||||
@ -136,7 +136,7 @@ type (
|
||||
QueryString() string
|
||||
}
|
||||
|
||||
// Config defines engine configuration.
|
||||
// Config defines engine config.
|
||||
Config struct {
|
||||
Address string // TCP address to listen on.
|
||||
Listener net.Listener // Custom `net.Listener`. If set, server accepts connections on it.
|
||||
@ -152,7 +152,8 @@ type (
|
||||
ServeHTTP(Request, Response)
|
||||
}
|
||||
|
||||
// HandlerFunc is an adapter to allow the use of `func(Request, Response)` as HTTP handlers.
|
||||
// HandlerFunc is an adapter to allow the use of `func(Request, Response)` as
|
||||
// an HTTP handler.
|
||||
HandlerFunc func(Request, Response)
|
||||
)
|
||||
|
||||
|
@ -16,27 +16,27 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
// Add implements `engine.Header#Add` method.
|
||||
// Add implements `engine.Header#Add` function.
|
||||
func (h *RequestHeader) Add(key, val string) {
|
||||
// h.RequestHeader.Add(key, val)
|
||||
}
|
||||
|
||||
// Del implements `engine.Header#Del` method.
|
||||
// Del implements `engine.Header#Del` function.
|
||||
func (h *RequestHeader) Del(key string) {
|
||||
h.RequestHeader.Del(key)
|
||||
}
|
||||
|
||||
// Set implements `engine.Header#Set` method.
|
||||
// Set implements `engine.Header#Set` function.
|
||||
func (h *RequestHeader) Set(key, val string) {
|
||||
h.RequestHeader.Set(key, val)
|
||||
}
|
||||
|
||||
// Get implements `engine.Header#Get` method.
|
||||
// Get implements `engine.Header#Get` function.
|
||||
func (h *RequestHeader) Get(key string) string {
|
||||
return string(h.Peek(key))
|
||||
}
|
||||
|
||||
// Keys implements `engine.Header#Keys` method.
|
||||
// Keys implements `engine.Header#Keys` function.
|
||||
func (h *RequestHeader) Keys() (keys []string) {
|
||||
keys = make([]string, h.Len())
|
||||
i := 0
|
||||
@ -51,28 +51,28 @@ func (h *RequestHeader) reset(hdr *fasthttp.RequestHeader) {
|
||||
h.RequestHeader = hdr
|
||||
}
|
||||
|
||||
// Add implements `engine.Header#Add` method.
|
||||
// Add implements `engine.Header#Add` function.
|
||||
func (h *ResponseHeader) Add(key, val string) {
|
||||
// TODO: https://github.com/valyala/fasthttp/issues/69
|
||||
// h.header.Add(key, val)
|
||||
}
|
||||
|
||||
// Del implements `engine.Header#Del` method.
|
||||
// Del implements `engine.Header#Del` function.
|
||||
func (h *ResponseHeader) Del(key string) {
|
||||
h.ResponseHeader.Del(key)
|
||||
}
|
||||
|
||||
// Get implements `engine.Header#Get` method.
|
||||
// Get implements `engine.Header#Get` function.
|
||||
func (h *ResponseHeader) Get(key string) string {
|
||||
return string(h.Peek(key))
|
||||
}
|
||||
|
||||
// Set implements `engine.Header#Set` method.
|
||||
// Set implements `engine.Header#Set` function.
|
||||
func (h *ResponseHeader) Set(key, val string) {
|
||||
h.ResponseHeader.Set(key, val)
|
||||
}
|
||||
|
||||
// Keys implements `engine.Header#Keys` method.
|
||||
// Keys implements `engine.Header#Keys` function.
|
||||
func (h *ResponseHeader) Keys() (keys []string) {
|
||||
keys = make([]string, h.Len())
|
||||
i := 0
|
||||
|
@ -22,72 +22,72 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
// TLS implements `engine.Request#TLS` method.
|
||||
// TLS implements `engine.Request#TLS` function.
|
||||
func (r *Request) TLS() bool {
|
||||
return r.IsTLS()
|
||||
}
|
||||
|
||||
// Scheme implements `engine.Request#Scheme` method.
|
||||
// Scheme implements `engine.Request#Scheme` function.
|
||||
func (r *Request) Scheme() string {
|
||||
return string(r.RequestCtx.URI().Scheme())
|
||||
}
|
||||
|
||||
// Host implements `engine.Request#Host` method.
|
||||
// Host implements `engine.Request#Host` function.
|
||||
func (r *Request) Host() string {
|
||||
return string(r.RequestCtx.Host())
|
||||
}
|
||||
|
||||
// URL implements `engine.Request#URL` method.
|
||||
// URL implements `engine.Request#URL` function.
|
||||
func (r *Request) URL() engine.URL {
|
||||
return r.url
|
||||
}
|
||||
|
||||
// Header implements `engine.Request#Header` method.
|
||||
// Header implements `engine.Request#Header` function.
|
||||
func (r *Request) Header() engine.Header {
|
||||
return r.header
|
||||
}
|
||||
|
||||
// UserAgent implements `engine.Request#UserAgent` method.
|
||||
// UserAgent implements `engine.Request#UserAgent` function.
|
||||
func (r *Request) UserAgent() string {
|
||||
return string(r.RequestCtx.UserAgent())
|
||||
}
|
||||
|
||||
// RemoteAddress implements `engine.Request#RemoteAddress` method.
|
||||
// RemoteAddress implements `engine.Request#RemoteAddress` function.
|
||||
func (r *Request) RemoteAddress() string {
|
||||
return r.RemoteAddr().String()
|
||||
}
|
||||
|
||||
// Method implements `engine.Request#Method` method.
|
||||
// Method implements `engine.Request#Method` function.
|
||||
func (r *Request) Method() string {
|
||||
return string(r.RequestCtx.Method())
|
||||
}
|
||||
|
||||
// SetMethod implements `engine.Request#SetMethod` method.
|
||||
// SetMethod implements `engine.Request#SetMethod` function.
|
||||
func (r *Request) SetMethod(method string) {
|
||||
r.Request.Header.SetMethod(method)
|
||||
}
|
||||
|
||||
// URI implements `engine.Request#URI` method.
|
||||
// URI implements `engine.Request#URI` function.
|
||||
func (r *Request) URI() string {
|
||||
return string(r.RequestURI())
|
||||
}
|
||||
|
||||
// Body implements `engine.Request#Body` method.
|
||||
// Body implements `engine.Request#Body` function.
|
||||
func (r *Request) Body() io.Reader {
|
||||
return bytes.NewBuffer(r.PostBody())
|
||||
}
|
||||
|
||||
// FormValue implements `engine.Request#FormValue` method.
|
||||
// FormValue implements `engine.Request#FormValue` function.
|
||||
func (r *Request) FormValue(name string) string {
|
||||
return string(r.RequestCtx.FormValue(name))
|
||||
}
|
||||
|
||||
// FormFile implements `engine.Request#FormFile` method.
|
||||
// FormFile implements `engine.Request#FormFile` function.
|
||||
func (r *Request) FormFile(name string) (*multipart.FileHeader, error) {
|
||||
return r.RequestCtx.FormFile(name)
|
||||
}
|
||||
|
||||
// MultipartForm implements `engine.Request#MultipartForm` method.
|
||||
// MultipartForm implements `engine.Request#MultipartForm` function.
|
||||
func (r *Request) MultipartForm() (*multipart.Form, error) {
|
||||
return r.RequestCtx.MultipartForm()
|
||||
}
|
||||
|
@ -24,12 +24,12 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
// Header implements `engine.Response#Header` method.
|
||||
// Header implements `engine.Response#Header` function.
|
||||
func (r *Response) Header() engine.Header {
|
||||
return r.header
|
||||
}
|
||||
|
||||
// WriteHeader implements `engine.Response#WriteHeader` method.
|
||||
// WriteHeader implements `engine.Response#WriteHeader` function.
|
||||
func (r *Response) WriteHeader(code int) {
|
||||
if r.committed {
|
||||
r.logger.Warn("response already committed")
|
||||
@ -40,34 +40,34 @@ func (r *Response) WriteHeader(code int) {
|
||||
r.committed = true
|
||||
}
|
||||
|
||||
// Write implements `engine.Response#Write` method.
|
||||
// Write implements `engine.Response#Write` function.
|
||||
func (r *Response) Write(b []byte) (n int, err error) {
|
||||
n, err = r.writer.Write(b)
|
||||
r.size += int64(n)
|
||||
return
|
||||
}
|
||||
|
||||
// Status implements `engine.Response#Status` method.
|
||||
// Status implements `engine.Response#Status` function.
|
||||
func (r *Response) Status() int {
|
||||
return r.status
|
||||
}
|
||||
|
||||
// Size implements `engine.Response#Size` method.
|
||||
// Size implements `engine.Response#Size` function.
|
||||
func (r *Response) Size() int64 {
|
||||
return r.size
|
||||
}
|
||||
|
||||
// Committed implements `engine.Response#Committed` method.
|
||||
// Committed implements `engine.Response#Committed` function.
|
||||
func (r *Response) Committed() bool {
|
||||
return r.committed
|
||||
}
|
||||
|
||||
// Writer implements `engine.Response#Writer` method.
|
||||
// Writer implements `engine.Response#Writer` function.
|
||||
func (r *Response) Writer() io.Writer {
|
||||
return r.writer
|
||||
}
|
||||
|
||||
// SetWriter implements `engine.Response#SetWriter` method.
|
||||
// SetWriter implements `engine.Response#SetWriter` function.
|
||||
func (r *Response) SetWriter(w io.Writer) {
|
||||
r.writer = w
|
||||
}
|
||||
|
@ -87,17 +87,17 @@ func NewFromConfig(c engine.Config) (s *Server) {
|
||||
return
|
||||
}
|
||||
|
||||
// SetHandler implements `engine.Server#SetHandler` method.
|
||||
// SetHandler implements `engine.Server#SetHandler` function.
|
||||
func (s *Server) SetHandler(h engine.Handler) {
|
||||
s.handler = h
|
||||
}
|
||||
|
||||
// SetLogger implements `engine.Server#SetLogger` method.
|
||||
// SetLogger implements `engine.Server#SetLogger` function.
|
||||
func (s *Server) SetLogger(l *log.Logger) {
|
||||
s.logger = l
|
||||
}
|
||||
|
||||
// Start implements `engine.Server#Start` method.
|
||||
// Start implements `engine.Server#Start` function.
|
||||
func (s *Server) Start() error {
|
||||
if s.config.Listener == nil {
|
||||
return s.startDefaultListener()
|
||||
|
@ -11,22 +11,22 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
// Path implements `engine.URL#Path` method.
|
||||
// Path implements `engine.URL#Path` function.
|
||||
func (u *URL) Path() string {
|
||||
return string(u.URI.Path())
|
||||
}
|
||||
|
||||
// SetPath implements `engine.URL#SetPath` method.
|
||||
// SetPath implements `engine.URL#SetPath` function.
|
||||
func (u *URL) SetPath(path string) {
|
||||
u.URI.SetPath(path)
|
||||
}
|
||||
|
||||
// QueryValue implements `engine.URL#QueryValue` method.
|
||||
// QueryValue implements `engine.URL#QueryValue` function.
|
||||
func (u *URL) QueryValue(name string) string {
|
||||
return string(u.QueryArgs().Peek(name))
|
||||
}
|
||||
|
||||
// QueryString implements `engine.URL#QueryString` method.
|
||||
// QueryString implements `engine.URL#QueryString` function.
|
||||
func (u *URL) QueryString() string {
|
||||
return string(u.URI.QueryString())
|
||||
}
|
||||
|
@ -9,27 +9,27 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
// Add implements `engine.Header#Add` method.
|
||||
// Add implements `engine.Header#Add` function.
|
||||
func (h *Header) Add(key, val string) {
|
||||
h.Header.Add(key, val)
|
||||
}
|
||||
|
||||
// Del implements `engine.Header#Del` method.
|
||||
// Del implements `engine.Header#Del` function.
|
||||
func (h *Header) Del(key string) {
|
||||
h.Header.Del(key)
|
||||
}
|
||||
|
||||
// Set implements `engine.Header#Set` method.
|
||||
// Set implements `engine.Header#Set` function.
|
||||
func (h *Header) Set(key, val string) {
|
||||
h.Header.Set(key, val)
|
||||
}
|
||||
|
||||
// Get implements `engine.Header#Get` method.
|
||||
// Get implements `engine.Header#Get` function.
|
||||
func (h *Header) Get(key string) string {
|
||||
return h.Header.Get(key)
|
||||
}
|
||||
|
||||
// Keys implements `engine.Header#Keys` method.
|
||||
// Keys implements `engine.Header#Keys` function.
|
||||
func (h *Header) Keys() (keys []string) {
|
||||
keys = make([]string, len(h.Header))
|
||||
i := 0
|
||||
|
@ -17,12 +17,12 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
// TLS implements `engine.Request#TLS` method.
|
||||
// TLS implements `engine.Request#TLS` function.
|
||||
func (r *Request) TLS() bool {
|
||||
return r.Request.TLS != nil
|
||||
}
|
||||
|
||||
// Scheme implements `engine.Request#Scheme` method.
|
||||
// Scheme implements `engine.Request#Scheme` function.
|
||||
func (r *Request) Scheme() string {
|
||||
if r.TLS() {
|
||||
return "https"
|
||||
@ -30,17 +30,17 @@ func (r *Request) Scheme() string {
|
||||
return "http"
|
||||
}
|
||||
|
||||
// Host implements `engine.Request#Host` method.
|
||||
// Host implements `engine.Request#Host` function.
|
||||
func (r *Request) Host() string {
|
||||
return r.Request.Host
|
||||
}
|
||||
|
||||
// URL implements `engine.Request#URL` method.
|
||||
// URL implements `engine.Request#URL` function.
|
||||
func (r *Request) URL() engine.URL {
|
||||
return r.url
|
||||
}
|
||||
|
||||
// Header implements `engine.Request#URL` method.
|
||||
// Header implements `engine.Request#URL` function.
|
||||
func (r *Request) Header() engine.Header {
|
||||
return r.header
|
||||
}
|
||||
@ -57,48 +57,48 @@ func (r *Request) Header() engine.Header {
|
||||
// return r.request.ProtoMinor()
|
||||
// }
|
||||
|
||||
// UserAgent implements `engine.Request#UserAgent` method.
|
||||
// UserAgent implements `engine.Request#UserAgent` function.
|
||||
func (r *Request) UserAgent() string {
|
||||
return r.Request.UserAgent()
|
||||
}
|
||||
|
||||
// RemoteAddress implements `engine.Request#RemoteAddress` method.
|
||||
// RemoteAddress implements `engine.Request#RemoteAddress` function.
|
||||
func (r *Request) RemoteAddress() string {
|
||||
return r.RemoteAddr
|
||||
}
|
||||
|
||||
// Method implements `engine.Request#Method` method.
|
||||
// Method implements `engine.Request#Method` function.
|
||||
func (r *Request) Method() string {
|
||||
return r.Request.Method
|
||||
}
|
||||
|
||||
// SetMethod implements `engine.Request#SetMethod` method.
|
||||
// SetMethod implements `engine.Request#SetMethod` function.
|
||||
func (r *Request) SetMethod(method string) {
|
||||
r.Request.Method = method
|
||||
}
|
||||
|
||||
// URI implements `engine.Request#URI` method.
|
||||
// URI implements `engine.Request#URI` function.
|
||||
func (r *Request) URI() string {
|
||||
return r.RequestURI
|
||||
}
|
||||
|
||||
// Body implements `engine.Request#Body` method.
|
||||
// Body implements `engine.Request#Body` function.
|
||||
func (r *Request) Body() io.Reader {
|
||||
return r.Request.Body
|
||||
}
|
||||
|
||||
// FormValue implements `engine.Request#FormValue` method.
|
||||
// FormValue implements `engine.Request#FormValue` function.
|
||||
func (r *Request) FormValue(name string) string {
|
||||
return r.Request.FormValue(name)
|
||||
}
|
||||
|
||||
// FormFile implements `engine.Request#FormFile` method.
|
||||
// FormFile implements `engine.Request#FormFile` function.
|
||||
func (r *Request) FormFile(name string) (*multipart.FileHeader, error) {
|
||||
_, fh, err := r.Request.FormFile(name)
|
||||
return fh, err
|
||||
}
|
||||
|
||||
// MultipartForm implements `engine.Request#MultipartForm` method.
|
||||
// MultipartForm implements `engine.Request#MultipartForm` function.
|
||||
func (r *Request) MultipartForm() (*multipart.Form, error) {
|
||||
err := r.Request.ParseMultipartForm(32 << 20) // 32 MB
|
||||
return r.Request.MultipartForm, err
|
||||
|
@ -28,12 +28,12 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
// Header implements `engine.Response#Header` method.
|
||||
// Header implements `engine.Response#Header` function.
|
||||
func (r *Response) Header() engine.Header {
|
||||
return r.header
|
||||
}
|
||||
|
||||
// WriteHeader implements `engine.Response#WriteHeader` method.
|
||||
// WriteHeader implements `engine.Response#WriteHeader` function.
|
||||
func (r *Response) WriteHeader(code int) {
|
||||
if r.committed {
|
||||
r.logger.Warn("response already committed")
|
||||
@ -44,48 +44,48 @@ func (r *Response) WriteHeader(code int) {
|
||||
r.committed = true
|
||||
}
|
||||
|
||||
// Write implements `engine.Response#Write` method.
|
||||
// Write implements `engine.Response#Write` function.
|
||||
func (r *Response) Write(b []byte) (n int, err error) {
|
||||
n, err = r.writer.Write(b)
|
||||
r.size += int64(n)
|
||||
return
|
||||
}
|
||||
|
||||
// Status implements `engine.Response#Status` method.
|
||||
// Status implements `engine.Response#Status` function.
|
||||
func (r *Response) Status() int {
|
||||
return r.status
|
||||
}
|
||||
|
||||
// Size implements `engine.Response#Size` method.
|
||||
// Size implements `engine.Response#Size` function.
|
||||
func (r *Response) Size() int64 {
|
||||
return r.size
|
||||
}
|
||||
|
||||
// Committed implements `engine.Response#Committed` method.
|
||||
// Committed implements `engine.Response#Committed` function.
|
||||
func (r *Response) Committed() bool {
|
||||
return r.committed
|
||||
}
|
||||
|
||||
// Writer implements `engine.Response#Writer` method.
|
||||
// Writer implements `engine.Response#Writer` function.
|
||||
func (r *Response) Writer() io.Writer {
|
||||
return r.writer
|
||||
}
|
||||
|
||||
// SetWriter implements `engine.Response#SetWriter` method.
|
||||
// SetWriter implements `engine.Response#SetWriter` function.
|
||||
func (r *Response) SetWriter(w io.Writer) {
|
||||
r.writer = w
|
||||
}
|
||||
|
||||
// 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)
|
||||
// See https://golang.org/pkg/net/http/#Flusher
|
||||
func (r *Response) Flush() {
|
||||
r.ResponseWriter.(http.Flusher).Flush()
|
||||
}
|
||||
|
||||
// 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)
|
||||
// See https://golang.org/pkg/net/http/#Hijacker
|
||||
func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||
return r.ResponseWriter.(http.Hijacker).Hijack()
|
||||
}
|
||||
@ -94,7 +94,7 @@ func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||
// 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)
|
||||
// See https://golang.org/pkg/net/http/#CloseNotifier
|
||||
func (r *Response) CloseNotify() <-chan bool {
|
||||
return r.ResponseWriter.(http.CloseNotifier).CloseNotify()
|
||||
}
|
||||
|
@ -80,17 +80,17 @@ func NewFromConfig(c engine.Config) (s *Server) {
|
||||
return
|
||||
}
|
||||
|
||||
// SetHandler implements `engine.Server#SetHandler` method.
|
||||
// SetHandler implements `engine.Server#SetHandler` function.
|
||||
func (s *Server) SetHandler(h engine.Handler) {
|
||||
s.handler = h
|
||||
}
|
||||
|
||||
// SetLogger implements `engine.Server#SetLogger` method.
|
||||
// SetLogger implements `engine.Server#SetLogger` function.
|
||||
func (s *Server) SetLogger(l *log.Logger) {
|
||||
s.logger = l
|
||||
}
|
||||
|
||||
// Start implements `engine.Server#Start` method.
|
||||
// Start implements `engine.Server#Start` function.
|
||||
func (s *Server) Start() error {
|
||||
if s.config.Listener == nil {
|
||||
return s.startDefaultListener()
|
||||
|
@ -10,17 +10,17 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
// Path implements `engine.URL#Path` method.
|
||||
// Path implements `engine.URL#Path` function.
|
||||
func (u *URL) Path() string {
|
||||
return u.URL.Path
|
||||
}
|
||||
|
||||
// SetPath implements `engine.URL#SetPath` method.
|
||||
// SetPath implements `engine.URL#SetPath` function.
|
||||
func (u *URL) SetPath(path string) {
|
||||
u.URL.Path = path
|
||||
}
|
||||
|
||||
// QueryValue implements `engine.URL#QueryValue` method.
|
||||
// QueryValue implements `engine.URL#QueryValue` function.
|
||||
func (u *URL) QueryValue(name string) string {
|
||||
if u.query == nil {
|
||||
u.query = u.Query()
|
||||
@ -28,7 +28,7 @@ func (u *URL) QueryValue(name string) string {
|
||||
return u.query.Get(name)
|
||||
}
|
||||
|
||||
// QueryString implements `engine.URL#QueryString` method.
|
||||
// QueryString implements `engine.URL#QueryString` function.
|
||||
func (u *URL) QueryString() string {
|
||||
return u.URL.RawQuery
|
||||
}
|
||||
|
17
group.go
17
group.go
@ -1,6 +1,9 @@
|
||||
package echo
|
||||
|
||||
type (
|
||||
// Group is a set of sub-routes 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.
|
||||
Group struct {
|
||||
prefix string
|
||||
middleware []Middleware
|
||||
@ -8,59 +11,71 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
// Use implements `Echo#Use()` for sub-routes within the Group.
|
||||
func (g *Group) Use(m ...Middleware) {
|
||||
g.middleware = append(g.middleware, m...)
|
||||
}
|
||||
|
||||
// Connect implements `Echo#Connect()` for sub-routes within the Group.
|
||||
func (g *Group) Connect(path string, h Handler, m ...Middleware) {
|
||||
g.add(CONNECT, path, h, m...)
|
||||
}
|
||||
|
||||
// Delete implements `Echo#Delete()` for sub-routes within the Group.
|
||||
func (g *Group) Delete(path string, h Handler, m ...Middleware) {
|
||||
g.add(DELETE, path, h, m...)
|
||||
}
|
||||
|
||||
// Get implements `Echo#Get()` for sub-routes within the Group.
|
||||
func (g *Group) Get(path string, h Handler, m ...Middleware) {
|
||||
g.add(GET, path, h, m...)
|
||||
}
|
||||
|
||||
// Head implements `Echo#Head()` for sub-routes within the Group.
|
||||
func (g *Group) Head(path string, h Handler, m ...Middleware) {
|
||||
g.add(HEAD, path, h, m...)
|
||||
}
|
||||
|
||||
// Options implements `Echo#Options()` for sub-routes within the Group.
|
||||
func (g *Group) Options(path string, h Handler, m ...Middleware) {
|
||||
g.add(OPTIONS, path, h, m...)
|
||||
}
|
||||
|
||||
// Patch implements `Echo#Patch()` for sub-routes within the Group.
|
||||
func (g *Group) Patch(path string, h Handler, m ...Middleware) {
|
||||
g.add(PATCH, path, h, m...)
|
||||
}
|
||||
|
||||
// Post implements `Echo#Post()` for sub-routes within the Group.
|
||||
func (g *Group) Post(path string, h Handler, m ...Middleware) {
|
||||
g.add(POST, path, h, m...)
|
||||
}
|
||||
|
||||
// Put implements `Echo#Put()` for sub-routes within the Group.
|
||||
func (g *Group) Put(path string, h Handler, m ...Middleware) {
|
||||
g.add(PUT, path, h, m...)
|
||||
}
|
||||
|
||||
// Trace implements `Echo#Trace()` for sub-routes within the Group.
|
||||
func (g *Group) Trace(path string, h Handler, m ...Middleware) {
|
||||
g.add(TRACE, path, h, m...)
|
||||
}
|
||||
|
||||
// Any implements `Echo#Any()` for sub-routes within the Group.
|
||||
func (g *Group) Any(path string, handler Handler, middleware ...Middleware) {
|
||||
for _, m := range methods {
|
||||
g.add(m, path, handler, middleware...)
|
||||
}
|
||||
}
|
||||
|
||||
// Match implements `Echo#Match()` for sub-routes within the Group.
|
||||
func (g *Group) Match(methods []string, path string, handler Handler, middleware ...Middleware) {
|
||||
for _, m := range methods {
|
||||
g.add(m, path, handler, middleware...)
|
||||
}
|
||||
}
|
||||
|
||||
// Group creates a new sub-group with prefix.
|
||||
// Group creates a new sub-group with prefix and optional sub-group-level middleware.
|
||||
func (g *Group) Group(prefix string, m ...Middleware) *Group {
|
||||
m = append(g.middleware, m...)
|
||||
return g.echo.Group(g.prefix+prefix, m...)
|
||||
|
@ -7,10 +7,12 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
// BasicAuthConfig defines config for HTTP basic auth middleware.
|
||||
BasicAuthConfig struct {
|
||||
AuthFunc BasicAuthFunc
|
||||
}
|
||||
|
||||
// BasicAuthFunc defines a function to validate basic auth credentials.
|
||||
BasicAuthFunc func(string, string) bool
|
||||
)
|
||||
|
||||
@ -19,10 +21,11 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultBasicAuthConfig is the default basic auth middleware config.
|
||||
DefaultBasicAuthConfig = BasicAuthConfig{}
|
||||
)
|
||||
|
||||
// BasicAuth returns an HTTP basic authentication middleware.
|
||||
// BasicAuth returns an HTTP basic auth middleware.
|
||||
//
|
||||
// For valid credentials it calls the next handler.
|
||||
// For invalid credentials, it sends "401 - Unauthorized" response.
|
||||
@ -32,6 +35,8 @@ func BasicAuth(f BasicAuthFunc) echo.MiddlewareFunc {
|
||||
return BasicAuthFromConfig(c)
|
||||
}
|
||||
|
||||
// BasicAuthFromConfig returns an HTTP basic auth middleware from config.
|
||||
// See `BasicAuth()`.
|
||||
func BasicAuthFromConfig(config BasicAuthConfig) echo.MiddlewareFunc {
|
||||
return func(next echo.Handler) echo.Handler {
|
||||
return echo.HandlerFunc(func(c echo.Context) error {
|
||||
|
@ -13,7 +13,9 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
// GzipConfig defines config for gzip middleware.
|
||||
GzipConfig struct {
|
||||
// Level is the gzip level.
|
||||
Level int
|
||||
}
|
||||
|
||||
@ -24,7 +26,8 @@ type (
|
||||
)
|
||||
|
||||
var (
|
||||
defaultGzipConfig = GzipConfig{
|
||||
// DefaultGzipConfig is the default gzip middleware config.
|
||||
DefaultGzipConfig = GzipConfig{
|
||||
Level: gzip.DefaultCompression,
|
||||
}
|
||||
)
|
||||
@ -32,10 +35,11 @@ var (
|
||||
// Gzip returns a middleware which compresses HTTP response using gzip compression
|
||||
// scheme.
|
||||
func Gzip() echo.MiddlewareFunc {
|
||||
return GzipFromConfig(defaultGzipConfig)
|
||||
return GzipFromConfig(DefaultGzipConfig)
|
||||
}
|
||||
|
||||
// GzipFromConfig return `Gzip` middleware from config.
|
||||
// GzipFromConfig return gzip middleware from config.
|
||||
// See `Gzip()`.
|
||||
func GzipFromConfig(config GzipConfig) echo.MiddlewareFunc {
|
||||
pool := gzipPool(config)
|
||||
scheme := "gzip"
|
||||
|
@ -15,26 +15,46 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
// LoggerConfig defines config for logger middleware.
|
||||
//
|
||||
LoggerConfig struct {
|
||||
Format string
|
||||
Output io.Writer
|
||||
// Format is the log format.
|
||||
//
|
||||
// Example "${remote_id} ${status}"
|
||||
// Available tags:
|
||||
// - time_rfc3339
|
||||
// - remote_ip
|
||||
// - method
|
||||
// - path
|
||||
// - status
|
||||
// - response_time
|
||||
// - response_size
|
||||
Format string
|
||||
|
||||
// Output is the writer where logs are written. Default is `os.Stdout`.
|
||||
Output io.Writer
|
||||
|
||||
template *fasttemplate.Template
|
||||
color *color.Color
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultLoggerConfig is the default logger middleware config.
|
||||
DefaultLoggerConfig = LoggerConfig{
|
||||
Format: "time=${time_rfc3339}, remote_ip=${remote_ip}, method=${method}, path=${path}, status=${status}, response_time=${response_time}, size=${size}\n",
|
||||
Format: "time=${time_rfc3339}, remote_ip=${remote_ip}, method=${method}, path=${path}, status=${status}, response_time=${response_time}, response_size=${response_size} bytes\n",
|
||||
color: color.New(),
|
||||
Output: os.Stdout,
|
||||
}
|
||||
)
|
||||
|
||||
// Logger returns a middleware that logs HTTP requests.
|
||||
func Logger() echo.MiddlewareFunc {
|
||||
return LoggerFromConfig(DefaultLoggerConfig)
|
||||
}
|
||||
|
||||
// LoggerFromConfig returns a logger middleware from config.
|
||||
// See `Logger()`.
|
||||
func LoggerFromConfig(config LoggerConfig) echo.MiddlewareFunc {
|
||||
config.template = fasttemplate.New(config.Format, "${", "}")
|
||||
config.color = color.New()
|
||||
@ -94,7 +114,7 @@ func LoggerFromConfig(config LoggerConfig) echo.MiddlewareFunc {
|
||||
return w.Write([]byte(status))
|
||||
case "response_time":
|
||||
return w.Write([]byte(took.String()))
|
||||
case "size":
|
||||
case "response_size":
|
||||
return w.Write([]byte(size))
|
||||
default:
|
||||
return w.Write([]byte(fmt.Sprintf("[unknown tag %s]", tag)))
|
||||
|
@ -9,14 +9,22 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
// RecoverConfig defines config for recover middleware.
|
||||
RecoverConfig struct {
|
||||
StackSize int
|
||||
StackAll bool
|
||||
// StackSize is the stack size to be printed.
|
||||
StackSize int
|
||||
|
||||
// StackAll is flag to format stack traces of all other goroutines into
|
||||
// buffer after the trace for the current goroutine, or not. Default is true.
|
||||
StackAll bool
|
||||
|
||||
// PrintStack is the flag to print stack or not. Default is true.
|
||||
PrintStack bool
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultRecoverConfig is the default recover middleware config.
|
||||
DefaultRecoverConfig = RecoverConfig{
|
||||
StackSize: 4 << 10, // 4 KB
|
||||
StackAll: true,
|
||||
@ -24,12 +32,14 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
// Recover returns a middleware which recovers from panics anywhere in the chain
|
||||
// and handles the control to the centralized HTTPErrorHandler.
|
||||
func Recover() echo.MiddlewareFunc {
|
||||
return RecoverFromConfig(DefaultRecoverConfig)
|
||||
}
|
||||
|
||||
// Recover returns a middleware which recovers from panics anywhere in the chain
|
||||
// and handles the control to the centralized HTTPErrorHandler.
|
||||
// RecoverFromConfig returns a recover middleware from config.
|
||||
// See `Recover()`.
|
||||
func RecoverFromConfig(config RecoverConfig) echo.MiddlewareFunc {
|
||||
return func(next echo.Handler) echo.Handler {
|
||||
return echo.HandlerFunc(func(c echo.Context) error {
|
||||
|
@ -9,26 +9,38 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
// StaticConfig defines config for static middleware.
|
||||
StaticConfig struct {
|
||||
Root string `json:"root"`
|
||||
Index string `json:"index"`
|
||||
Browse bool `json:"browse"`
|
||||
// Root is the directory from where the static content is served.
|
||||
Root string `json:"root"`
|
||||
|
||||
// Index is the index file to be used while serving a directory.
|
||||
// Default is `index.html`.
|
||||
Index string `json:"index"`
|
||||
|
||||
// Browse is the flag to list directory or not. Default is false.
|
||||
Browse bool `json:"browse"`
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultStaticConfig is the default static middleware config.
|
||||
DefaultStaticConfig = StaticConfig{
|
||||
Index: "index.html",
|
||||
Browse: false,
|
||||
}
|
||||
)
|
||||
|
||||
// Static returns a static middleware to deliever static content from the provided
|
||||
// root directory.
|
||||
func Static(root string) echo.MiddlewareFunc {
|
||||
c := DefaultStaticConfig
|
||||
c.Root = root
|
||||
return StaticFromConfig(c)
|
||||
}
|
||||
|
||||
// StaticFromConfig returns a static middleware from config.
|
||||
// See `Static()`.
|
||||
func StaticFromConfig(config StaticConfig) echo.MiddlewareFunc {
|
||||
return func(next echo.Handler) echo.Handler {
|
||||
return echo.HandlerFunc(func(c echo.Context) error {
|
||||
|
14
router.go
14
router.go
@ -1,6 +1,8 @@
|
||||
package echo
|
||||
|
||||
type (
|
||||
// Router is the registry of all registered routes for an `Echo` instance for
|
||||
// request matching and URL path parameter parsing.
|
||||
Router struct {
|
||||
tree *node
|
||||
routes []Route
|
||||
@ -37,6 +39,7 @@ const (
|
||||
akind
|
||||
)
|
||||
|
||||
// NewRouter returns a new Router instance.
|
||||
func NewRouter(e *Echo) *Router {
|
||||
return &Router{
|
||||
tree: &node{
|
||||
@ -47,6 +50,7 @@ func NewRouter(e *Echo) *Router {
|
||||
}
|
||||
}
|
||||
|
||||
// Handle implements `echo.Middleware` which makes router a middleware.
|
||||
func (r *Router) Handle(next Handler) Handler {
|
||||
return HandlerFunc(func(c Context) error {
|
||||
method := c.Request().Method()
|
||||
@ -56,10 +60,12 @@ func (r *Router) Handle(next Handler) Handler {
|
||||
})
|
||||
}
|
||||
|
||||
// Priority is super secret.
|
||||
func (r *Router) Priority() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Add registers a new route for method and path with matching handler.
|
||||
func (r *Router) Add(method, path string, h Handler, e *Echo) {
|
||||
ppath := path // Pristine path
|
||||
pnames := []string{} // Param names
|
||||
@ -280,6 +286,14 @@ func (n *node) check405() HandlerFunc {
|
||||
return notFoundHandler
|
||||
}
|
||||
|
||||
// Find lookup a handler registed for method and path. It also parses URL for path
|
||||
// parameters and load them into context.
|
||||
//
|
||||
// For performance:
|
||||
//
|
||||
// - Get context from `Echo#GetContext()`
|
||||
// - Reset it `Context#Reset()`
|
||||
// - Return it `Echo#PutContext()`.
|
||||
func (r *Router) Find(method, path string, context Context) {
|
||||
ctx := context.Object()
|
||||
cn := r.tree // Current node as root
|
||||
|
Loading…
Reference in New Issue
Block a user