Skip to content

Commit

Permalink
add fast http settings (#38)
Browse files Browse the repository at this point in the history
* add fast http settings

* fix default settings

* fix cache set

* fix cache set

* fix default settings

* Removed not need if check

* caching setting

* Moved cacheKey up because it won't compile if under if

* caching setting

Co-authored-by: Nagy Salem <me@muhnagy.com>
  • Loading branch information
abahmed and muhammednagy committed Jun 14, 2020
1 parent c9f2fad commit cbbfe32
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 25 deletions.
5 changes: 5 additions & 0 deletions cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ type pair struct {

// newCache returns LRU cache
func newCache(capacity int) cache {
// minimum is 1
if capacity <= 0 {
capacity = 1
}

return &lruCache{
capacity: capacity,
list: new(list.List),
Expand Down
4 changes: 4 additions & 0 deletions cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@ func ExampleCache() {
cache.Set([]byte("user5"), 5)
fmt.Println(cache.Get([]byte("user3")))

cache2 := newCache(0)
cache2.Set([]byte("user1"), 1)
fmt.Println(cache2.Get([]byte("user1")).(int))
// Output:
// 1
// 2
// 3
// <nil>
// 2
// <nil>
// 1
}
94 changes: 78 additions & 16 deletions gearbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import (
"fmt"
"log"
"net"
"time"

"github.com/valyala/fasthttp"
)

// Exported constants
const (
Version = "0.0.3-beta" // Version of gearbox
Name = "Gearbox" // Name of gearbox
Version = "1.0.0" // Version of gearbox
Name = "Gearbox" // Name of gearbox
// http://patorjk.com/software/taag/#p=display&f=Big%20Money-ne&t=Gearbox
banner = `
/$$$$$$ /$$
Expand All @@ -28,7 +29,14 @@ Listening on %s
)

const (
cacheSizeDefault = 1000 // default number of entries that can cache hold
// defaultCacheSize is number of entries that can cache hold
defaultCacheSize = 1000

// defaultConcurrency is the maximum number of concurrent connections
defaultConcurrency = 256 * 1024

// defaultMaxRequestBodySize is the maximum request body size the server
defaultMaxRequestBodySize = 4 * 1024 * 1024
)

// HTTP methods were copied from net/http.
Expand Down Expand Up @@ -145,9 +153,47 @@ type gearbox struct {

// Settings struct holds server settings
type Settings struct {
CaseSensitive bool // default false
// Enable case sensitive routing
CaseSensitive bool // default false

// Maximum size of LRU cache that will be used in routing if it's enabled
CacheSize int // default 1000

// ServerName for sending in response headers
ServerName string // default ""

// Maximum request body size
MaxRequestBodySize int // default 4 * 1024 * 1024

// Maximum number of concurrent connections
Concurrency int // default 256 * 1024

// LRU caching used to speed up routing
DisableCaching bool // default false

// Disable printing gearbox banner
DisableStartupMessage bool // default false
CacheSize int // default 1000

// Disable keep-alive connections, the server will close incoming connections after sending the first response to client
DisableKeepalive bool // default false

// When set to true causes the default date header to be excluded from the response
DisableDefaultDate bool // default false

// When set to true, causes the default Content-Type header to be excluded from the Response
DisableDefaultContentType bool // default false

// By default all header names are normalized: conteNT-tYPE -> Content-Type
DisableHeaderNormalizing bool // default false

// The amount of time allowed to read the full request including body
ReadTimeout time.Duration // default unlimited

// The maximum duration before timing out writes of the response
WriteTimeout time.Duration // default unlimited

// The maximum amount of time to wait for the next request when keep-alive is enabled
IdleTimeout time.Duration // default unlimited
}

// Route struct which holds each route info
Expand All @@ -161,23 +207,29 @@ type Route struct {
func New(settings ...*Settings) Gearbox {
gb := new(gearbox)
gb.registeredRoutes = make([]*Route, 0)
gb.httpServer = gb.newHTTPServer()

if len(settings) > 0 {
populateSettings(settings[0])
gb.settings = settings[0]
} else {
gb.settings = &Settings{}
}

return gb
}
// set default settings for settings that don't have values set
if gb.settings.CacheSize <= 0 {
gb.settings.CacheSize = defaultCacheSize
}

// populateSettings sets default settings for settings that don't have values set
func populateSettings(settings *Settings) {
if settings.CacheSize == 0 {
settings.CacheSize = cacheSizeDefault
if gb.settings.MaxRequestBodySize <= 0 {
gb.settings.MaxRequestBodySize = defaultMaxRequestBodySize
}

if gb.settings.Concurrency <= 0 {
gb.settings.Concurrency = defaultConcurrency
}

gb.httpServer = gb.newHTTPServer()

return gb
}

// Start handling requests
Expand Down Expand Up @@ -211,9 +263,19 @@ func (dl *customLogger) Printf(format string, args ...interface{}) {
// newHTTPServer returns a new instance of fasthttp server
func (gb *gearbox) newHTTPServer() *fasthttp.Server {
return &fasthttp.Server{
Handler: gb.handler,
Logger: &customLogger{},
LogAllErrors: false,
Handler: gb.handler,
Logger: &customLogger{},
LogAllErrors: false,
Name: gb.settings.ServerName,
Concurrency: gb.settings.Concurrency,
NoDefaultDate: gb.settings.DisableDefaultDate,
NoDefaultContentType: gb.settings.DisableDefaultContentType,
DisableHeaderNamesNormalizing: gb.settings.DisableHeaderNormalizing,
DisableKeepalive: gb.settings.DisableKeepalive,
NoDefaultServerHeader: gb.settings.ServerName == "",
ReadTimeout: gb.settings.ReadTimeout,
WriteTimeout: gb.settings.WriteTimeout,
IdleTimeout: gb.settings.IdleTimeout,
}
}

Expand Down
2 changes: 1 addition & 1 deletion gearbox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func (c *fakeConn) Write(b []byte) (int, error) {

// startGearbox constructs routing tree and creates server
func startGearbox(gb *gearbox) {
gb.cache = newCache(cacheSizeDefault)
gb.cache = newCache(defaultCacheSize)
gb.constructRoutingTree()
gb.httpServer = &fasthttp.Server{
Handler: gb.handler,
Expand Down
19 changes: 12 additions & 7 deletions router.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,10 +399,13 @@ func (gb *gearbox) matchRouteAgainstRegistered(method, path []byte) (handlersCha

trimmedPath := trimPath(path)

// Try to get from cache
cacheKey := append(method, trimmedPath...)
if cacheResult, ok := gb.cache.Get(cacheKey).(*matchParamsResult); ok {
return cacheResult.Handlers, cacheResult.Params
// Try to get from cache if it's enabled
cacheKey := ""
if !gb.settings.DisableCaching {
cacheKey := append(method, trimmedPath...)
if cacheResult, ok := gb.cache.Get(cacheKey).(*matchParamsResult); ok {
return cacheResult.Handlers, cacheResult.Params
}
}

paths := bytes.Split(trimmedPath, []byte("/"))
Expand Down Expand Up @@ -439,9 +442,11 @@ func (gb *gearbox) matchRouteAgainstRegistered(method, path []byte) (handlersCha
// Return longest prefix match
for i := lastMatchedNodesIndex - 1; i >= 0; i-- {
if lastMatchedNodes[i].Matched {
go func(key []byte, matchResult *matchParamsResult) {
gb.cache.Set(key, matchResult)
}(append(make([]byte, 0, len(cacheKey)), cacheKey...), lastMatchedNodes[i])
if !gb.settings.DisableCaching {
go func(key []byte, matchResult *matchParamsResult) {
gb.cache.Set(key, matchResult)
}(append(make([]byte, 0, len(cacheKey)), cacheKey...), lastMatchedNodes[i])
}

return lastMatchedNodes[i].Handlers, lastMatchedNodes[i].Params
}
Expand Down
2 changes: 1 addition & 1 deletion router_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func setupGearbox(settings ...*Settings) *gearbox {
gb.settings = &Settings{}
}

gb.cache = newCache(cacheSizeDefault)
gb.cache = newCache(defaultCacheSize)
return gb
}

Expand Down

0 comments on commit cbbfe32

Please sign in to comment.