Skip to content
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

Improve routing #64

Merged
merged 11 commits into from
Jul 26, 2020
Merged
Show file tree
Hide file tree
Changes from 6 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/test_and_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:

- name: Build
run: go build

- name: Lint
run: golint -set_exit_status ./...

Expand Down
45 changes: 15 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,13 @@
</p>


**gearbox** :gear: is a web framework for building micro services written in Go with a focus on high performance and memory optimization.
**gearbox** :gear: is a web framework for building micro services written in Go with a focus on high performance and memory optimization. It's built on [fasthttp](https://github.com/valyala/fasthttp) which is **up to 10x faster** than net/http

Currently, **gearbox** :gear: is **under development (not production ready)** and built on [fasthttp](https://github.com/valyala/fasthttp) which is **up to 10x faster** than net/http

In **gearbox**, we care about peformance and memory which will be used by each method while building things up and how we can improve that. It also takes more time to **research** about each component that will be used and **compare** it with different implementations of other open source web frameworks. It may end up writing our **own components** in an optimized way to achieve our goals

### gearbox seeks to be
+ Secure :closed_lock_with_key:
+ Fast :rocket:
+ Simple :eyeglasses:
+ Easy to use
+ Easy to use :eyeglasses:
+ Lightweight


Expand Down Expand Up @@ -58,8 +54,8 @@ func main() {
gb := gearbox.New()

// Define your handlers
gb.Get("/hello", func(ctx *gearbox.Context) {
ctx.RequestCtx.Response.SetBodyString("Hello World!")
gb.Get("/hello", func(ctx gearbox.Context) {
ctx.SendString("Hello World!")
})

// Start service
Expand All @@ -80,18 +76,8 @@ func main() {
gb := gearbox.New()

// Handler with parameter
gb.Get("/users/:user", func(ctx *gearbox.Context) {
fmt.Printf("%s\n", ctx.Params["user"])
})

// Handler with optional parameter
gb.Get("/search/:pattern?", func(ctx *gearbox.Context) {
fmt.Printf("%s\n", ctx.Params["pattern"])
})

// Handler with regex parameter
gb.Get("/book/:name:([a-z]+[0-3])", func(ctx *gearbox.Context) {
fmt.Printf("%s\n", ctx.Params["name"])
gb.Get("/users/:user", func(ctx gearbox.Context) {
fmt.Printf("%s\n", ctx.Param("user"))
})

// Start service
Expand All @@ -113,32 +99,31 @@ func main() {
gb := gearbox.New()

// create a logger middleware
logMiddleware := func(ctx *gearbox.Context) {
log.Printf(ctx.RequestCtx.String())
logMiddleware := func(ctx gearbox.Context) {
log.Printf("log message!")
ctx.Next() // Next is what allows the request to continue to the next middleware/handler
}

// create an unauthorized middleware
unAuthorizedMiddleware := func(ctx *gearbox.Context) {
ctx.RequestCtx.SetStatusCode(401) // unauthorized status code
ctx.RequestCtx.Response.SetBodyString("You are unauthorized to access this page!")
unAuthorizedMiddleware := func(ctx gearbox.Context) {
ctx.Status(gearbox.StatusUnauthorized).SendString("You are unauthorized to access this page!")
}

// Register the log middleware for all requests
gb.Use(logMiddleware)

// Define your handlers
gb.Get("/hello", func(ctx *gearbox.Context) {
ctx.RequestCtx.Response.SetBodyString("Hello World!")
gb.Get("/hello", func(ctx gearbox.Context) {
ctx.SendString("Hello World!")
})

// Register the routes to be used when grouping routes
routes := []*gearbox.Route {
gb.Get("/id", func(ctx *gearbox.Context) {
ctx.RequestCtx.Response.SetBodyString("User X")
ctx.SendString("User X")
}),
gb.Delete("/id", func(ctx *gearbox.Context) {
ctx.RequestCtx.Response.SetBodyString("Deleted")
ctx.SendString("Deleted")
})
}

Expand All @@ -151,7 +136,7 @@ func main() {
// Define a route with unAuthorizedMiddleware as the middleware
// you can define as many middlewares as you want and have the handler as the last argument
gb.Get("/protected", unAuthorizedMiddleware, func(ctx *gearbox.Context) {
ctx.RequestCtx.Response.SetBodyString("You accessed a protected page")
ctx.SendString("You accessed a protected page")
})

// Start service
Expand Down
85 changes: 0 additions & 85 deletions cache.go

This file was deleted.

42 changes: 0 additions & 42 deletions cache_test.go

This file was deleted.

73 changes: 65 additions & 8 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,80 @@ import (
"github.com/valyala/fasthttp"
)

// Context interface
type Context interface {
Next()
Context() *fasthttp.RequestCtx
Param(key string) string
Query(key string) string
SendString(value string) Context
Status(status int) Context
Set(key string, value string)
Get(key string) string
Body() string
}

// handlerFunc defines the handler used by middleware as return value.
type handlerFunc func(ctx *Context)
type handlerFunc func(ctx Context)

// handlersChain defines a handlerFunc array.
type handlersChain []handlerFunc

// Context defines the current context of request and handlers/middlewares to execute
type Context struct {
RequestCtx *fasthttp.RequestCtx
Params map[string]string
handlers handlersChain
index int
type context struct {
requestCtx *fasthttp.RequestCtx
paramValues map[string]string
handlers handlersChain
index int
}

// Next function is used to successfully pass from current middleware to next middleware.
// if the middleware thinks it's okay to pass it.
func (ctx *Context) Next() {
func (ctx *context) Next() {
ctx.index++
ctx.handlers[ctx.index](ctx)
if ctx.index < len(ctx.handlers) {
ctx.handlers[ctx.index](ctx)
}
}

func (ctx *context) Param(key string) string {
return ctx.paramValues[key]
}

func (ctx *context) Context() *fasthttp.RequestCtx {
return ctx.requestCtx
}

// SendString sends trinsdf
func (ctx *context) SendString(value string) Context {
ctx.requestCtx.SetBodyString(value)
return ctx
}

// Status sets the HTTP status code and if the response body is empty,
// it sets the correct status message in the body.
func (ctx *context) Status(status int) Context {
ctx.requestCtx.Response.SetStatusCode(status)
return ctx
}

// Get returns the HTTP request header specified by field.

func (ctx *context) Get(key string) string {
return GetString(ctx.requestCtx.Request.Header.Peek(key))
}

// Set sets the response's HTTP header field to the specified key, value.
func (ctx *context) Set(key, value string) {
ctx.requestCtx.Response.Header.Set(key, value)
}

// Query returns the query string parameter in the url.
func (ctx *context) Query(key string) string {
return GetString(ctx.requestCtx.QueryArgs().Peek(key))
}

// Body contains the raw body submitted in a POST request.
func (ctx *context) Body() string {
return GetString(ctx.requestCtx.Request.Body())
}
6 changes: 2 additions & 4 deletions context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

// Test passing the request from middleware to handler
func Test_Next(t *testing.T) {
func TestNext(t *testing.T) {
// testing routes
routes := []struct {
path string
Expand All @@ -17,9 +17,7 @@ func Test_Next(t *testing.T) {
}

// get instance of gearbox
gb := new(gearbox)
gb.registeredRoutes = make([]*Route, 0)
gb.settings = &Settings{}
gb := setupGearbox()

// register routes according to method
for _, r := range routes {
Expand Down
Loading