Skip to content

Commit

Permalink
improve root middleware gql & rest server
Browse files Browse the repository at this point in the history
  • Loading branch information
agungdwiprasetyo committed Mar 17, 2023
1 parent 719cf20 commit ce53ad1
Show file tree
Hide file tree
Showing 11 changed files with 86 additions and 71 deletions.
38 changes: 0 additions & 38 deletions candishared/http_handler.go

This file was deleted.

6 changes: 4 additions & 2 deletions codebase/app/graphql_server/graphql_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/golangid/candi/codebase/factory/types"
"github.com/golangid/candi/logger"
"github.com/golangid/candi/tracer"
"github.com/golangid/candi/wrapper"

graphql "github.com/golangid/graphql-go"
gqltypes "github.com/golangid/graphql-go/types"
Expand All @@ -44,6 +45,7 @@ func NewServer(service factory.ServiceFactory, opts ...OptionFunc) factory.AppSe
httpEngine := new(http.Server)
server := &graphqlServer{
httpEngine: httpEngine,
opt: getDefaultOption(),
}
for _, opt := range opts {
opt(&server.opt)
Expand All @@ -53,7 +55,7 @@ func NewServer(service factory.ServiceFactory, opts ...OptionFunc) factory.AppSe

mux := http.NewServeMux()
mux.Handle("/", server.opt.rootHandler)
mux.HandleFunc("/memstats", candishared.HTTPMemstatsHandler)
mux.Handle("/memstats", service.GetDependency().GetMiddleware().HTTPBasicAuth(http.HandlerFunc(wrapper.HTTPHandlerMemstats)))
mux.HandleFunc(server.opt.rootPath+rootGraphQLPath, httpHandler.ServeGraphQL())
mux.HandleFunc(server.opt.rootPath+rootGraphQLPlayground, httpHandler.ServePlayground)
mux.HandleFunc(server.opt.rootPath+rootGraphQLVoyager, httpHandler.ServeVoyager)
Expand All @@ -67,7 +69,7 @@ func NewServer(service factory.ServiceFactory, opts ...OptionFunc) factory.AppSe
fmt.Printf("\x1b[34;1m⇨ GraphQL HTTP server run at port [::]%s\x1b[0m\n\n", httpEngine.Addr)

if server.opt.sharedListener != nil {
server.listener = server.opt.sharedListener.Match(cmux.HTTP1Fast())
server.listener = server.opt.sharedListener.Match(cmux.HTTP1Fast(http.MethodPatch))
}

return server
Expand Down
11 changes: 5 additions & 6 deletions codebase/app/graphql_server/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"net/http"

"github.com/golangid/candi/wrapper"
"github.com/golangid/graphql-go/types"
"github.com/soheilhy/cmux"
)
Expand All @@ -29,12 +30,10 @@ type (

func getDefaultOption() Option {
return Option{
httpPort: ":8000",
rootPath: "",
debugMode: true,
rootHandler: http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rw.Write([]byte("REST Server up and running"))
}),
httpPort: ":8000",
rootPath: "",
debugMode: true,
rootHandler: http.HandlerFunc(wrapper.HTTPHandlerDefaultRoot),
}
}

Expand Down
4 changes: 3 additions & 1 deletion codebase/app/graphql_server/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ func (t *graphqlTracer) TraceQuery(ctx context.Context, queryString string, oper

trace, ctx := tracer.StartTraceFromHeader(ctx, strings.TrimSuffix(fmt.Sprintf("GraphQL-Root:%s", operationName), ":"), header)

trace.SetTag("graphql.operationName", operationName)
if operationName != "" {
trace.SetTag("graphql.operationName", operationName)
}
if len(headers) > 0 {
trace.Log("http.headers", headers)
}
Expand Down
11 changes: 6 additions & 5 deletions codebase/app/rest_server/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,13 @@ func getDefaultOption() option {
env.BaseEnv().CORSAllowMethods, env.BaseEnv().CORSAllowHeaders,
env.BaseEnv().CORSAllowOrigins, nil, env.BaseEnv().CORSAllowCredential,
)),
EchoWrapMiddleware(wrapper.HTTPMiddlewareTracer(env.BaseEnv().JaegerMaxPacketSize)),
EchoWrapMiddleware(wrapper.HTTPMiddlewareTracer(wrapper.HTTPMiddlewareTracerConfig{
MaxLogSize: env.BaseEnv().JaegerMaxPacketSize,
ExcludePath: map[string]struct{}{"/": {}, "/graphql": {}},
})),
EchoLoggerMiddleware(env.BaseEnv().DebugMode, os.Stdout),
},
rootHandler: http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rw.Write([]byte("REST Server up and running"))
}),
rootHandler: http.HandlerFunc(wrapper.HTTPHandlerDefaultRoot),
errorHandler: CustomHTTPErrorHandler,
}
}
Expand Down Expand Up @@ -115,7 +116,7 @@ func SetRootMiddlewares(middlewares ...echo.MiddlewareFunc) OptionFunc {
}
}

