skhatri/api-router-go

View on GitHub
router/server.go

Summary

Maintainability
A
0 mins
Test Coverage
package router

import (
    "encoding/json"
    "github.com/skhatri/api-router-go/router/model"
    "github.com/skhatri/api-router-go/router/settings"
    "io/ioutil"
    "net/http"
    "strings"
    "time"
)

type httpRouter struct {
    router  *HttpRouterConfiguration
    options *HttpRouterOptions
}
type RequestSummary struct {
    Method    string `json:"method"`
    Uri       string `json:"uri"`
    TimeTaken int    `json:"time_taken"`
    Unit      string `json:"unit"`
    Status    int    `json:"status_code"`
}

//ServeHTTP http interface method
func (hs *httpRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    start := time.Now()
    requestUri := r.URL.Path
    handlerFunc, pathParams := hs.router.delegate.getHandler(r.Method, requestUri)
    if handlerFunc == nil {
        notFound(&WebRequest{Uri: r.RequestURI})
        return
    }
    var requestData []byte = nil
    if r.Body != nil {
        defer r.Body.Close()
        body, err := ioutil.ReadAll(r.Body)
        if err != nil {
            render(w, badRequest())
            return
        }
        requestData = body
    }
    var headers = make(map[string]string)
    for name, value := range r.Header {
        headers[name] = strings.Join(value, ";")
    }
    var params = make(map[string]string)

    for name, value := range r.URL.Query() {
        params[name] = strings.Join(value, ";")
    }

    webRequest := &WebRequest{
        Uri:         requestUri,
        Body:        requestData,
        Headers:     headers,
        QueryParams: params,
        QueryString: r.URL.RawQuery,
        PathParams:  pathParams,
    }

    status := render(w, handlerFunc(webRequest))
    if hs.options.LogRequest {
        timeTaken := time.Since(start).Milliseconds()
        hs.options.LogFunction(RequestSummary{
            Method:    r.Method,
            Uri:       r.RequestURI,
            TimeTaken: int(timeTaken),
            Unit:      "ms",
            Status:    status,
        })
    }
}

func render(w http.ResponseWriter, container *model.Container) int {
    status := container.GetStatus()
    if status == 0 {
        status = 200
    }
    for k, v := range settings.GetSettings().ResponseHeaders() {
        w.Header().Add(k, v)
    }
    for k, v := range container.GetHeaders() {
        w.Header().Add(k, v)
    }
    w.WriteHeader(status)

    encoder := json.NewEncoder(w)
    if container.IsDecorated() {
        encoder.Encode(container)
    } else if status <= 400 {
        encoder.Encode(container.Data)
    } else {
        encoder.Encode(container.Errors)
    }
    return status
}

func Bind(httpRouter *httpRouter, hostPort string) {
    http.ListenAndServe(hostPort, httpRouter)
}