Skip to content

Commit

Permalink
feature(ctx): ctx as handler parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
alexisvisco committed Oct 3, 2020
1 parent 1fa1fc3 commit dd54428
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 2 deletions.
38 changes: 38 additions & 0 deletions examples/simple-with-ctx/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package main

import (
"context"
"net/http"

"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"

"github.com/expectedsh/kcd"
)

func main() {
r := chi.NewRouter()
r.Use(middleware.RequestID)

r.Get("/{name}", kcd.Handler(YourHttpHandler, http.StatusOK))
_ = http.ListenAndServe(":3000", r)
}

// CreateCustomerInput is an example of input for an http request.
type CreateCustomerInput struct {
Name string `path:"name"`
Emails []string `query:"emails" exploder:","`
}

// CustomerOutput is the output type of your handler it contain the input for simplicity.
type CustomerOutput struct {
Name string `json:"name"`
}

// YourHttpHandler is here using the ctx of the request.
func YourHttpHandler(ctx context.Context, _ *CreateCustomerInput) (CustomerOutput, error) {
// get the id of the request from the context
id := middleware.GetReqID(ctx)

return CustomerOutput{Name: id}, nil
}
19 changes: 17 additions & 2 deletions handler.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package kcd

import (
"context"
"fmt"
"net/http"
"reflect"
Expand All @@ -16,6 +17,7 @@ const (
inputTypeResponse inputType = iota
inputTypeRequest
inputTypeInput
inputTypeCtx
)

// Handler returns a default http handler.
Expand Down Expand Up @@ -103,6 +105,8 @@ func Handler(h interface{}, defaultStatusCode int) http.HandlerFunc {
args = append(args, reflect.ValueOf(r))
case inputTypeResponse:
args = append(args, reflect.ValueOf(w))
case inputTypeCtx:
args = append(args, reflect.ValueOf(r.Context()))
}
}

Expand Down Expand Up @@ -131,15 +135,16 @@ func Handler(h interface{}, defaultStatusCode int) http.HandlerFunc {
}

var interfaceResponseWriter = reflect.TypeOf((*http.ResponseWriter)(nil)).Elem()
var interfaceCtx = reflect.TypeOf((*context.Context)(nil)).Elem()

// input checks the input parameters of a kcd handler
// and return the type of the second parameter, if any.
func input(ht reflect.Type, name string) (orderedInputType []inputType, reflectType reflect.Type) {
n := ht.NumIn()

if n > 3 {
if n > 4 {
panic(fmt.Sprintf(
"incorrect number of input parameters for handler %s, expected 0 or 3, got %d",
"incorrect number of input parameters for handler %s, expected 0 to 4, got %d",
name, n,
))
}
Expand All @@ -161,6 +166,16 @@ func input(ht reflect.Type, name string) (orderedInputType []inputType, reflectT

setInputType[inputTypeResponse] = true
orderedInputType = append(orderedInputType, inputTypeResponse)
case currentInput.Implements(interfaceCtx):
if _, exist := setInputType[inputTypeCtx]; exist {
panic(fmt.Sprintf(
"invalid parameter %d at handler %s: there is already a context.Context parameter",
i, name,
))
}

setInputType[inputTypeCtx] = true
orderedInputType = append(orderedInputType, inputTypeCtx)
case currentInput.ConvertibleTo(reflect.TypeOf(&http.Request{})):
if _, exist := setInputType[inputTypeRequest]; exist {
panic(fmt.Sprintf(
Expand Down

0 comments on commit dd54428

Please sign in to comment.