forked from manyminds/api2go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapi_public.go
157 lines (133 loc) · 5.6 KB
/
api_public.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package api2go
import (
"net/http"
"strings"
"sync"
"github.com/manyminds/api2go/jsonapi"
"github.com/manyminds/api2go/routing"
)
// HandlerFunc for api2go middlewares
type HandlerFunc func(APIContexter, http.ResponseWriter, *http.Request)
// DefaultContentMarshalers is the default set of content marshalers for an API.
// Currently this means handling application/vnd.api+json content type bodies
// using the standard encoding/json package.
var DefaultContentMarshalers = map[string]ContentMarshaler{
defaultContentTypHeader: JSONContentMarshaler{},
}
// API is a REST JSONAPI.
type API struct {
router routing.Routeable
info information
resources []resource
marshalers map[string]ContentMarshaler
middlewares []HandlerFunc
contextPool sync.Pool
contextAllocator APIContextAllocatorFunc
}
// Handler returns the http.Handler instance for the API.
func (api API) Handler() http.Handler {
return api.router.Handler()
}
//Router returns the specified router on an api instance
func (api API) Router() routing.Routeable {
return api.router
}
// SetContextAllocator custom implementation for making contexts
func (api *API) SetContextAllocator(allocator APIContextAllocatorFunc) {
api.contextAllocator = allocator
}
// AddResource registers a data source for the given resource
// At least the CRUD interface must be implemented, all the other interfaces are optional.
// `resource` should be either an empty struct instance such as `Post{}` or a pointer to
// a struct such as `&Post{}`. The same type will be used for constructing new elements.
func (api *API) AddResource(prototype jsonapi.MarshalIdentifier, source CRUD) {
api.addResource(prototype, source, api.marshalers)
}
// UseMiddleware registers middlewares that implement the api2go.HandlerFunc
// Middleware is run before any generated routes.
func (api *API) UseMiddleware(middleware ...HandlerFunc) {
api.middlewares = append(api.middlewares, middleware...)
}
// SetRedirectTrailingSlash enables 307 redirects on urls ending with /
// when disabled, an URL ending with / will 404
// this will and should work only if using the default router
// DEPRECATED
func (api *API) SetRedirectTrailingSlash(enabled bool) {
if api.router == nil {
panic("router must not be nil")
}
httpRouter, ok := api.router.(*routing.HTTPRouter)
if !ok {
panic("can not set redirectTrailingSlashes if not using the internal httpRouter")
}
httpRouter.SetRedirectTrailingSlash(enabled)
}
// NewAPIWithMarshalling does the same as NewAPIWithBaseURL with the addition
// of a set of marshalers that provide a way to interact with clients that
// use a serialization format other than JSON. The marshalers map is indexed
// by the MIME content type to use for a given request-response pair. If the
// client provides an Accept header the server will respond using the client's
// preferred content type, otherwise it will respond using whatever content
// type the client provided in its Content-Type request header.
func NewAPIWithMarshalling(prefix string, resolver URLResolver, marshalers map[string]ContentMarshaler) *API {
r := routing.NewHTTPRouter(prefix, notAllowedHandler{marshalers: marshalers})
return newAPI(prefix, resolver, marshalers, r)
}
// NewAPIWithBaseURL does the same as NewAPI with the addition of
// a baseURL which get's added in front of all generated URLs.
// For example http://localhost/v1/myResource/abc instead of /v1/myResource/abc
func NewAPIWithBaseURL(prefix string, baseURL string) *API {
return NewAPIWithMarshalers(prefix, baseURL, DefaultContentMarshalers)
}
// NewAPI returns an initialized API instance
// `prefix` is added in front of all endpoints.
func NewAPI(prefix string) *API {
return NewAPIWithMarshalers(prefix, "", DefaultContentMarshalers)
}
// NewAPIWithRouting allows you to use a custom URLResolver, marshalers and custom routing
// if you want to use the default routing, you should use another constructor.
//
// If you don't need any of the parameters you can skip them with the defaults:
// the default for `prefix` would be `""`, which means there is no namespace for your api.
// although we suggest using one.
//
// if your api only answers to one url you can use a NewStaticResolver() as `resolver`
//
// if you have no specific marshalling needs, use `DefaultContentMarshalers`
func NewAPIWithRouting(prefix string, resolver URLResolver, marshalers map[string]ContentMarshaler, router routing.Routeable) *API {
return newAPI(prefix, resolver, marshalers, router)
}
// newAPI is now an internal method that can be changed if params are changing
func newAPI(prefix string, resolver URLResolver, marshalers map[string]ContentMarshaler, router routing.Routeable) *API {
if len(marshalers) == 0 {
panic("marshaler map must not be empty")
}
// Add initial and trailing slash to prefix
prefixSlashes := strings.Trim(prefix, "/")
if len(prefixSlashes) > 0 {
prefixSlashes = "/" + prefixSlashes + "/"
} else {
prefixSlashes = "/"
}
info := information{prefix: prefix, resolver: resolver}
api := &API{
router: router,
info: info,
marshalers: marshalers,
middlewares: make([]HandlerFunc, 0),
contextAllocator: nil,
}
api.contextPool.New = func() interface{} {
if api.contextAllocator != nil {
return api.contextAllocator(api)
}
return api.allocateDefaultContext()
}
return api
}
// NewAPIWithMarshalers is DEPRECATED
// use NewApiWithMarshalling instead
func NewAPIWithMarshalers(prefix string, baseURL string, marshalers map[string]ContentMarshaler) *API {
staticResolver := NewStaticResolver(baseURL)
return NewAPIWithMarshalling(prefix, staticResolver, marshalers)
}