High performance, extensible, minimalist Go web framework.
Help and questions: Github Discussions
- Optimized HTTP router which smartly prioritize routes
- Build robust and scalable RESTful APIs
- Group APIs
- Extensible middleware framework
- Define middleware at root, group or route level
- Data binding for JSON, XML and form payload
- Handy functions to send variety of HTTP responses
- Centralized HTTP error handling
- Template rendering with any template engine
- Define your format for the logger
- Highly customizable
- Automatic TLS via Let’s Encrypt
- HTTP/2 support
Click here for more information on sponsorship.
Date: 2020/11/11
Source: https://github.com/vishr/web-framework-benchmark
Lower is better!
The benchmarks above were run on an Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz
// go get github.com/labstack/echo/{version}
go get github.com/labstack/echo/v4
Latest version of Echo supports last four Go major releases and might work with older versions.
package main
import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"log/slog"
"net/http"
)
func main() {
// Echo instance
e := echo.New()
// Middleware
e.Use(middleware.Logger())
e.Use(middleware.Recover())
// Routes
e.GET("/", hello)
// Start server
if err := e.Start(":8080"); err != nil && !errors.Is(err, http.ErrServerClosed) {
slog.Error("failed to start server", "error", err)
}
}
// Handler
func hello(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
}
Following list of middleware is maintained by Echo team.
Repository | Description |
---|---|
github.com/labstack/echo-jwt | JWT middleware |
github.com/labstack/echo-contrib | casbin, gorilla/sessions, jaegertracing, prometheus, pprof, zipkin middlewares |
Be careful when adding 3rd party middleware. Echo teams does not have time or manpower to guarantee safety and quality of middlewares in this list.
Repository | Description |
---|---|
deepmap/oapi-codegen | Automatically generate RESTful API documentation with OpenAPI Client and Server Code Generator |
github.com/swaggo/echo-swagger | Automatically generate RESTful API documentation with Swagger 2.0. |
github.com/ziflex/lecho | Zerolog logging library wrapper for Echo logger interface. |
github.com/brpaz/echozap | Uber´s Zap logging library wrapper for Echo logger interface. |
github.com/samber/slog-echo | Go slog logging library wrapper for Echo logger interface. |
github.com/darkweak/souin/plugins/echo | HTTP cache system based on Souin to automatically get your endpoints cached. It supports some distributed and non-distributed storage systems depending your needs. |
github.com/mikestefanello/pagoda | Rapid, easy full-stack web development starter kit built with Echo. |
github.com/go-woo/protoc-gen-echo | ProtoBuf generate Echo server side code |
Please send a PR to add your own library here.
Use issues for everything
- For a small change, just send a PR.
- For bigger changes open an issue for discussion before sending a PR.
- PR should have:
- Test case
- Documentation
- Example (If it makes sense)
- You can also contribute by:
- Reporting issues
- Suggesting new features or enhancements
- Improve/fix documentation
- Vishal Rana (Author)
- Nitin Rana (Consultant)
- Roland Lammel (Maintainer)
- Martti T. (Maintainer)
- Pablo Andres Fuente (Maintainer)
- Contributors
echo's People
Forkers
mattn malisetti godeep aeppert hacksparrow alfg mre mnpk kristofer eksenga nilslice yanlinaung yufeiliu brg-liuwei guermahtaoufik xingskycn urandu vonrosenchild j0x47 sarvex urbie-mk2 jqk6 zofuthan dlsniper sekimura bransorem chinaweilu nextgenintelligence agk 8legd v1xingyue vicever no2key juanolon rainyear pmcgrath yriveiro raphael newoga esaul tanema buztard mmaelzer crazyjvm khaf nomon captaincodeman alejotima abhispade jllopis codeblanche eeertekin leekchan xyproto joonhochoi optimuse zhiqinyang edersohe chrisseto cxjava elct9620 zhoudianyou yangxianjun rejoicelee rainslytherin ketqi transtone xbee willf leno3416 wmydz1 pbpuccino sszgr reasonz queran zj8487 0x2901 alex8023 asamqi mr-luo tankerwng insionng andrewstucki webus hvnsweeting steenzout currantlabs strogo lshengjian younghu gitlibs eliquious husobee gowebabc phenixsh vinniey mertenvg hiying b54898533 rojtjoecho's Issues
Reverse url
Needs a function that behaves as follows:
e.Get("/users/:id", getUser)
e.URL(getUser, "123")
// => "/users/123"
context reset
Should the context.reset method also reset the context's params and store fields so we do not have data from servicing a previous http request ?
Should this data be available when servicing the current request and could it not contain data from a previous request ?
I can create a PR, just want to clarify before doing so
See https://github.com/labstack/echo/blob/d97cb44d82607ae0db8cc45cdd8fe2bb778fbce8/context.go#L100-104
Pat
Json Web Token middleware
Hey!
Any plans to have a built-in jwt middleware?
Parent middleware is not being applied to sub-groups
Middleware that gets added to a parent route is not being applied to any of the groups created off that route.
Here is a reproducible example:
package main
import (
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
)
func main() {
e := echo.New()
e.Use(middleware.Logger)
g := e.Group("/group")
g.Get("/search", func(e *echo.Context) {
e.String(200, "Hello, World!")
})
e.Run(":3000")
}
If you were to run that code and the curl http://localhost:3000/group/search
you will see that the logging middleware was never triggered.
To get the desire effect one has to change the application to explicitly add the desired middleware to the group as well as the parent:
package main
import (
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
)
func main() {
e := echo.New()
e.Use(middleware.Logger)
g := e.Group("/group")
g.Use(middleware.Logger)
g.Get("/search", func(e *echo.Context) {
e.String(200, "Hello, World!")
})
e.Run(":3000")
}
Example of template sets?
I've tried to load template sets based on documentation but still have no idea how.
Below is example using plain Go
. I'm trying to make this using echo
and output on browser.
server.go
:
package main
import (
"fmt"
"os"
"text/template"
)
type Person struct {
Name, Age string
}
func main() {
p := Person{Name: "Mary", Age: "35"} //define an instance with required field
s1, _ := template.ParseFiles("t1.tmpl", "t2.tmpl") //create a set of template from many files.
s1.ExecuteTemplate(os.Stdout, "basetemplate", p) //execute basetemplate
fmt.Println()
s1.Execute(os.Stdout, p)
}
t1.tmpl
:
{{define "basetemplate"}}My name is {{.Name}} and {{template "insideit" .}}years old.{{end}}
t2.tmpl
:
{{define "insideit"}}I'm {{.Age}} {{end}}
Output: My name is Mary and I'm 35 years old.
runtime error: index out of range in router Find
Test code:
package main
import (
"github.com/labstack/echo"
)
func main() {
e := echo.New()
gr := e.Group("/acct/:a")
gr.Get("/hello", helloHandler)
e.Run(":4444")
}
func helloHandler(c *echo.Context) {
c.String(200, "Hello World!")
}
Failure demo:
$ go run main.go &
[1] 27082
$ curl -i http://localhost:4444/acct/abc
2015/04/28 21:22:57 http: panic serving [::1]:46035: runtime error: index out of range
goroutine 5 [running]:
net/http.func·011()
/big/usr-local/go/src/net/http/server.go:1130 +0xbb
github.com/labstack/echo.(*router).Find(0xc20800a750, 0xc20801e440, 0x3, 0xc20801e444, 0x9, 0xc2080403c0, 0x0, 0x0)
/home/src/github.com/labstack/echo/router.go:271 +0x43d
github.com/labstack/echo.(*Echo).ServeHTTP(0xc208066000, 0x7f50a9246010, 0xc2080441e0, 0xc208032410)
/home/src/github.com/labstack/echo/echo.go:294 +0xd0
net/http.serverHandler.ServeHTTP(0xc208042060, 0x7f50a9246010, 0xc2080441e0, 0xc208032410)
/big/usr-local/go/src/net/http/server.go:1703 +0x19a
net/http.(*conn).serve(0xc208044000)
/big/usr-local/go/src/net/http/server.go:1204 +0xb57
created by net/http.(*Server).Serve
/big/usr-local/go/src/net/http/server.go:1751 +0x35e
curl: (52) Empty reply from server
$ curl -i http://localhost:4444/acct/abc/
2015/04/28 21:23:05 http: panic serving [::1]:46036: runtime error: index out of range
goroutine 6 [running]:
net/http.func·011()
/big/usr-local/go/src/net/http/server.go:1130 +0xbb
github.com/labstack/echo.(*router).Find(0xc20800a750, 0xc20801e520, 0x3, 0xc20801e524, 0xa, 0xc208040500, 0x0, 0x0)
/home/src/github.com/labstack/echo/router.go:271 +0x43d
github.com/labstack/echo.(*Echo).ServeHTTP(0xc208066000, 0x7f50a9246010, 0xc208044320, 0xc2080325b0)
/home/src/github.com/labstack/echo/echo.go:294 +0xd0
net/http.serverHandler.ServeHTTP(0xc208042060, 0x7f50a9246010, 0xc208044320, 0xc2080325b0)
/big/usr-local/go/src/net/http/server.go:1703 +0x19a
net/http.(*conn).serve(0xc208044280)
/big/usr-local/go/src/net/http/server.go:1204 +0xb57
created by net/http.(*Server).Serve
/big/usr-local/go/src/net/http/server.go:1751 +0x35e
curl: (52) Empty reply from server
caddy support?
Parameters mixed up between routes
Looks like the parameters and getting mixed up when two routes share the same url, but not the same parameters.
[...]
e.Get("/list", test)
e.Get("/list/:limit", test)
[...]
func test(c *echo.Context) {
fmt.Println(c.Param("limit"))
}
/list
-> prints nothing
/list/100
-> prints "100"
/list
-> prints "100"
Looks like the limit parameter persists when it shouldn't.
Allow log warning to be controlled for Response.committed
Line 24 in 04cdefb
I'm trying to stream a JSON response, which works just fine but I get warning messages logged.
For example:
func streamTest(c *echo.Context) *echo.HTTPError {
i := 0
for {
i++
c.JSON(http.StatusOK, &SomeStruct{Name: fmt.Sprintf("John Doe #%d", cpt)})
c.Response.Writer.(http.Flusher).Flush()
// send every 3 seconds
time.Sleep(time.Duration(3) * time.Second)
}
}
If there was a way to set something to ignore warnings or disable logging or something that'd be great. Thanks!
port echo'router to node.js
Just notify. :)
https://github.com/trekjs/router
And I will refactor trekjs'router system.
Thanks. Great work! 👍
NewHttpError does not assign given message to HTTPError struct
https://github.com/labstack/echo/blob/master/echo.go#L123 if no msgs is given, http.StatusText is used, if one is given it is ignored.
Router cannot find a handler
I'd try bolt as router, and encountered unexpected behavior to me.
Code:
r := New().Router
r.Add("GET", "/alice", func(c *Context) {})
r.Add("GET", "/:name", func(c *Context) {})
h, _, _ := r.Find("GET", "/bob")
if h == nil {
fmt.Printf("handler not found\n")
return
}
Output:
handler not found
Is this the intended behavior?
Custom context supplied with a method
Hi,
I want to supply some application wide context to my echo handlers by making my handlers a method on AppContext
. A struct containing some pointers to storage engines etc. As an example:
// FindOne returns a single thread in the API
func (a *AppContext) FindOne(c *echo.Context) error {
id := c.P(0)
thread, err := a.ThreadStorage.FindOne(id)
if err != nil {
return c.JSON(http.StatusNotFound, nil)
}
return c.JSON(http.StatusOK, thread)
}
Now, the strange thing is that if I place this method in my main.go
, everything works fine. However, as soon as I place it in a separate file (same package) it gives me the error panic: echo: unknown handler
as seen in echo.go.
Is this a completely wrong use case or should the method satisfy as a handler for Echo?
Panic-Recover Middleware
Hi. How can I write Panic-Recover Middleware? 500 error in case of panic.
Have Bind() handle application/x-www-form-urlencoded
Currently Bind()
only handles decoding JSON in the body of the request. It would be handy to have this handle url encoded form bodies as well. I patched this for myself real quick using the gorilla/schema decoder. Not sure what you think about external dependencies.
Run middleware from middleware chain and context access
Hi guys,
I being use Echo a while and there are two things to discuss with you, I guess it would be a nice have.
- If I 'Use' a middleware of mine, is it possible to Run that Middleware for a given route ?
I mean:
...
echo.Use(middlewareA)
echo.Use(middlewareB)
...
echo.Get("/home"), func(c *echo.Context) {
echo.Execute(middlewareA)
})
echo.Get("/root"), func(c *echo.Context) {
echo.Execute(middlewareB)
})
2 ) It would be cool, when using Echo and external middlewares like negroni, to access Echo Context easily through Echo instance. Since Echo allows wrapping Handlers, we can't use Echo context when needed inside of one of that foreign handlers like:
echo.Get("/user",negroni.New(
negroni.HandlerFunc(...),
negroni.HandlerFunc(...),
...
))
I hope I'm not saying stupid things totally other way from the project purpose.
Many thanks
Router Match Rules
The router maps below:
r.Add('GET', '/users/:id', func(c *Context) {})
r.Add('GET', '/photos/:id', func(c *Context) {})
r.Add('GET', '/:c/:a', func(c *Context) {})
h, _ := r.Find('GET', '/controller/action')
// => h == nil
I think the /controller/action
path should be matched, but not.
Param returning empty string
I modified the example project a bit, adding this:
func nextUserId() string {
var next = nextid;
nextid += 1;
return strconv.Itoa(next)
}
func createUser(c *echo.Context) {
u := new(user)
u.ID = nextUserId()
u.Name = c.Param("name")
if c.Bind(u) {
users[u.ID] = *u
c.JSON(http.StatusCreated, u)
}
}
Except u.Name
is for some reason always the empty string. What am I doing wrong? I've looked at the context.go
source and it looks like it should work.
Mistake in Response section of guide
Serving favicon
echo.Favicon(file string) serves default favicon - GET /favicon.ico. For example, code below serves favicon from file public/favicon.ico.
e.Index("public/favicon.ico")
but need e.Favicon("public/favicon.ico")
Stable API
Hi. Thank you for this project, it's great. I want to ask when do you plan to release stable api to use in production. Is there a lot things to do which can break backward compatibility?
I can use echo in Google Cloud Platform?
I try this, but routes not work (response 404 page)
support for context.Render
Would be awesome if there was a Render
function in context similar to rendering JSON
.
Having this RendererFunc
interface would allow to use any renderer. Would also be good to have html/template
as a default Render. This is similar to how http.Handler and http.HandlerFunc
is implemented.
type Renderer interface {
Render(w http.ResponseWriter, r *http.Request, status int, name string, data interface{})
}
type RendererFunc (w http.ResponseWriter, r *http.Request, status int, name string, data interface{})
func (f RendererFunc) Render(w http.ResponseWriter, r *http.Request, status int, name string, data interface{})
gin use ... interface{}
for data
. Also should we also pass *http.Request
to Render
so that it can support content negotiation? If we pass request as nil
then we can tell the render to not use content negotiation. Not sure if this is too much of magic. I think content negotiation should be a separate topic.
Here is sample api that could be possible to use. Thoughts?
var e := echo.New()
e.Get("/", func (c *e.Context) {
c.Render(http.StatusOK, "home", nil)
});
Installation giving error
go version go1.1.2 linux/386
Install by go get github.com/labstack/echo
will give below error
# github.com/labstack/echo
/root/go/src/github.com/labstack/echo/context.go:17: invalid recursive type Echo
/root/go/src/github.com/labstack/echo/echo.go:30: undefined: sync.Pool
/root/go/src/github.com/labstack/echo/router.go:305: r.echo.pool undefined (type *Echo has no field or method pool)
/root/go/src/github.com/labstack/echo/router.go:306: cannot assign <T> to _ (type blank) in multiple assignment
/root/go/src/github.com/labstack/echo/router.go:311: r.echo.notFoundHandler undefined (type *Echo has no field or method notFoundHandler)
/root/go/src/github.com/labstack/echo/router.go:313: r.echo.pool undefined (type *Echo has no field or method pool)
Am I missed something?
why HTTPError as return from HandlerFunc?
Why did you make the breaking change to require HandlerFunc to return *HTTPError instead of error? Why not make HTTPError implement the Error() method and then it can be passed as error? This way a handler could either return a plain error or an HTTPError.
The pool leaks contexts if the handlers panics.
If the handler panics, the context is never released in the pool
Line 234 in de6644a
CORS and concurrency
Hi guys,
I've been using echo for a while and its awesome. Congratz. 👍
My bundle has a front-end application that requests data from an API with echo. When the load of requests is too high, sometimes I receive a HTTP 502 error due a >> No 'Access-Control-Allow-Origin' header is present on the requested resource. <<
I use rs/cors middleware as found in the docs.
The headers are well-formed as it is supposed to be.
Between client and Go API there is a cloudflare-nginx server.
What are you're guess about this ? Has Echo any kind of issue regarding concurrent requests ? Like that ones "Response headers were already written" ?
I can reproduce this error if I kill the API service. Response from server is the same. It seems a concurrency problem..
Thank you so much for your help. :)
Help testing middleware
echo currently makes it hard/impossible to initialize a context outside of an actual HTTP request handling (the "response" field is private for example). This makes testing echo middleware tricky as one cannot just mock a context. It would be good if echo exposed a way to create arbitrary contexts. To make things more concrete here is an example of what I'm trying to achieve:
// Create dummy echo.Context with request for tests
// Note: echo makes it impossible to initialize the context response :(
func dummyContext() *echo.Context {
req, _ := http.NewRequest("POST", "http://example.com", strings.NewReader("foo"))
ctx := echo.Context{Request: req}
ctx.String(200, "ok") // BLOWS UP because "response" not initialized
return &ctx
}
c.Request.Header.Get("Referer") — not works on latest Echo release
This codes works on previous Echo release, but not works on the latest Echo release:
package main
import (
"github.com/labstack/echo"
"github.com/snowplow/referer-parser/go"
"net/http"
)
func main() {
e := echo.New()
e.Get("/users", func(c *echo.Context) error {
refererURL := c.Request.Header.Get("Referer")
r := refererparser.Parse(refererURL)
return c.String(http.StatusOK, "The search term is: "+r.SearchTerm)
})
e.Run(":4444")
}
Running above codes will give error:
c.Request.Header undefined (type func() *http.Request has no field or method Header)
I failed to find any solution elsewhere.
context doesn't capture "Group" params
The request params that are part of the Group prefix are not captured correctly. Here's a test program:
package main
import (
"fmt"
"github.com/labstack/echo"
)
func main() {
e := echo.New()
gr := e.Group("/acct/:a")
gr.Get("/hello", helloHandler)
e.Run(":4444")
}
func helloHandler(c *echo.Context) {
c.String(200, fmt.Sprintf("Hello World!\nacct: %s\n%#v\n", c.Param("acct"), *c))
}
and a simple test:
2$ go run main.go &
[1] 1485
tve@h:/home/src/github.com/rightscale/uca/bug2$ curl http://localhost:4444/acct/123/hello
Hello World!
acct:
echo.Context{Request:(*http.Request)(0xc2080325b0), Response:(*echo.response)(0xc20803ac90), pnames:[]string(nil), pvalues:[]string{"123", "", "", "", ""}, store:echo.store{}, echo:(*echo.Echo)(0xc208066080)}
You can see that the 'acct' param is empty, but in the context the value of the param was captured but not the name. Am I doing something wrong?
Static handler broken
e.Static()
seems to have broken. With a very simple setup to serve an index page and script it no longer works and returns 'not found' for requests that should be served by the static handler. If the e.Index method is commented out then it works so some interaction with how the routes are built up or searched (?)
e.Index("public/index.html")
e.Static("/scripts", "public/scripts")
Decouple router from context usage
Hi,
I'd like to know if there's a way to have the router decoupled from the context.
My use case is that I'd like to use the routing part but without all the other context stuff as I have a custom context already built.
What do you think?
Sync pool resetting context
- Store
- Status code
NotFoundHandler: panic: echo: unknown handler
The following code fails with panic: echo: unknown handler
line 16: e.NotFoundHandler(index)
package main
import (
"net/http"
"github.com/labstack/echo"
)
func index(c *echo.Context) {
c.HTML(http.StatusOK, "<html></html>")
}
func main() {
e := echo.New()
e.NotFoundHandler(index)
e.Run(":1234")
}
I have an older version of echo (54d2f72) and with that the code above works just fine. Could this be a bug or am I missing something?
Catch route with regex
This will allow catching a bad route using regex for situations where route is bad written.
Main route: "/home"
Bad route: "/hhome"
If I could declare a route e.Get("/* ") or e.Get(" [a-zA-Z0-9]+ ") I could work over the response Header.
Many thanks
Middleware chain no longer traversed if no route found
73fa05f (https://github.com/labstack/echo/blob/master/echo.go#L323) makes ServeHTTP skip all middlewares if no matching route is found.
This breaks among other things logging of 404 requests with logger middleware, also other middlewares we use like CORS/preflight for options requests do no longer work as we have no matching Options routes. Is this intended (and future) behavior to skip all the middlewares if no matching route is found or is it a bug?
Serving static file
Create a mechanism for serving static files
Documentation Generation
I'm thinking of using echo for a large project and one of the requirements will be extensive documentation, it would be nice to automatically keep the code and docs in sync with something like:
e := echo.New()
...
//with cli flag, or even via another REST endpoint
if generate {
//json.MarshalIndent internal echo structures (fn name, methods, urls, params, middleware, etc.)
b := e.GenerateSpec()
//display
os.Stdout.Write(b)
//or, send to documentation server
http.Post("...", "application/json", &bytes.NewBuffer(b))
}
Then the user could convert the structures into:
- a https://apiary.io/ API blueprint
- a http://swagger.io/ spec
- a https://github.com/mashery/iodocs spec
Thoughts?
/users/new and /users/:id doesn't seem to work correctly
If I have this program. It does navigate to /user/new
route but says not found for /users/:id
route.
package main
import "github.com/labstack/echo"
func main() {
app := echo.New()
app.Get("/users/new", func(c *echo.Context) {
c.String(200, "/users/new")
})
app.Get("/users/:id", func(c *echo.Context) {
c.String(200, "/users/:id")
})
app.Run(":3000")
}
For express to work it needs to be in order but for hapijs it can be any order and it will automatically match with the stricter first.
Support for streaming API
Echo response that implements http.Hijack
I could just copy that issue: go-martini/martini#45
It's almost the same problem. I am new to go and working on my first small project. I am now almost done and wanted to add websockets.
But I ran into this error websocket: response does not implement http.Hijacker
.
I guess I could just rewrite some parts and use Martini or some other framework, but I really started to like Echo.
What do you think? Would it be possible to implement http.Hijack or would this be against the concept of Echo?
As in the Martini issue I would like to say: "please excuse me if this is just nonesense".
Middleware documentation/examples
Any documentation/advice on creating own middleware for Echo? There are things that I see to be different to other frameworks - no need to pass control to the next middleware in the chain for one?
I'm writing a simple basicauth middleware - it partially works but returns and flow passes to the route handler's function, so I get double output:- a 401 then the route's func handler response. How should I approach it to halt in the middleware and serve just the 401 Unauthorized?
Full disclosure: I'm fairly new to Go, so I'm still bit of a hacker and apologies if what I've asked seems basic or approached in the wrong way.
nested resources and named params problem
I have the nested resource routes,
below case will be failed:
r.Add("GET", "/users/new", func(*Context) {}, nil)
r.Add("GET", "/users/wen", func(*Context) {}, nil)
r.Add("GET", "/users/:id", func(*Context) {}, nil)
r.Add("GET", "/users/:userId/photos/:photoId/comments/:id", func(*Context) {}, nil)
h, _, _ := r.Find(MethodGET, "/users/233/photos/377/comments/610")
if h == nil {
t.Fatal("handle not found")
}
Tree
└── /users/ has=0, h=<nil>, echo=0, edges=3
├── new has=0, h=0x6e8a0, echo=0, edges=0
├── wen has=0, h=0x6e8b0, echo=0, edges=0
└── : has=0, h=<nil>, echo=0, edges=2
├── id has=0, h=0x6e8c0, echo=0, edges=0
└── userId has=0, h=<nil>, echo=0, edges=1
└── /photos/ has=1, h=<nil>, echo=0, edges=1
└── :photoId has=0, h=<nil>, echo=0, edges=1
└── /comments/ has=1, h=<nil>, echo=0, edges=1
└── :id has=0, h=0x6e8d0, echo=0, edges=0
Per-route middlewares
This should be an enhancement. It is useful for a few of us out here that a router + middleware would allow per-route middlewares. Say you have a small admin panel and you want to use the http-auth middleware in just that route, but you don't want to apply it to all the other routes declared, currently, looks like it's not possible without something like alice.
Several routers already have the option to mix with certain middleware chainers such as alice or negroni, but they always loose any kind of functionality related to the router, though. For example, you can create an alice chain to a certain handler in httprouter but then, how do you retrieve any named parameter from the url? By passing the handler to alice, you lose the ability to retrieve them in the handler.
Error out for already registered route
Create website with documentation
Create changelog or history file
It would be nice if we could see the past versions and changes in time :) Great job on the project :) Thank you.
panic: echo => unknown middleware
This morning I pulled down the latest version of echo and when I try to use the new middleware I get the following panic:
panic: echo => unknown middleware
goroutine 1 [running]:
github.com/labstack/echo.wrapMiddleware(0x21e600, 0x364d38, 0x18040d0)
/Users/markbates/Dropbox/development/gocode/src/github.com/labstack/echo/echo.go:399 +0x35c
github.com/labstack/echo.(*Echo).Use(0xc208054090, 0xc20801f768, 0x1, 0x1)
/Users/markbates/Dropbox/development/gocode/src/github.com/labstack/echo/echo.go:215 +0xa7
main.main()
/Users/markbates/Dropbox/Desktop/scraps/scrap.go:10 +0xbf
goroutine 2 [runnable]:
runtime.forcegchelper()
/usr/local/go/src/runtime/proc.go:90
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:2232 +0x1
goroutine 3 [runnable]:
runtime.bgsweep()
/usr/local/go/src/runtime/mgc0.go:82
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:2232 +0x1
goroutine 4 [runnable]:
runtime.runfinq()
/usr/local/go/src/runtime/malloc.go:712
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:2232 +0x1
exit status 2
shell returned 1
Here is a simple, reproducible (for me at least), bit of code to demonstrate the issue.
package main
import (
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
)
func main() {
e := echo.New()
e.Use(middleware.Recover)
e.Run(":3000")
}
`*` doesn't match an empty string
I would expect *
in a route to match any string, including the empty string. It doesn't, though:
package main
import (
"fmt"
"github.com/labstack/echo"
)
func okay(context *echo.Context) {
context.String(200, "")
}
func main() {
e := echo.New()
e.Post("members*", okay)
handler, ech := e.Router.Find("POST", "members", nil)
fmt.Printf("%+v %+v\n", handler, ech)
}
Prints <nil>, <nil>
.
Add interface that unifies *echo.Router and *echo.Group
Since Groups were recently split from the main echo.Router class, it's difficult for my application to work on these two classes simultaneously: 1) root level router (defined as *echo.Router), or 2) a sub-group (defined as *echo.Group)
It should be simple to make an interface that covers the common parts of both APIs, then calling applications could just expect that to be passed in instead.
Does this make sense?
Serving static files also list directory when opened at root.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.