The Good Framework
Gramework long-term testing stand metrics screenshot made with Gramework Stats Dashboard and metrics middleware
Gramework is a fast, highly effective, reliable, SPA-first, go-way web framework made by a fasthttp maintainer. You get the simple yet powerful API, we handle optimizations internally. We're always glad to see your feature requests and PRs.
Reasons to use Gramework
- Gramework has a stable API.
- Gramework is battle-tested.
- Gramework is made by a maintainer of fasthttp.
- Gramework is one of the rare frameworks that can help you use your server's resources more efficiently.
- Gramework lowers your infrastructure costs by using as little memory as possible.
- Gramework helps you serve requests faster, and so it helps you increase conversions (source 1, source 2).
- With Gramework you can build software faster using a simple yet powerful and highly optimized API.
- With Gramework you get enterprise-grade support and answers to all your questions.
- At the Gramework team, we respect our users.
- You can directly contact the maintainer and donate for high priority feature.
- You can be sure that all license questions are OK with gramework.
Go >= 1.9.6 is the oldest continously tested and supported version.
If you encounter any vulnerabilities then please feel free to submit them via k@gramework.win.
Name | Link/Badge |
---|---|
Docs | GoDoc |
Our Jira | Jira |
License Report | Report |
Changelog | Changelog |
Support us with a donation or become a sponsor | OpenCollective |
Our Telegram chat | @gramework |
Our #gramework channel in the Gophers Slack | https://gophers.slack.com |
Our Discord Server | https://discord.gg/HkW8DsD |
Master branch coverage | |
Master branch status | |
Dev branch coverage | |
Dev branch status | |
CII Best Practices | |
Gramework Stats Dashboard for Grafana | https://grafana.com/dashboards/3422 |
Support contacts | Via email: k@gramework.win |
Via phone (urgent support only): +1 484-666-0990 | |
Via Telegram: @gramework_support | |
Via Telegram community: @gramework |
This project exists thanks to our awesome contributors! [Contribute].
Thank you to all our backers! 🙏 [Become a backer]
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]
- Gramework is now powered by fasthttp and an embedded custom fasthttprouter.
You will find the according licenses in
/third_party_licenses/fasthttp
and/third_party_licenses/fasthttprouter
. - The 3rd autoTLS implementation, placed in
nettls_*.go
, is an integrated version of caddytls, because using it through a simple import isn't an option, gramework is based onfasthttp
, which is incompatible withnet/http
. In the commit I based on, caddy isApache-2.0
licensed. Its license placed in/third_party_licenses/caddy
. @mholt allow us to copy the code in this repo.
The example below will serve "hello, grameworld". Gramework will register the bind
flag for you, that allows you to choose another ip/port that gramework should listen on:
package main
import (
"github.com/gramework/gramework"
)
func main() {
app := gramework.New()
app.GET("/", "hello, grameworld")
app.ListenAndServe()
}
If you don't want to support the bind
flag then pass the optional address argument to ListenAndServe
.
NOTE: all examples below will register the bind
flag.
From version: 1.1.0-rc1
The example below will serve {"hello":"grameworld"}
from the map. Gramework will register the bind
flag for you, that allows you to choose another ip/port that gramework should listen on:
package main
import (
"github.com/gramework/gramework"
)
func main() {
app := gramework.New()
app.GET("/", func() map[string]interface{} {
return map[string]interface{}{
"hello": "gramework",
}
})
app.ListenAndServe()
}
From version: 1.1.0-rc1
The example below will serve {"hello":"grameworld"}
from the struct. Gramework will register the bind
flag for you, that allows you to choose another ip/port that gramework should listen on:
package main
import (
"github.com/gramework/gramework"
)
type SomeResponse struct {
hello string
}
func main() {
app := gramework.New()
app.GET("/", func() interface{} {
return SomeResponse{
hello: "gramework",
}
})
app.ListenAndServe()
}
The example below will serve static files from ./files
:
package main
import (
"github.com/gramework/gramework"
)
func main() {
app := gramework.New()
app.GET("/*any", app.ServeDir("./files"))
app.ListenAndServe()
}
The example below will serve a byte slice:
package main
import (
"github.com/gramework/gramework"
)
func main() {
app := gramework.New()
app.GET("/*any", []byte("some data"))
app.ListenAndServe()
}
This example demonstrates:
- some ways of serving responses
- how to use preconfigured loggers etc.
package main
import (
"github.com/gramework/gramework"
)
type SomeData struct {
Name string
Age uint8
}
func main() {
app := gramework.New()
d := SomeData{
Name: "Grame",
Age: 20,
}
// service-wide CORS. you can also instead of using middleware
// call ctx.CORS() manually
app.Use(app.CORSMiddleware())
app.GET("/someJSON", func(ctx *gramework.Context) {
// send json, no metter if user asked for json, xml or anything else.
if err := ctx.JSON(d); err != nil {
// you can return err instead of manual checks and Err500() call.
// See next handler for example.
ctx.Err500()
}
})
app.GET("/simpleJSON", func(ctx *gramework.Context) error {
return ctx.JSON(d)
})
app.GET("/someData", func(ctx *gramework.Context) error {
// send data in one of supported encodings user asked for.
// Now we support json, xml and csv. More coming soon.
sentType, err := ctx.Encode(d)
if err != nil {
ctx.Logger.WithError(err).Error("could not process request")
return err
}
ctx.Logger.WithField("sentType", sentType).Debug("some request-related message")
return nil
})
// you can omit context if you want, return `interface{}`, `error` or both.
app.GET("/simplestJSON", func() interface{} {
return d
})
// you can also use one of built-in types as a handler, we got you covered too
app.GET("/hostnameJSON", fmt.Sprintf(`{"hostname": %q}`, os.Hostname()))
wait := make(chan struct{})
go func() {
time.Sleep(10 * time.Minute)
app.Shutdown()
wait <- struct{}{}
}()
app.ListenAndServe()
// allow Shutdown() to stop the app properly.
// ListenAndServe will return before Shutdown(), so we should wait.
<- wait
}
This example demonstrates how to migrate from fasthttp to gramework without rewriting your handlers.
package main
import (
"github.com/gramework/gramework"
)
func main() {
app := gramework.New()
app.GET("/someJSON", func(ctx *fasthttp.RequestCtx) {
ctx.WriteString("another data")
})
app.ListenAndServe()
}