diff --git a/examples/stringsvc1/main.go b/examples/stringsvc1/main.go index 03fc79396..7649a385d 100644 --- a/examples/stringsvc1/main.go +++ b/examples/stringsvc1/main.go @@ -14,47 +14,50 @@ import ( // StringService provides operations on strings. type StringService interface { - Uppercase(string) (string, error) - Count(string) int + Uppercase(context.Context, string) (string, error) + Count(context.Context, string) int } +// stringService is a concrete implementation of StringService type stringService struct{} -func (stringService) Uppercase(s string) (string, error) { +func (stringService) Uppercase(_ context.Context, s string) (string, error) { if s == "" { return "", ErrEmpty } return strings.ToUpper(s), nil } -func (stringService) Count(s string) int { +func (stringService) Count(_ context.Context, s string) int { return len(s) } -func main() { - svc := stringService{} +// ErrEmpty is returned when an input string is empty. +var ErrEmpty = errors.New("empty string") - uppercaseHandler := httptransport.NewServer( - makeUppercaseEndpoint(svc), - decodeUppercaseRequest, - encodeResponse, - ) +// For each method, we define request and response structs +type uppercaseRequest struct { + S string `json:"s"` +} - countHandler := httptransport.NewServer( - makeCountEndpoint(svc), - decodeCountRequest, - encodeResponse, - ) +type uppercaseResponse struct { + V string `json:"v"` + Err string `json:"err,omitempty"` // errors don't define JSON marshaling +} - http.Handle("/uppercase", uppercaseHandler) - http.Handle("/count", countHandler) - log.Fatal(http.ListenAndServe(":8080", nil)) +type countRequest struct { + S string `json:"s"` } +type countResponse struct { + V int `json:"v"` +} + +// Endpoints are a primary abstraction in go-kit. An endpoint represents a single RPC (method in our service interface) func makeUppercaseEndpoint(svc StringService) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { req := request.(uppercaseRequest) - v, err := svc.Uppercase(req.S) + v, err := svc.Uppercase(ctx, req.S) if err != nil { return uppercaseResponse{v, err.Error()}, nil } @@ -65,11 +68,32 @@ func makeUppercaseEndpoint(svc StringService) endpoint.Endpoint { func makeCountEndpoint(svc StringService) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { req := request.(countRequest) - v := svc.Count(req.S) + v := svc.Count(ctx, req.S) return countResponse{v}, nil } } +// Transports expose the service to the network. In this first example we utilize JSON over HTTP. +func main() { + svc := stringService{} + + uppercaseHandler := httptransport.NewServer( + makeUppercaseEndpoint(svc), + decodeUppercaseRequest, + encodeResponse, + ) + + countHandler := httptransport.NewServer( + makeCountEndpoint(svc), + decodeCountRequest, + encodeResponse, + ) + + http.Handle("/uppercase", uppercaseHandler) + http.Handle("/count", countHandler) + log.Fatal(http.ListenAndServe(":8080", nil)) +} + func decodeUppercaseRequest(_ context.Context, r *http.Request) (interface{}, error) { var request uppercaseRequest if err := json.NewDecoder(r.Body).Decode(&request); err != nil { @@ -89,23 +113,3 @@ func decodeCountRequest(_ context.Context, r *http.Request) (interface{}, error) func encodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error { return json.NewEncoder(w).Encode(response) } - -type uppercaseRequest struct { - S string `json:"s"` -} - -type uppercaseResponse struct { - V string `json:"v"` - Err string `json:"err,omitempty"` // errors don't define JSON marshaling -} - -type countRequest struct { - S string `json:"s"` -} - -type countResponse struct { - V int `json:"v"` -} - -// ErrEmpty is returned when an input string is empty. -var ErrEmpty = errors.New("empty string")