-
Notifications
You must be signed in to change notification settings - Fork 94
/
api_public.go
134 lines (115 loc) · 4.37 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
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)
// API is a REST JSONAPI.
type API struct {
ContentType string
router routing.Routeable
info information
resources []resource
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 interface{}) {
api.addResource(prototype, source)
}
// 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...)
}
// NewAPIVersion can be used to chain an additional API version to the routing of a previous
// one. Use this if you have multiple version prefixes and want to combine all
// your different API versions. This reuses the baseURL or URLResolver
func (api *API) NewAPIVersion(prefix string) *API {
return newAPI(prefix, api.info.resolver, api.router)
}
// NewAPIWithResolver can be used to create an API with a custom URL resolver.
func NewAPIWithResolver(prefix string, resolver URLResolver) *API {
handler := notAllowedHandler{}
r := routing.NewHTTPRouter(prefix, &handler)
api := newAPI(prefix, resolver, r)
handler.API = api
return api
}
// 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 {
handler := notAllowedHandler{}
staticResolver := NewStaticResolver(baseURL)
r := routing.NewHTTPRouter(prefix, &handler)
api := newAPI(prefix, staticResolver, r)
handler.API = api
return api
}
// NewAPI returns an initialized API instance
// `prefix` is added in front of all endpoints.
func NewAPI(prefix string) *API {
handler := notAllowedHandler{}
staticResolver := NewStaticResolver("")
r := routing.NewHTTPRouter(prefix, &handler)
api := newAPI(prefix, staticResolver, r)
handler.API = api
return api
}
// 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`
func NewAPIWithRouting(prefix string, resolver URLResolver, router routing.Routeable) *API {
return newAPI(prefix, resolver, router)
}
// newAPI is now an internal method that can be changed if params are changing
func newAPI(prefix string, resolver URLResolver, router routing.Routeable) *API {
// 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{
ContentType: defaultContentTypHeader,
router: router,
info: info,
middlewares: make([]HandlerFunc, 0),
contextAllocator: nil,
}
api.contextPool.New = func() interface{} {
if api.contextAllocator != nil {
return api.contextAllocator(api)
}
return api.allocateDefaultContext()
}
return api
}