Skip to content

Refactor init and add compression support. #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/go-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
test:
strategy:
matrix:
go: ["1.21", "1.20", "1.18", "1.19"]
go: ["1.21"]

runs-on: ubuntu-20.04

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ write HTTP servers. It enables:
## Install

```bash
go get -u github.com/zerodha/fastglue
go get -u github.com/zerodha/fastglue/v2
```

## Usage

```go
import "github.com/zerodha/fastglue"
import "github.com/zerodha/fastglue/v2"
```

## Examples
Expand Down
4 changes: 2 additions & 2 deletions custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ type Envelope struct {

// NewGlue creates and returns a new instance of Fastglue with custom error
// handlers pre-bound.
func NewGlue() *Fastglue {
f := New()
func NewGlue(o Options) *Fastglue {
f := New(o)
f.Router.MethodNotAllowed = BadMethodHandler
f.Router.NotFound = NotFoundHandler
f.Router.SaveMatchedRoutePath = true
Expand Down
4 changes: 2 additions & 2 deletions examples/before-after/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"time"

"github.com/valyala/fasthttp"
"github.com/zerodha/fastglue"
"github.com/zerodha/fastglue/v2"
)

var (
Expand All @@ -18,7 +18,7 @@ var (
func main() {
flag.Parse()

g := fastglue.New()
g := fastglue.New(fastglue.Options{})
g.Before(setTime)
g.After(calculateTime)
g.GET("/", handleIndex)
Expand Down
4 changes: 2 additions & 2 deletions examples/decode/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"time"

"github.com/valyala/fasthttp"
"github.com/zerodha/fastglue"
"github.com/zerodha/fastglue/v2"
)

var (
Expand All @@ -17,7 +17,7 @@ var (
func main() {
flag.Parse()

g := fastglue.New()
g := fastglue.New(fastglue.Options{})
g.GET("/", handleIndex)

s := &fasthttp.Server{
Expand Down
4 changes: 2 additions & 2 deletions examples/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"time"

"github.com/valyala/fasthttp"
"github.com/zerodha/fastglue"
"github.com/zerodha/fastglue/v2"
)

// App is the global config "context" that'll be injected into every Request.
Expand Down Expand Up @@ -77,7 +77,7 @@ func myRedirectHandler(r *fastglue.Request) error {
}

func main() {
f := fastglue.NewGlue()
f := fastglue.NewGlue(fastglue.Options{})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New vs New Glue, its confusing can be deprecated?

f.SetContext(&App{version: "v3.0.0"})
// f.Before(checkToken)

Expand Down
4 changes: 2 additions & 2 deletions examples/graceful/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"time"

"github.com/valyala/fasthttp"
"github.com/zerodha/fastglue"
"github.com/zerodha/fastglue/v2"
)

var (
Expand All @@ -19,7 +19,7 @@ var (
func main() {
flag.Parse()

g := fastglue.New()
g := fastglue.New(fastglue.Options{})
g.ServeStatic("/{filepath:*}", ".", true)

s := &fasthttp.Server{
Expand Down
4 changes: 2 additions & 2 deletions examples/helloworld/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"time"

"github.com/valyala/fasthttp"
"github.com/zerodha/fastglue"
"github.com/zerodha/fastglue/v2"
)

var (
Expand All @@ -17,7 +17,7 @@ var (
func main() {
flag.Parse()

g := fastglue.New()
g := fastglue.New(fastglue.Options{})
g.GET("/", handleHelloWorld)

s := &fasthttp.Server{
Expand Down
4 changes: 2 additions & 2 deletions examples/middleware/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"time"

"github.com/valyala/fasthttp"
"github.com/zerodha/fastglue"
"github.com/zerodha/fastglue/v2"
)

var (
Expand All @@ -19,7 +19,7 @@ var (
func main() {
flag.Parse()

g := fastglue.New()
g := fastglue.New(fastglue.Options{})
g.GET("/", auth(validateAll(handleGetAll)))
g.PUT("/", auth(fastglue.ReqLenParams(validate(handleMiddleware), map[string]int{"a": 5, "b": 5})))
g.POST("/", auth(fastglue.ReqParams(validate(handleMiddleware), []string{"a", "b"})))
Expand Down
4 changes: 2 additions & 2 deletions examples/path/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"time"

"github.com/valyala/fasthttp"
"github.com/zerodha/fastglue"
"github.com/zerodha/fastglue/v2"
)

var (
Expand All @@ -18,7 +18,7 @@ var (
func main() {
flag.Parse()

g := fastglue.New()
g := fastglue.New(fastglue.Options{})
g.GET("/", handleIndex)
g.GET("/{name:^[a-zA-Z]+$}", handleIndex)

Expand Down
4 changes: 2 additions & 2 deletions examples/singleton/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"time"

"github.com/valyala/fasthttp"
"github.com/zerodha/fastglue"
"github.com/zerodha/fastglue/v2"
)

var (
Expand All @@ -29,7 +29,7 @@ func main() {
log: log.New(os.Stdout, "SINGLETON", log.Llongfile),
}

g := fastglue.New()
g := fastglue.New(fastglue.Options{})
g.SetContext(app)
g.GET("/", handleIndex)

Expand Down
4 changes: 2 additions & 2 deletions examples/static-file/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"time"

"github.com/valyala/fasthttp"
"github.com/zerodha/fastglue"
"github.com/zerodha/fastglue/v2"
)

var (
Expand All @@ -16,7 +16,7 @@ var (
func main() {
flag.Parse()

g := fastglue.New()
g := fastglue.New(fastglue.Options{})
g.ServeStatic("/{filepath:*}", ".", true)

s := &fasthttp.Server{
Expand Down
82 changes: 76 additions & 6 deletions fastglue.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ var (
authToken = []byte("token")
)

// CompressionType is the type of otuput compression available in fasthttp
// for the response body.
type CompressionType string

const (
CompressionZstd CompressionType = "zstd"
CompressionBr CompressionType = "br"
CompressionGzip CompressionType = "gzip"
CompressionDeflate CompressionType = "deflate"
)

// FastRequestHandler is the fastglue HTTP request handler function
// that wraps over the fasthttp handler.
type FastRequestHandler func(*Request) error
Expand All @@ -53,21 +64,52 @@ type Request struct {
Context interface{}
}

// CompressionOpt is the configuration for enabling and controlling compression.
// Enabling this will automatically compress the response based on the client's
// Accept-Encoding header by internally invoking fasthttp.CompressHandler()
// gzip|deflate|br|zstd are the supported compression types.
type CompressionOpt struct {
Enabled bool

// Type of compression to support (std, gzip, deflate, br). If no type is specified
// then fasthttp's default compression types and its internal order of priority are used.
//
// Important: The first type in the list is the preferred type
// irrespective of the ordering of types in the incoming client's Accept-Encoding header.
// That is because fasthttp's CompressHandler() internally uses arbitrary
// type ordering to compress the response. fastglue thus overrides the
// Accept-Encoding header to only have the first type in this list.
// For instance, if the list here is [zstd, br], and the incoming header is
// [gzip, deflate, br, zstd], fastglue will overwrite the header to [zstd],
// forcing fasthttp to compress the response using the preferred type here.
Types []CompressionType
}

// Fastglue is the "glue" wrapper over fasthttp and fasthttprouter.
type Fastglue struct {
Router *fasthttprouter.Router
Server *fasthttp.Server
context interface{}
MatchedRoutePathParam string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MatchedRoutePathParam

This is setup in NewGlue in custom.go, maybe it can be an opt since currently we depend on NewGlue()

fastglue.NewGlue() <- Deprecate this since we are doing a v2?

before []FastMiddleware
after []FastMiddleware

context interface{}
before []FastMiddleware
after []FastMiddleware

opt Options
}

type Options struct {
CompressionOpt CompressionOpt
}

// New creates and returns a new instance of Fastglue.
func New() *Fastglue {
return &Fastglue{
func New(o Options) *Fastglue {
f := &Fastglue{
Router: fasthttprouter.New(),
opt: o,
}

return f
}

// ListenAndServe is a wrapper for fasthttp.ListenAndServe. It takes a TCP address,
Expand Down Expand Up @@ -150,7 +192,7 @@ func (f *Fastglue) Shutdown(s *fasthttp.Server, shutdownComplete chan error) {
// handler is the "proxy" abstraction that converts a fastglue handler into
// a fasthttp handler and passes execution in and out.
func (f *Fastglue) handler(h FastRequestHandler) func(*fasthttp.RequestCtx) {
return func(ctx *fasthttp.RequestCtx) {
handler := func(ctx *fasthttp.RequestCtx) {
req := &Request{
RequestCtx: ctx,
Context: f.context,
Expand All @@ -172,7 +214,35 @@ func (f *Fastglue) handler(h FastRequestHandler) func(*fasthttp.RequestCtx) {
}
}

// If compression is enabled, override the response header to
// the preferred type in the config.
if f.opt.CompressionOpt.Enabled {
for _, typ := range f.opt.CompressionOpt.Types {
t := string(typ)
// If the preferred type is in the client's Accept-Encoding header,
// overwrite the request header to only have this type, forcing
// fasthttp.CompressHandler() to compress the response using it.
// This is because fasthttp internally does not respect the order
// in the client header and uses arbitrary ordering to compress the response.
if ctx.Request.Header.HasAcceptEncoding(t) {
ctx.Request.Header.Set("Accept-Encoding", t)
break
}
}
}
}

// If compression is enabled, wrap the handler with fasthttp's CompressHandler
// which automatically handles the compression logic.
if f.opt.CompressionOpt.Enabled {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can rename this to opt.Compression? Type name can remain CompressionOpt.

// fasthttp's compression handlers are pretty bad. This particular handler
// is the one that supports gzip|br|zstd|deflate.
return fasthttp.CompressHandlerBrotliLevel(handler,
fasthttp.CompressBrotliDefaultCompression,
fasthttp.CompressDefaultCompression)
}

return handler
}

// Handler returns fastglue's central fasthttp handler that can be registered
Expand Down
Loading