Gem is an easy to use and high performance web framework written in Go(golang), it supports HTTP/2, and provides leveled logger and frequently used middlewares.
Note: requires
go1.8
or above.
Starter Kit is available, it provides a convenient way to create an application.
- High performance
- Friendly to REST API
- Full test of all APIs
- Pretty and fast router - the router is custom version of httprouter
- HTTP/2 support - HTTP/2 server push was supported since
go1.8
- Leveled logging - included four levels
debug
,info
,error
andfatal
, the following packages are compatible with Gem- logrus - structured, pluggable logging for Go
- go-logging - golang logging library
- gem-log - default logger
- Frequently used middlewares
- CORS Middleware - Cross-Origin Resource Sharing
- AUTH Middleware - HTTP Basic and HTTP Digest authentication
- JWT Middleware - JSON WEB TOKEN authentication
- Compress Middleware - Compress response body
- Request Body Limit Middleware - limit request body maximum size
- Rate Limiting Middleware - limit API usage of each user
- CSRF Middleware - Cross-Site Request Forgery protection
- Frozen APIs
- Hardly any third-party dependencies
- Compatible with third-party packages of
net/http
, such as gorilla sessions, gorilla websocket etc
$ go get -u github.com/go-gem/gem
package main
import (
"log"
"github.com/go-gem/gem"
)
func index(ctx *gem.Context) {
ctx.HTML(200, "hello world")
}
func main() {
// Create server.
srv := gem.New(":8080")
// Create router.
router := gem.NewRouter()
// Register handler
router.GET("/", index)
// Start server.
log.Println(srv.ListenAndServe(router.Handler()))
}
Context embedded http.ResponseWriter
and *http.Request
, and
provides some useful APIs and shortcut, see https://godoc.org/github.com/go-gem/gem#Context.
AFAIK, the following leveled logging packages are compatible with Gem web framework:
- logrus - structured, pluggable logging for Go
- go-logging - golang logging library
- gem-log - default logger
- Please let me know if I missed the other logging packages :)
Logger includes four levels: debug
, info
, error
and fatal
.
APIs
Debug
andDebugf
Info
andInfof
Error
andErrorf
Fatal
andFatalf
For example:
// set logrus logger as server's logger.
srv.SetLogger(logrus.New())
// we can use it in handler.
router.GET("/logger", func(ctx *gem.Context) {
ctx.Logger().Debug("debug")
ctx.Logger().Info("info")
ctx.Logger().Error("error")
})
router.ServeFiles("/tmp/*filepath", http.Dir(os.TempDir()))
Note: the first parameter must end with *filepath
.
The router is friendly to REST APIs.
// user list
router.GET("/users", func(ctx *gem.Context) {
ctx.JSON(200, userlist)
})
// add user
router.POST("/users", func(ctx *gem.Context) {
ctx.Request.ParseForm()
name := ctx.Request.FormValue("name")
// add user
ctx.JSON(200, msg)
})
// user profile.
router.GET("/users/:name", func(ctx *gem.Context) {
// firstly, we need get the username from the URL query.
name, err := gem.String(ctx.UserValue("name"))
if err != nil {
ctx.JSON(404, userNotFound)
return
}
// return user profile.
ctx.JSON(200, userProfileByName(name))
})
// update user profile
router.PUT("/users/:name", func(ctx *gem.Context) {
// firstly, we need get the username from the URL query.
name, err := gem.String(ctx.UserValue("name"))
if err != nil {
ctx.JSON(404, userNotFound)
return
}
// get nickname
ctx.Request.ParseForm()
nickname := ctx.Request.FormValue("nickname")
// update user nickname.
ctx.JSON(200, msg)
})
// delete user
router.DELETE("/users/:name", func(ctx *gem.Context) {
// firstly, we need get the username from the URL query.
name, err := gem.String(ctx.UserValue("name"))
if err != nil {
ctx.JSON(404, userNotFound)
return
}
// delete user.
ctx.JSON(200, msg)
}
See https://github.com/go-gem/examples/tree/master/http2.
router.GET("/", func(ctx *gem.Context) {
if err := ctx.Push("/images/logo.png", nil); err != nil {
ctx.Logger().Info(err)
}
ctx.HTML(200, `<html><head></head><body><img src="/images/logo.png"/></body></html>`)
})
router.ServeFiles("/images/*filepath", http.Dir(imagesDir))
It is easy to implement a middleware, see Middleware interface,
you just need to implement the Wrap
function.
type Middleware interface {
Wrap(next Handler) Handler
}
For example, we defined a simple debug middleware:
type Debug struct{}
// Wrap implements the Middleware interface.
func (d *Debug) Wrap(next gem.Handler) gem.Handler {
// gem.HandlerFunc is an adapter like http.HandlerFunc.
return gem.HandlerFunc(func(ctx *gem.Context) {
// print request info.
log.Println(ctx.Request.URL, ctx.Request.Method)
// call the next handler.
next.Handle(ctx)
})
}
and then we should register it:
register the middleware for all handlers via Router.Use.
router.Use(&Debug{})
we can also set up the middleware for specific handler via HandlerOption.
router.GET("/specific", specificHandler, &gem.HandlerOption{Middlewares:[]gem.Middleware{&Debug{}}})
Gem also provides some frequently used middlewares, see Middlewares.
Context provides two useful methods: SetUserValue
and UserValue
to share data between middlewares.
// Store data into context in one middleware
ctx.SetUserValue("name", "foo")
// Get data from context in other middleware or handler
ctx.UserValue("name")
Please let me know that you composed some middlewares, I will mention it here, I believe it would be helpful to users.
- CORS Middleware - Cross-Origin Resource Sharing
- AUTH Middleware - HTTP Basic and HTTP Digest authentication
- JWT Middleware - JSON WEB TOKEN authentication
- Compress Middleware - compress response body
- Request Body Limit Middleware - limit request body maximum size
- Rate Limiting Middleware - limit API usage of each user
- CSRF Middleware - Cross-Site Request Forgery protection
Gem follows semantic versioning 2.0.0 managed through GitHub releases.
- ⭐ the project.
- Spread the word.
- Contribute to the project.
- Report issues
- Send PRs.
- Improve/fix documentation.
We’re always looking for help, so if you would like to contribute, we’d love to have you!
The v2
and v1
are totally different:
-
v2
built on top ofnet/http
instead offasthttp
. -
v2
requirego1.8
or above. -
v2
is compatible withWindows
.
-
Why choose
net/http
instead offasthttp
?-
net/http
has much more third-party packages thanfasthttp
. -
fasthttp
doesn't supportHTTP/2
yet.
-
BSD 3-Clause License, see LICENSE and AUTHORS.
Inspiration & Credits
For respecting the third party packages, I added their author into AUTHORS, and listed those packages here.
- httprouter - LICENSE.
Gem's router is a custom version of
httprouter
, thanks tohttprouter
.