10 "github.com/gorilla/mux"
12 kitlog "github.com/go-kit/kit/log"
13 kithttp "github.com/go-kit/kit/transport/http"
15 "github.com/go-kit/kit/examples/shipping/cargo"
16 "github.com/go-kit/kit/examples/shipping/location"
19 // MakeHandler returns a handler for the booking service.
20 func MakeHandler(bs Service, logger kitlog.Logger) http.Handler {
21 opts := []kithttp.ServerOption{
22 kithttp.ServerErrorLogger(logger),
23 kithttp.ServerErrorEncoder(encodeError),
26 bookCargoHandler := kithttp.NewServer(
27 makeBookCargoEndpoint(bs),
28 decodeBookCargoRequest,
32 loadCargoHandler := kithttp.NewServer(
33 makeLoadCargoEndpoint(bs),
34 decodeLoadCargoRequest,
38 requestRoutesHandler := kithttp.NewServer(
39 makeRequestRoutesEndpoint(bs),
40 decodeRequestRoutesRequest,
44 assignToRouteHandler := kithttp.NewServer(
45 makeAssignToRouteEndpoint(bs),
46 decodeAssignToRouteRequest,
50 changeDestinationHandler := kithttp.NewServer(
51 makeChangeDestinationEndpoint(bs),
52 decodeChangeDestinationRequest,
56 listCargosHandler := kithttp.NewServer(
57 makeListCargosEndpoint(bs),
58 decodeListCargosRequest,
62 listLocationsHandler := kithttp.NewServer(
63 makeListLocationsEndpoint(bs),
64 decodeListLocationsRequest,
71 r.Handle("/booking/v1/cargos", bookCargoHandler).Methods("POST")
72 r.Handle("/booking/v1/cargos", listCargosHandler).Methods("GET")
73 r.Handle("/booking/v1/cargos/{id}", loadCargoHandler).Methods("GET")
74 r.Handle("/booking/v1/cargos/{id}/request_routes", requestRoutesHandler).Methods("GET")
75 r.Handle("/booking/v1/cargos/{id}/assign_to_route", assignToRouteHandler).Methods("POST")
76 r.Handle("/booking/v1/cargos/{id}/change_destination", changeDestinationHandler).Methods("POST")
77 r.Handle("/booking/v1/locations", listLocationsHandler).Methods("GET")
82 var errBadRoute = errors.New("bad route")
84 func decodeBookCargoRequest(_ context.Context, r *http.Request) (interface{}, error) {
86 Origin string `json:"origin"`
87 Destination string `json:"destination"`
88 ArrivalDeadline time.Time `json:"arrival_deadline"`
91 if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
95 return bookCargoRequest{
96 Origin: location.UNLocode(body.Origin),
97 Destination: location.UNLocode(body.Destination),
98 ArrivalDeadline: body.ArrivalDeadline,
102 func decodeLoadCargoRequest(_ context.Context, r *http.Request) (interface{}, error) {
106 return nil, errBadRoute
108 return loadCargoRequest{ID: cargo.TrackingID(id)}, nil
111 func decodeRequestRoutesRequest(_ context.Context, r *http.Request) (interface{}, error) {
115 return nil, errBadRoute
117 return requestRoutesRequest{ID: cargo.TrackingID(id)}, nil
120 func decodeAssignToRouteRequest(_ context.Context, r *http.Request) (interface{}, error) {
124 return nil, errBadRoute
127 var itinerary cargo.Itinerary
128 if err := json.NewDecoder(r.Body).Decode(&itinerary); err != nil {
132 return assignToRouteRequest{
133 ID: cargo.TrackingID(id),
134 Itinerary: itinerary,
138 func decodeChangeDestinationRequest(_ context.Context, r *http.Request) (interface{}, error) {
142 return nil, errBadRoute
146 Destination string `json:"destination"`
149 if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
153 return changeDestinationRequest{
154 ID: cargo.TrackingID(id),
155 Destination: location.UNLocode(body.Destination),
159 func decodeListCargosRequest(_ context.Context, r *http.Request) (interface{}, error) {
160 return listCargosRequest{}, nil
163 func decodeListLocationsRequest(_ context.Context, r *http.Request) (interface{}, error) {
164 return listLocationsRequest{}, nil
167 func encodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
168 if e, ok := response.(errorer); ok && e.error() != nil {
169 encodeError(ctx, e.error(), w)
172 w.Header().Set("Content-Type", "application/json; charset=utf-8")
173 return json.NewEncoder(w).Encode(response)
176 type errorer interface {
180 // encode errors from business-logic
181 func encodeError(_ context.Context, err error, w http.ResponseWriter) {
182 w.Header().Set("Content-Type", "application/json; charset=utf-8")
184 case cargo.ErrUnknown:
185 w.WriteHeader(http.StatusNotFound)
186 case ErrInvalidArgument:
187 w.WriteHeader(http.StatusBadRequest)
189 w.WriteHeader(http.StatusInternalServerError)
191 json.NewEncoder(w).Encode(map[string]interface{}{
192 "error": err.Error(),