Skip to content

Commit

Permalink
move the common components to the router package
Browse files Browse the repository at this point in the history
  • Loading branch information
kpacha committed Jan 17, 2018
1 parent 0f4fcf1 commit a7e9531
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 53 deletions.
16 changes: 8 additions & 8 deletions docs/BENCHMARKS.md
Expand Up @@ -151,14 +151,14 @@ Here you'll find some benchmarks of the different components of the KrakenD fram

## Gin

BenchmarkEndpointHandler_ko-8 1000000 5612 ns/op 3026 B/op 31 allocs/op
BenchmarkEndpointHandler_ok-8 1000000 6621 ns/op 3393 B/op 36 allocs/op
BenchmarkEndpointHandler_ko_Parallel-8 5000000 1650 ns/op 3028 B/op 31 allocs/op
BenchmarkEndpointHandler_ok_Parallel-8 5000000 2203 ns/op 3393 B/op 36 allocs/op
BenchmarkEndpointHandler_ko-8 1000000 5440 ns/op 3026 B/op 31 allocs/op
BenchmarkEndpointHandler_ok-8 1000000 6456 ns/op 3393 B/op 36 allocs/op
BenchmarkEndpointHandler_ko_Parallel-8 5000000 1534 ns/op 3028 B/op 31 allocs/op
BenchmarkEndpointHandler_ok_Parallel-8 5000000 1846 ns/op 3393 B/op 36 allocs/op

## Mux

BenchmarkEndpointHandler_ko-8 5000000 1444 ns/op 1088 B/op 13 allocs/op
BenchmarkEndpointHandler_ok-8 5000000 1449 ns/op 1088 B/op 13 allocs/op
BenchmarkEndpointHandler_ko_Parallel-8 20000000 485 ns/op 1088 B/op 13 allocs/op
BenchmarkEndpointHandler_ok_Parallel-8 20000000 541 ns/op 1088 B/op 13 allocs/op
BenchmarkEndpointHandler_ko-8 5000000 1815 ns/op 1088 B/op 13 allocs/op
BenchmarkEndpointHandler_ok-8 5000000 1693 ns/op 1088 B/op 13 allocs/op
BenchmarkEndpointHandler_ko_Parallel-8 20000000 558 ns/op 1088 B/op 13 allocs/op
BenchmarkEndpointHandler_ok_Parallel-8 20000000 597 ns/op 1088 B/op 13 allocs/op
28 changes: 11 additions & 17 deletions router/gin/endpoint.go
Expand Up @@ -2,7 +2,6 @@ package gin

