forked from nytimes/marvin
/
service.go
111 lines (98 loc) · 2.63 KB
/
service.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package api
import (
"context"
"net/http"
"strings"
"github.com/NYTimes/marvin"
"github.com/go-kit/kit/endpoint"
httptransport "github.com/go-kit/kit/transport/http"
"google.golang.org/appengine/user"
readinglist "github.com/NYTimes/marvin/examples/reading-list"
)
func init() {
marvin.Init(newService())
}
type httpService struct {
svc readinglist.Service
}
func newService() httpService {
return httpService{
svc: readinglist.NewService(readinglist.NewDB()),
}
}
// adding a service-wide error handler that can check the path
// suffix to determine how to serialize the error
func (s httpService) Options() []httptransport.ServerOption {
return []httptransport.ServerOption{
httptransport.ServerErrorEncoder(func(ctx context.Context, err error, w http.ResponseWriter) {
// check proto/json by inspecting url
path := ctx.Value(httptransport.ContextKeyRequestPath).(string)
if strings.HasSuffix(path, ".json") {
httptransport.EncodeJSONResponse(ctx, w, err)
return
}
marvin.EncodeProtoResponse(ctx, w, err)
}),
}
}
// override the default gorilla router and select the stdlib
func (s httpService) RouterOptions() []marvin.RouterOption {
return []marvin.RouterOption{
marvin.RouterSelect("stdlib"),
}
}
// in this example, we're tossing a simple CORS middleware in the mix
func (s httpService) HTTPMiddleware(h http.Handler) http.Handler {
return marvin.CORSHandler(h, "")
}
func (s httpService) Middleware(ep endpoint.Endpoint) endpoint.Endpoint {
return endpoint.Endpoint(func(ctx context.Context, r interface{}) (interface{}, error) {
usr, err := user.CurrentOAuth(ctx, "")
if usr == nil || err != nil {
// reject if user is not logged in
return nil, marvin.NewProtoStatusResponse(
&readinglist.Message{"please provide oauth token"},
http.StatusUnauthorized,
)
}
return ep(ctx, r)
})
}
func (s httpService) JSONEndpoints() map[string]map[string]marvin.HTTPEndpoint {
return map[string]map[string]marvin.HTTPEndpoint{
"/link.json": {
"PUT": {
Endpoint: s.PutLink,
Decoder: decodePutRequest,
},
},
"/list.json": {
"GET": {
Endpoint: s.GetLinks,
Decoder: decodeGetRequest,
},
},
}
}
func (s httpService) ProtoEndpoints() map[string]map[string]marvin.HTTPEndpoint {
return map[string]map[string]marvin.HTTPEndpoint{
"/link.proto": {
"PUT": {
Endpoint: s.PutLink,
Decoder: decodePutProtoRequest,
},
},
"/list.proto": {
"GET": {
Endpoint: s.GetLinks,
Decoder: decodeGetRequest,
},
},
}
}
func getUserID(ctx context.Context) string {
if usr, err := user.CurrentOAuth(ctx); usr != nil && err == nil {
return usr.ID
}
return ""
}