Skip to content

Commit

Permalink
Added ability to specify some middlewares
Browse files Browse the repository at this point in the history
  • Loading branch information
eko committed Jan 19, 2017
1 parent 20ffdc2 commit c583202
Show file tree
Hide file tree
Showing 9 changed files with 140 additions and 32 deletions.
18 changes: 18 additions & 0 deletions README.md
Expand Up @@ -115,6 +115,24 @@ Using the example given below, here is the request results:
<p>my post data</p>
```

Middlewares
-----------

You can add some middlewares in your application by the following way:

```go
app.Use(func(context gofast.Context, next gofast.MiddlewareFunc) gofast.Handler {
// Some code before calling the next middleware
handler := next(context, next)
// Some code after calling the next middleware

return handler
})
```

It allows you to access `context` (request, response, current route) and also
allows to define a new `handler` function to update the application behavior.

Default CORS headers
--------------------

Expand Down
15 changes: 13 additions & 2 deletions context.go
Expand Up @@ -11,6 +11,7 @@ import (
type Context struct {
request *Request
response *Response
route *Route
}

// Creates a new context component instance
Expand All @@ -19,8 +20,8 @@ func NewContext() Context {
}

// Sets a HTTP request instance
func (c *Context) SetRequest(req *http.Request, route Route) {
request := NewRequest(req, route)
func (c *Context) SetRequest(req *http.Request) {
request := NewRequest(req)
c.request = &request
}

Expand All @@ -29,6 +30,16 @@ func (c *Context) GetRequest() *Request {
return c.request
}

// Sets a route instance
func (c *Context) SetRoute(route *Route) {
c.route = route
}

// Returns a route instance
func (c *Context) GetRoute() *Route {
return c.route
}

// Sets a HTTP response instance
func (c *Context) SetResponse(res http.ResponseWriter) {
response := NewResponse(res)
Expand Down
10 changes: 7 additions & 3 deletions gofast.go
Expand Up @@ -21,6 +21,7 @@ const (
type Gofast struct {
*Router
*Templating
*Middleware
}

// Bootstraps a new instance
Expand All @@ -29,8 +30,9 @@ func Bootstrap() *Gofast {

router := NewRouter()
templating := NewTemplating()
middleware := NewMiddleware()

return &Gofast{&router, &templating}
return &Gofast{&router, &templating, &middleware}
}

// Listens and handles HTTP requests
Expand Down Expand Up @@ -76,10 +78,12 @@ func (g *Gofast) HandleRoute(res http.ResponseWriter, req *http.Request, route R
startTime := time.Now()

context := NewContext()
context.SetRequest(req, route)
context.SetRoute(&route)
context.SetRequest(req)
context.SetResponse(res)

route.handler(context)
handler := g.HandleMiddlewares(context)
handler(context)

stopTime := time.Now()

Expand Down
40 changes: 40 additions & 0 deletions middleware.go
@@ -0,0 +1,40 @@
// A fast web framework written in Go.
//
// Author: Vincent Composieux <vincent.composieux@gmail.com>

package gofast

type Middleware struct {
middlewares []MiddlewareFunc
}

type MiddlewareFunc func(context Context, middleware MiddlewareFunc) Handler

// Creates a new middleware component instance
func NewMiddleware() Middleware {
return Middleware{middlewares: make([]MiddlewareFunc, 0)}
}

// Adds a new middleware
func (m *Middleware) Use(middleware MiddlewareFunc) {
m.middlewares = append(m.middlewares, middleware)
}

// Handle middlewares and returns handler
func (m *Middleware) HandleMiddlewares(context Context) Handler {
m.Use(func(context Context, next MiddlewareFunc) Handler {
return context.GetRoute().GetHandler()
})

handler := context.GetRoute().GetHandler()

for i := 0; i < len(m.middlewares)-1; i++ {
middleware := m.middlewares[i]
next := m.middlewares[i+1]

handler = middleware(context, next)
context.GetRoute().SetHandler(handler)
}

return handler
}
34 changes: 34 additions & 0 deletions middleware_test.go
@@ -0,0 +1,34 @@
// A fast web framework written in Go.
//
// Author: Vincent Composieux <vincent.composieux@gmail.com>

package gofast

import (
"testing"
)

// Tests initializing a new middleware component
func TestMiddleware(t *testing.T) {
middleware := NewMiddleware()

if len(middleware.middlewares) > 0 {
t.Fail()
}
}

// Tests adding a new middlewares
func TestUseNewMiddlewares(t *testing.T) {
middleware := NewMiddleware()
middleware.Use(func(context Context, next MiddlewareFunc) Handler {
return next(context, next)
})

middleware.Use(func(context Context, next MiddlewareFunc) Handler {
return next(context, next)
})

if len(middleware.middlewares) < 2 {
t.Fail()
}
}
10 changes: 2 additions & 8 deletions request.go
Expand Up @@ -10,7 +10,6 @@ import (

type Request struct {
httpRequest *http.Request
route *Route
parameters []Parameter
}

Expand All @@ -20,22 +19,17 @@ type Parameter struct {
}

// Creates a new Request component instance
func NewRequest(req *http.Request, route Route) Request {
func NewRequest(req *http.Request) Request {
req.ParseForm()

return Request{req, &route, make([]Parameter, 0)}
return Request{req, make([]Parameter, 0)}
}

// Returs HTTP request
func (r *Request) GetHttpRequest() *http.Request {
return r.httpRequest
}

// Returns current route
func (r *Request) GetRoute() *Route {
return r.route
}

// Adds a request parameter
func (r *Request) AddParameter(name string, value interface{}) {
r.parameters = append(r.parameters, Parameter{name, value})
Expand Down
21 changes: 2 additions & 19 deletions request_test.go
Expand Up @@ -6,28 +6,13 @@ package gofast

import (
"net/http"
"regexp"
"testing"
)

// Tests setting and retrieving current route
func TestRoute(t *testing.T) {
httpRequest := new(http.Request)
route := Route{"GET", "test", regexp.MustCompile("/test"), func(c Context) {}}

request := NewRequest(httpRequest, route)

if request.GetRoute().name != "test" {
t.Fail()
}
}

// Tests setting and retrieving request parameters
func TestParameters(t *testing.T) {
httpRequest := new(http.Request)
route := Route{"GET", "test", regexp.MustCompile("/test"), func(c Context) {}}

request := NewRequest(httpRequest, route)
request := NewRequest(httpRequest)

request.AddParameter("test1", "value1")
request.AddParameter("test2", "value2")
Expand All @@ -46,9 +31,7 @@ func TestGetHeader(t *testing.T) {
httpRequest, _ := http.NewRequest("GET", "/", nil)
httpRequest.Header.Set("X-Test-Header", "yes")

route := Route{"GET", "test", regexp.MustCompile("/test"), func(c Context) {}}

request := NewRequest(httpRequest, route)
request := NewRequest(httpRequest)

if request.GetHeader("X-Test-Header") != "yes" {
t.Fail()
Expand Down
10 changes: 10 additions & 0 deletions router.go
Expand Up @@ -100,6 +100,16 @@ func (r *Route) GetPattern() *regexp.Regexp {
return r.pattern
}

// Sets a route handler
func (r *Route) SetHandler(handler Handler) {
r.handler = handler
}

// Returns a route handler
func (r *Route) GetHandler() Handler {
return r.handler
}

// Route sort functions
func (this RouteLen) Len() int {
return len(this)
Expand Down
14 changes: 14 additions & 0 deletions router_test.go
Expand Up @@ -72,3 +72,17 @@ func TestFallbackRoute(t *testing.T) {
t.Fail()
}
}

// Tests route handling getter
func TestRouteGetHandler(t *testing.T) {
handler := func(c Context) {}

router := NewRouter()
router.Get("get", "/get", handler)

route := router.GetRoute("get")

if route.GetHandler() == nil {
t.Fail()
}
}

0 comments on commit c583202

Please sign in to comment.