import (
"context"
"errors"
"fmt"
"net/http"
"strings"
Expand All @@ -16,9 +15,6 @@ import (
"github.com/devopsfaith/krakend/router"
)

// ErrInternalError is the error returned by the router when something went wrong
var ErrInternalError = errors.New("internal server error")

// HandlerFactory creates a handler function that adapts the gin router with the injected proxy
type HandlerFactory func(*config.EndpointConfig, proxy.Proxy) gin.HandlerFunc

Expand All @@ -32,6 +28,7 @@ func CustomErrorEndpointHandler(configuration *config.EndpointConfig, proxy prox
endpointTimeout := time.Duration(configuration.Timeout) * time.Millisecond
cacheControlHeaderValue := fmt.Sprintf("public, max-age=%d", int(configuration.CacheTTL.Seconds()))
isCacheEnabled := configuration.CacheTTL.Seconds() != 0
emptyResponse := gin.H{}

return func(c *gin.Context) {
requestCtx, cancel := context.WithTimeout(c, endpointTimeout)
Expand All @@ -47,41 +44,38 @@ func CustomErrorEndpointHandler(configuration *config.EndpointConfig, proxy prox

select {
case <-requestCtx.Done():
c.AbortWithError(http.StatusInternalServerError, ErrInternalError)
c.AbortWithError(http.StatusInternalServerError, router.ErrInternalError)
cancel()
return
default:
}

if isCacheEnabled && response != nil && response.IsComplete {
c.Header("Cache-Control", cacheControlHeaderValue)
}

if response != nil {
c.JSON(http.StatusOK, response.Data)
} else {
c.JSON(http.StatusOK, gin.H{})
if response == nil {
c.JSON(http.StatusOK, emptyResponse)
cancel()
return
}
c.JSON(http.StatusOK, response.Data)
cancel()
}
}

var (
headersToSend = []string{"Content-Type"}
userAgentHeaderValue = []string{core.KrakendUserAgent}
)

// NewRequest gets a request from the current gin context and the received query string
func NewRequest(c *gin.Context, queryString []string) *proxy.Request {
params := make(map[string]string, len(c.Params))
for _, param := range c.Params {
params[strings.Title(param.Key)] = param.Value
}

headers := make(map[string][]string, 2+len(headersToSend))
headers := make(map[string][]string, 2+len(router.HeadersToSend))
headers["X-Forwarded-For"] = []string{c.ClientIP()}
headers["User-Agent"] = userAgentHeaderValue
headers["User-Agent"] = router.UserAgentHeaderValue

for _, k := range headersToSend {
for _, k := range router.HeadersToSend {
if h, ok := c.Request.Header[k]; ok {
headers[k] = h
}
Expand Down
2 changes: 1 addition & 1 deletion router/gin/endpoint_test.go
Expand Up @@ -50,7 +50,7 @@ func TestEndpointHandler_cancel(t *testing.T) {
time.Sleep(100 * time.Millisecond)
return nil, nil
}
testEndpointHandler(t, 0, p, "{}", "", "", http.StatusInternalServerError)
testEndpointHandler(t, 0, p, "", "", "", http.StatusInternalServerError)
}

func TestEndpointHandler_noop(t *testing.T) {
Expand Down
45 changes: 20 additions & 25 deletions router/mux/endpoint.go
Expand Up @@ -3,7 +3,6 @@ package mux
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"time"
Expand All @@ -14,9 +13,6 @@ import (
"github.com/devopsfaith/krakend/router"
)

// ErrInternalError is the error returned by the router when something went wrong
var ErrInternalError = errors.New("internal server error")

// HandlerFactory creates a handler function that adapts the mux router with the injected proxy
type HandlerFactory func(*config.EndpointConfig, proxy.Proxy) http.HandlerFunc

Expand All @@ -35,6 +31,7 @@ func CustomEndpointHandlerWithHTTPError(rb RequestBuilder, errF router.ToHTTPErr
endpointTimeout := time.Duration(configuration.Timeout) * time.Millisecond
cacheControlHeaderValue := fmt.Sprintf("public, max-age=%d", int(configuration.CacheTTL.Seconds()))
isCacheEnabled := configuration.CacheTTL.Seconds() != 0
emptyResponse := []byte("{}")

return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set(core.KrakendHeaderName, core.KrakendHeaderValue)
Expand All @@ -54,26 +51,29 @@ func CustomEndpointHandlerWithHTTPError(rb RequestBuilder, errF router.ToHTTPErr

select {
case <-requestCtx.Done():
http.Error(w, ErrInternalError.Error(), http.StatusInternalServerError)
http.Error(w, router.ErrInternalError.Error(), http.StatusInternalServerError)
cancel()
return
default:
}

var js []byte

if response != nil {
js, err = json.Marshal(response.Data)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
cancel()
return
}
if isCacheEnabled && response.IsComplete {
w.Header().Set("Cache-Control", cacheControlHeaderValue)
}
if response == nil {
w.Header().Set("Content-Type", "application/json")
w.Write(emptyResponse)
cancel()
return
}

js, err := json.Marshal(response.Data)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
cancel()
return
}

if isCacheEnabled && response.IsComplete {
w.Header().Set("Cache-Control", cacheControlHeaderValue)
}
w.Header().Set("Content-Type", "application/json")
w.Write(js)
cancel()
Expand All @@ -93,21 +93,16 @@ var NewRequest = NewRequestBuilder(func(_ *http.Request) map[string]string {
return map[string]string{}
})

var (
headersToSend = []string{"Content-Type"}
userAgentHeaderValue = []string{core.KrakendUserAgent}
)

// NewRequestBuilder gets a RequestBuilder with the received ParamExtractor as a query param
// extraction mecanism
func NewRequestBuilder(paramExtractor ParamExtractor) RequestBuilder {
return func(r *http.Request, queryString []string) *proxy.Request {
params := paramExtractor(r)
headers := make(map[string][]string, 2+len(headersToSend))
headers := make(map[string][]string, 2+len(router.HeadersToSend))
headers["X-Forwarded-For"] = []string{r.RemoteAddr}
headers["User-Agent"] = userAgentHeaderValue
headers["User-Agent"] = router.UserAgentHeaderValue

for _, k := range headersToSend {
for _, k := range router.HeadersToSend {
if h, ok := r.Header[k]; ok {
headers[k] = h
}
Expand Down
5 changes: 3 additions & 2 deletions router/mux/endpoint_test.go
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/devopsfaith/krakend/config"
"github.com/devopsfaith/krakend/proxy"
"github.com/devopsfaith/krakend/router"
)

func TestEndpointHandler_ok(t *testing.T) {
Expand Down Expand Up @@ -51,12 +52,12 @@ func TestEndpointHandler_cancel(t *testing.T) {
time.Sleep(100 * time.Millisecond)
return nil, nil
}
testEndpointHandler(t, 0, p, "GET", ErrInternalError.Error()+"\n", "", "text/plain; charset=utf-8", http.StatusInternalServerError)
testEndpointHandler(t, 0, p, "GET", router.ErrInternalError.Error()+"\n", "", "text/plain; charset=utf-8", http.StatusInternalServerError)
time.Sleep(5 * time.Millisecond)
}

func TestEndpointHandler_noop(t *testing.T) {
testEndpointHandler(t, 10, proxy.NoopProxy, "GET", "", "", "application/json", http.StatusOK)
testEndpointHandler(t, 10, proxy.NoopProxy, "GET", "{}", "", "application/json", http.StatusOK)
time.Sleep(5 * time.Millisecond)
}

Expand Down
11 changes: 11 additions & 0 deletions router/router.go
Expand Up @@ -3,9 +3,11 @@ package router

import (
"context"
"errors"
"net/http"

"github.com/devopsfaith/krakend/config"
"github.com/devopsfaith/krakend/core"
)

// Router sets up the public layer exposed to the users
Expand Down Expand Up @@ -34,3 +36,12 @@ type ToHTTPError func(error) int
func DefaultToHTTPError(_ error) int {
return http.StatusInternalServerError
}

var (
// HeadersToSend are the headers to pass from the router request to the proxy
HeadersToSend = []string{"Content-Type"}
// UserAgentHeaderValue is the value of the User-Agent header to add to the proxy request
UserAgentHeaderValue = []string{core.KrakendUserAgent}
// ErrInternalError is the error returned by the router when something went wrong
ErrInternalError = errors.New("internal server error")
)

0 comments on commit a7e9531

Please sign in to comment.