// AddRootMiddlewares option func
// AddRootMiddlewares option func, overide root middleware
func AddRootMiddlewares(middlewares ...echo.MiddlewareFunc) OptionFunc {
return func(o *option) {
o.rootMiddlewares = append(o.rootMiddlewares, middlewares...)
Expand Down
4 changes: 2 additions & 2 deletions codebase/app/rest_server/rest_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ import (
"github.com/soheilhy/cmux"

"github.com/golangid/candi/candihelper"
"github.com/golangid/candi/candishared"
graphqlserver "github.com/golangid/candi/codebase/app/graphql_server"
"github.com/golangid/candi/codebase/factory"
"github.com/golangid/candi/codebase/factory/types"
"github.com/golangid/candi/logger"
"github.com/golangid/candi/wrapper"
)

type restServer struct {
Expand Down Expand Up @@ -51,7 +51,7 @@ func NewServer(service factory.ServiceFactory, opts ...OptionFunc) factory.AppSe

server.serverEngine.GET("/", echo.WrapHandler(server.opt.rootHandler))
server.serverEngine.GET("/memstats",
echo.WrapHandler(http.HandlerFunc(candishared.HTTPMemstatsHandler)),
echo.WrapHandler(http.HandlerFunc(wrapper.HTTPHandlerMemstats)),
echo.WrapMiddleware(service.GetDependency().GetMiddleware().HTTPBasicAuth),
)

Expand Down
4 changes: 0 additions & 4 deletions codebase/factory/appfactory/setup_graphql_server.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package appfactory

import (
"net/http"

"github.com/golangid/candi/candishared"
graphqlserver "github.com/golangid/candi/codebase/app/graphql_server"
"github.com/golangid/candi/codebase/factory"
"github.com/golangid/candi/config/env"
Expand All @@ -15,7 +12,6 @@ func SetupGraphQLServer(service factory.ServiceFactory, opts ...graphqlserver.Op
graphqlserver.SetHTTPPort(env.BaseEnv().HTTPPort),
graphqlserver.SetRootPath(env.BaseEnv().HTTPRootPath),
graphqlserver.SetDisableIntrospection(env.BaseEnv().GraphQLDisableIntrospection),
graphqlserver.SetRootHTTPHandler(http.HandlerFunc(candishared.HTTPRoot(string(service.Name()), env.BaseEnv().BuildNumber))),
graphqlserver.SetSharedListener(service.GetConfig().SharedListener),
graphqlserver.SetDebugMode(env.BaseEnv().DebugMode),
graphqlserver.SetJaegerMaxPacketSize(env.BaseEnv().JaegerMaxPacketSize),
Expand Down
4 changes: 0 additions & 4 deletions codebase/factory/appfactory/setup_rest_server.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package appfactory

import (
"net/http"

"github.com/golangid/candi/candishared"
restserver "github.com/golangid/candi/codebase/app/rest_server"
"github.com/golangid/candi/codebase/factory"
"github.com/golangid/candi/config/env"
Expand All @@ -15,7 +12,6 @@ func SetupRESTServer(service factory.ServiceFactory, opts ...restserver.OptionFu
restserver.SetHTTPPort(env.BaseEnv().HTTPPort),
restserver.SetRootPath(env.BaseEnv().HTTPRootPath),
restserver.SetIncludeGraphQL(env.BaseEnv().UseGraphQL),
restserver.SetRootHTTPHandler(http.HandlerFunc(candishared.HTTPRoot(string(service.Name()), env.BaseEnv().BuildNumber))),
restserver.SetSharedListener(service.GetConfig().SharedListener),
restserver.SetDebugMode(env.BaseEnv().DebugMode),
restserver.SetJaegerMaxPacketSize(env.BaseEnv().JaegerMaxPacketSize),
Expand Down
2 changes: 1 addition & 1 deletion init.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ package candi

const (
// Version of this library
Version = "v1.14.2"
Version = "v1.14.3"
)
65 changes: 61 additions & 4 deletions wrapper/http_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,39 @@ package wrapper

import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httputil"
"os"
"runtime"
"strconv"
"strings"
"time"

"github.com/golangid/candi/candihelper"
"github.com/golangid/candi/config/env"
"github.com/golangid/candi/logger"
"github.com/golangid/candi/tracer"
)

type HTTPMiddlewareTracerConfig struct {
MaxLogSize int
ExcludePath map[string]struct{}
}

// HTTPMiddlewareTracer middleware wrapper for tracer
func HTTPMiddlewareTracer(maxLogSize int) func(http.Handler) http.Handler {
func HTTPMiddlewareTracer(cfg HTTPMiddlewareTracerConfig) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {

if _, isExcludePath := cfg.ExcludePath[req.URL.Path]; isExcludePath {
next.ServeHTTP(rw, req)
return
}
isDisableTrace, _ := strconv.ParseBool(req.Header.Get(candihelper.HeaderDisableTrace))
if isDisableTrace || req.URL.Path == "/" {
if isDisableTrace {
next.ServeHTTP(rw, req.WithContext(tracer.SkipTraceContext(req.Context())))
return
}
Expand All @@ -45,7 +59,7 @@ func HTTPMiddlewareTracer(maxLogSize int) func(http.Handler) http.Handler {
trace.Log("http.request", httpDump)

body, _ := io.ReadAll(req.Body)
if len(body) < maxLogSize {
if len(body) < cfg.MaxLogSize {
trace.Log("request.body", body)
} else {
trace.Log("request.body.size", len(body))
Expand All @@ -62,7 +76,7 @@ func HTTPMiddlewareTracer(maxLogSize int) func(http.Handler) http.Handler {
trace.SetError(fmt.Errorf("resp.code:%d", respWriter.statusCode))
}

if resBody.Len() < maxLogSize {
if resBody.Len() < cfg.MaxLogSize {
trace.Log("response.body", resBody.String())
} else {
trace.Log("response.body.size", resBody.Len())
Expand Down Expand Up @@ -134,3 +148,46 @@ func HTTPMiddlewareCORS(
})
}
}

// HTTPHandlerDefaultRoot default root http handler
func HTTPHandlerDefaultRoot(w http.ResponseWriter, r *http.Request) {
now := time.Now()
payload := struct {
BuildNumber string `json:"build_number,omitempty"`
Message string `json:"message,omitempty"`
Hostname string `json:"hostname,omitempty"`
Timestamp string `json:"timestamp,omitempty"`
StartAt string `json:"start_at,omitempty"`
Uptime string `json:"uptime,omitempty"`
}{
Message: fmt.Sprintf("Service %s up and running", env.BaseEnv().ServiceName),
Timestamp: now.Format(time.RFC3339Nano),
}

if startAt, err := time.Parse(time.RFC3339, env.BaseEnv().StartAt); err == nil {
payload.StartAt = env.BaseEnv().StartAt
payload.Uptime = now.Sub(startAt).String()
}
if env.BaseEnv().BuildNumber != "" {
payload.BuildNumber = env.BaseEnv().BuildNumber
}
if hostname, err := os.Hostname(); err == nil {
payload.Hostname = hostname
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(payload)
}

// HTTPHandlerMemstats calculate runtime statistic
func HTTPHandlerMemstats(w http.ResponseWriter, r *http.Request) {
var m runtime.MemStats
runtime.ReadMemStats(&m)
data := struct {
NumGoroutine int `json:"num_goroutine"`
Memstats interface{} `json:"memstats"`
}{
runtime.NumGoroutine(), m,
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(data)
}
8 changes: 4 additions & 4 deletions wrapper/http_response_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import (
type WrapHTTPResponseWriter struct {
statusCode int
writer io.Writer
rw http.ResponseWriter
http.ResponseWriter
}

// NewWrapHTTPResponseWriter init new wrapper for http response writter
func NewWrapHTTPResponseWriter(w io.Writer, httpResponseWriter http.ResponseWriter) *WrapHTTPResponseWriter {
// Default the status code to 200
return &WrapHTTPResponseWriter{statusCode: http.StatusOK, writer: io.MultiWriter(w, httpResponseWriter), rw: httpResponseWriter}
return &WrapHTTPResponseWriter{statusCode: http.StatusOK, writer: io.MultiWriter(w, httpResponseWriter), ResponseWriter: httpResponseWriter}
}

// StatusCode give a way to get the Code
Expand All @@ -25,7 +25,7 @@ func (w *WrapHTTPResponseWriter) StatusCode() int {

// Header Satisfy the http.ResponseWriter interface
func (w *WrapHTTPResponseWriter) Header() http.Header {
return w.rw.Header()
return w.ResponseWriter.Header()
}

func (w *WrapHTTPResponseWriter) Write(data []byte) (int, error) {
Expand All @@ -39,5 +39,5 @@ func (w *WrapHTTPResponseWriter) WriteHeader(statusCode int) {
w.statusCode = statusCode

// Write the status code onward.
w.rw.WriteHeader(statusCode)
w.ResponseWriter.WriteHeader(statusCode)
}

0 comments on commit ce53ad1

Please sign in to comment.