OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / go-kit / kit / examples / profilesvc / transport.go
1 package profilesvc
2
3 // The profilesvc is just over HTTP, so we just have a single transport.go.
4
5 import (
6         "bytes"
7         "context"
8         "encoding/json"
9         "errors"
10         "io/ioutil"
11         "net/http"
12         "net/url"
13
14         "github.com/gorilla/mux"
15
16         "github.com/go-kit/kit/log"
17         httptransport "github.com/go-kit/kit/transport/http"
18 )
19
20 var (
21         // ErrBadRouting is returned when an expected path variable is missing.
22         // It always indicates programmer error.
23         ErrBadRouting = errors.New("inconsistent mapping between route and handler (programmer error)")
24 )
25
26 // MakeHTTPHandler mounts all of the service endpoints into an http.Handler.
27 // Useful in a profilesvc server.
28 func MakeHTTPHandler(s Service, logger log.Logger) http.Handler {
29         r := mux.NewRouter()
30         e := MakeServerEndpoints(s)
31         options := []httptransport.ServerOption{
32                 httptransport.ServerErrorLogger(logger),
33                 httptransport.ServerErrorEncoder(encodeError),
34         }
35
36         // POST    /profiles/                          adds another profile
37         // GET     /profiles/:id                       retrieves the given profile by id
38         // PUT     /profiles/:id                       post updated profile information about the profile
39         // PATCH   /profiles/:id                       partial updated profile information
40         // DELETE  /profiles/:id                       remove the given profile
41         // GET     /profiles/:id/addresses/            retrieve addresses associated with the profile
42         // GET     /profiles/:id/addresses/:addressID  retrieve a particular profile address
43         // POST    /profiles/:id/addresses/            add a new address
44         // DELETE  /profiles/:id/addresses/:addressID  remove an address
45
46         r.Methods("POST").Path("/profiles/").Handler(httptransport.NewServer(
47                 e.PostProfileEndpoint,
48                 decodePostProfileRequest,
49                 encodeResponse,
50                 options...,
51         ))
52         r.Methods("GET").Path("/profiles/{id}").Handler(httptransport.NewServer(
53                 e.GetProfileEndpoint,
54                 decodeGetProfileRequest,
55                 encodeResponse,
56                 options...,
57         ))
58         r.Methods("PUT").Path("/profiles/{id}").Handler(httptransport.NewServer(
59                 e.PutProfileEndpoint,
60                 decodePutProfileRequest,
61                 encodeResponse,
62                 options...,
63         ))
64         r.Methods("PATCH").Path("/profiles/{id}").Handler(httptransport.NewServer(
65                 e.PatchProfileEndpoint,
66                 decodePatchProfileRequest,
67                 encodeResponse,
68                 options...,
69         ))
70         r.Methods("DELETE").Path("/profiles/{id}").Handler(httptransport.NewServer(
71                 e.DeleteProfileEndpoint,
72                 decodeDeleteProfileRequest,
73                 encodeResponse,
74                 options...,
75         ))
76         r.Methods("GET").Path("/profiles/{id}/addresses/").Handler(httptransport.NewServer(
77                 e.GetAddressesEndpoint,
78                 decodeGetAddressesRequest,
79                 encodeResponse,
80                 options...,
81         ))
82         r.Methods("GET").Path("/profiles/{id}/addresses/{addressID}").Handler(httptransport.NewServer(
83                 e.GetAddressEndpoint,
84                 decodeGetAddressRequest,
85                 encodeResponse,
86                 options...,
87         ))
88         r.Methods("POST").Path("/profiles/{id}/addresses/").Handler(httptransport.NewServer(
89                 e.PostAddressEndpoint,
90                 decodePostAddressRequest,
91                 encodeResponse,
92                 options...,
93         ))
94         r.Methods("DELETE").Path("/profiles/{id}/addresses/{addressID}").Handler(httptransport.NewServer(
95                 e.DeleteAddressEndpoint,
96                 decodeDeleteAddressRequest,
97                 encodeResponse,
98                 options...,
99         ))
100         return r
101 }
102
103 func decodePostProfileRequest(_ context.Context, r *http.Request) (request interface{}, err error) {
104         var req postProfileRequest
105         if e := json.NewDecoder(r.Body).Decode(&req.Profile); e != nil {
106                 return nil, e
107         }
108         return req, nil
109 }
110
111 func decodeGetProfileRequest(_ context.Context, r *http.Request) (request interface{}, err error) {
112         vars := mux.Vars(r)
113         id, ok := vars["id"]
114         if !ok {
115                 return nil, ErrBadRouting
116         }
117         return getProfileRequest{ID: id}, nil
118 }
119
120 func decodePutProfileRequest(_ context.Context, r *http.Request) (request interface{}, err error) {
121         vars := mux.Vars(r)
122         id, ok := vars["id"]
123         if !ok {
124                 return nil, ErrBadRouting
125         }
126         var profile Profile
127         if err := json.NewDecoder(r.Body).Decode(&profile); err != nil {
128                 return nil, err
129         }
130         return putProfileRequest{
131                 ID:      id,
132                 Profile: profile,
133         }, nil
134 }
135
136 func decodePatchProfileRequest(_ context.Context, r *http.Request) (request interface{}, err error) {
137         vars := mux.Vars(r)
138         id, ok := vars["id"]
139         if !ok {
140                 return nil, ErrBadRouting
141         }
142         var profile Profile
143         if err := json.NewDecoder(r.Body).Decode(&profile); err != nil {
144                 return nil, err
145         }
146         return patchProfileRequest{
147                 ID:      id,
148                 Profile: profile,
149         }, nil
150 }
151
152 func decodeDeleteProfileRequest(_ context.Context, r *http.Request) (request interface{}, err error) {
153         vars := mux.Vars(r)
154         id, ok := vars["id"]
155         if !ok {
156                 return nil, ErrBadRouting
157         }
158         return deleteProfileRequest{ID: id}, nil
159 }
160
161 func decodeGetAddressesRequest(_ context.Context, r *http.Request) (request interface{}, err error) {
162         vars := mux.Vars(r)
163         id, ok := vars["id"]
164         if !ok {
165                 return nil, ErrBadRouting
166         }
167         return getAddressesRequest{ProfileID: id}, nil
168 }
169
170 func decodeGetAddressRequest(_ context.Context, r *http.Request) (request interface{}, err error) {
171         vars := mux.Vars(r)
172         id, ok := vars["id"]
173         if !ok {
174                 return nil, ErrBadRouting
175         }
176         addressID, ok := vars["addressID"]
177         if !ok {
178                 return nil, ErrBadRouting
179         }
180         return getAddressRequest{
181                 ProfileID: id,
182                 AddressID: addressID,
183         }, nil
184 }
185
186 func decodePostAddressRequest(_ context.Context, r *http.Request) (request interface{}, err error) {
187         vars := mux.Vars(r)
188         id, ok := vars["id"]
189         if !ok {
190                 return nil, ErrBadRouting
191         }
192         var address Address
193         if err := json.NewDecoder(r.Body).Decode(&address); err != nil {
194                 return nil, err
195         }
196         return postAddressRequest{
197                 ProfileID: id,
198                 Address:   address,
199         }, nil
200 }
201
202 func decodeDeleteAddressRequest(_ context.Context, r *http.Request) (request interface{}, err error) {
203         vars := mux.Vars(r)
204         id, ok := vars["id"]
205         if !ok {
206                 return nil, ErrBadRouting
207         }
208         addressID, ok := vars["addressID"]
209         if !ok {
210                 return nil, ErrBadRouting
211         }
212         return deleteAddressRequest{
213                 ProfileID: id,
214                 AddressID: addressID,
215         }, nil
216 }
217
218 func encodePostProfileRequest(ctx context.Context, req *http.Request, request interface{}) error {
219         // r.Methods("POST").Path("/profiles/")
220         req.Method, req.URL.Path = "POST", "/profiles/"
221         return encodeRequest(ctx, req, request)
222 }
223
224 func encodeGetProfileRequest(ctx context.Context, req *http.Request, request interface{}) error {
225         // r.Methods("GET").Path("/profiles/{id}")
226         r := request.(getProfileRequest)
227         profileID := url.QueryEscape(r.ID)
228         req.Method, req.URL.Path = "GET", "/profiles/"+profileID
229         return encodeRequest(ctx, req, request)
230 }
231
232 func encodePutProfileRequest(ctx context.Context, req *http.Request, request interface{}) error {
233         // r.Methods("PUT").Path("/profiles/{id}")
234         r := request.(putProfileRequest)
235         profileID := url.QueryEscape(r.ID)
236         req.Method, req.URL.Path = "PUT", "/profiles/"+profileID
237         return encodeRequest(ctx, req, request)
238 }
239
240 func encodePatchProfileRequest(ctx context.Context, req *http.Request, request interface{}) error {
241         // r.Methods("PATCH").Path("/profiles/{id}")
242         r := request.(patchProfileRequest)
243         profileID := url.QueryEscape(r.ID)
244         req.Method, req.URL.Path = "PATCH", "/profiles/"+profileID
245         return encodeRequest(ctx, req, request)
246 }
247
248 func encodeDeleteProfileRequest(ctx context.Context, req *http.Request, request interface{}) error {
249         // r.Methods("DELETE").Path("/profiles/{id}")
250         r := request.(deleteProfileRequest)
251         profileID := url.QueryEscape(r.ID)
252         req.Method, req.URL.Path = "DELETE", "/profiles/"+profileID
253         return encodeRequest(ctx, req, request)
254 }
255
256 func encodeGetAddressesRequest(ctx context.Context, req *http.Request, request interface{}) error {
257         // r.Methods("GET").Path("/profiles/{id}/addresses/")
258         r := request.(getAddressesRequest)
259         profileID := url.QueryEscape(r.ProfileID)
260         req.Method, req.URL.Path = "GET", "/profiles/"+profileID+"/addresses/"
261         return encodeRequest(ctx, req, request)
262 }
263
264 func encodeGetAddressRequest(ctx context.Context, req *http.Request, request interface{}) error {
265         // r.Methods("GET").Path("/profiles/{id}/addresses/{addressID}")
266         r := request.(getAddressRequest)
267         profileID := url.QueryEscape(r.ProfileID)
268         addressID := url.QueryEscape(r.AddressID)
269         req.Method, req.URL.Path = "GET", "/profiles/"+profileID+"/addresses/"+addressID
270         return encodeRequest(ctx, req, request)
271 }
272
273 func encodePostAddressRequest(ctx context.Context, req *http.Request, request interface{}) error {
274         // r.Methods("POST").Path("/profiles/{id}/addresses/")
275         r := request.(postAddressRequest)
276         profileID := url.QueryEscape(r.ProfileID)
277         req.Method, req.URL.Path = "POST", "/profiles/"+profileID+"/addresses/"
278         return encodeRequest(ctx, req, request)
279 }
280
281 func encodeDeleteAddressRequest(ctx context.Context, req *http.Request, request interface{}) error {
282         // r.Methods("DELETE").Path("/profiles/{id}/addresses/{addressID}")
283         r := request.(deleteAddressRequest)
284         profileID := url.QueryEscape(r.ProfileID)
285         addressID := url.QueryEscape(r.AddressID)
286         req.Method, req.URL.Path = "DELETE", "/profiles/"+profileID+"/addresses/"+addressID
287         return encodeRequest(ctx, req, request)
288 }
289
290 func decodePostProfileResponse(_ context.Context, resp *http.Response) (interface{}, error) {
291         var response postProfileResponse
292         err := json.NewDecoder(resp.Body).Decode(&response)
293         return response, err
294 }
295
296 func decodeGetProfileResponse(_ context.Context, resp *http.Response) (interface{}, error) {
297         var response getProfileResponse
298         err := json.NewDecoder(resp.Body).Decode(&response)
299         return response, err
300 }
301
302 func decodePutProfileResponse(_ context.Context, resp *http.Response) (interface{}, error) {
303         var response putProfileResponse
304         err := json.NewDecoder(resp.Body).Decode(&response)
305         return response, err
306 }
307
308 func decodePatchProfileResponse(_ context.Context, resp *http.Response) (interface{}, error) {
309         var response patchProfileResponse
310         err := json.NewDecoder(resp.Body).Decode(&response)
311         return response, err
312 }
313
314 func decodeDeleteProfileResponse(_ context.Context, resp *http.Response) (interface{}, error) {
315         var response deleteProfileResponse
316         err := json.NewDecoder(resp.Body).Decode(&response)
317         return response, err
318 }
319
320 func decodeGetAddressesResponse(_ context.Context, resp *http.Response) (interface{}, error) {
321         var response getAddressesResponse
322         err := json.NewDecoder(resp.Body).Decode(&response)
323         return response, err
324 }
325
326 func decodeGetAddressResponse(_ context.Context, resp *http.Response) (interface{}, error) {
327         var response getAddressResponse
328         err := json.NewDecoder(resp.Body).Decode(&response)
329         return response, err
330 }
331
332 func decodePostAddressResponse(_ context.Context, resp *http.Response) (interface{}, error) {
333         var response postAddressResponse
334         err := json.NewDecoder(resp.Body).Decode(&response)
335         return response, err
336 }
337
338 func decodeDeleteAddressResponse(_ context.Context, resp *http.Response) (interface{}, error) {
339         var response deleteAddressResponse
340         err := json.NewDecoder(resp.Body).Decode(&response)
341         return response, err
342 }
343
344 // errorer is implemented by all concrete response types that may contain
345 // errors. It allows us to change the HTTP response code without needing to
346 // trigger an endpoint (transport-level) error. For more information, read the
347 // big comment in endpoints.go.
348 type errorer interface {
349         error() error
350 }
351
352 // encodeResponse is the common method to encode all response types to the
353 // client. I chose to do it this way because, since we're using JSON, there's no
354 // reason to provide anything more specific. It's certainly possible to
355 // specialize on a per-response (per-method) basis.
356 func encodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
357         if e, ok := response.(errorer); ok && e.error() != nil {
358                 // Not a Go kit transport error, but a business-logic error.
359                 // Provide those as HTTP errors.
360                 encodeError(ctx, e.error(), w)
361                 return nil
362         }
363         w.Header().Set("Content-Type", "application/json; charset=utf-8")
364         return json.NewEncoder(w).Encode(response)
365 }
366
367 // encodeRequest likewise JSON-encodes the request to the HTTP request body.
368 // Don't use it directly as a transport/http.Client EncodeRequestFunc:
369 // profilesvc endpoints require mutating the HTTP method and request path.
370 func encodeRequest(_ context.Context, req *http.Request, request interface{}) error {
371         var buf bytes.Buffer
372         err := json.NewEncoder(&buf).Encode(request)
373         if err != nil {
374                 return err
375         }
376         req.Body = ioutil.NopCloser(&buf)
377         return nil
378 }
379
380 func encodeError(_ context.Context, err error, w http.ResponseWriter) {
381         if err == nil {
382                 panic("encodeError with nil error")
383         }
384         w.Header().Set("Content-Type", "application/json; charset=utf-8")
385         w.WriteHeader(codeFrom(err))
386         json.NewEncoder(w).Encode(map[string]interface{}{
387                 "error": err.Error(),
388         })
389 }
390
391 func codeFrom(err error) int {
392         switch err {
393         case ErrNotFound:
394                 return http.StatusNotFound
395         case ErrAlreadyExists, ErrInconsistentIDs:
396                 return http.StatusBadRequest
397         default:
398                 return http.StatusInternalServerError
399         }
400 }