Documentation
¶
Overview ¶
Package api2go enables building REST servers for the JSONAPI.org standard.
See https://github.com/cention-sany/api2go for usage instructions.
Index ¶
- Variables
- func OffsetPage(r *Request) (bool, int, int, error)
- type API
- type APIContexter
- type CRUD
- type DefaultLinks
- type Doc
- type EditToManyRelations
- type FindAll
- type HTTPError
- type Identifier
- type LinksResponder
- type Metable
- type ObjectInitializer
- type PaginatedFindAll
- type Pagination
- type RelationNode
- type Request
- type RequestAwareURLResolver
- type Responder
- type Response
- type URLResolver
- type UnmarshalIdentifier
- type UnmarshalToManyRelations
- type UnmarshalToOneRelations
Constants ¶
This section is empty.
Variables ¶
var ( // EmptyObject only apply to top level object which return null when the doc // can not be found but the requested path is legitimate. EmptyObject = &ja.OnePayload{} // EmptyObject only apply to top level object which return empty json array // [] when the doc can not be found but the requested path is legitimate. EmptyArray = &ja.ManyPayload{} )
Functions ¶
func OffsetPage ¶
OffsetPage is helper to check if r contains pagination query or not and turn it into SQL friendly offset and limit value. It return if r contains page query, offset, limit, and any error found. If page[limit] not exist in the offset-paged query, limit will return as -1.
Types ¶
type API ¶
type API struct {
ContentType string
// contains filtered or unexported fields
}
API is a REST JSONAPI. It also satisfies github.com/cention-sany/jsonapi.ServerInformation. GetPrefix() always return trail slash.
func NewAPI ¶
func NewAPI(prefix string, resolver URLResolver) *API
NewAPIWithResolver can be used to create an API with a custom URL resolver.
func (*API) AddResource ¶
func (api *API) AddResource(rg *gin.RouterGroup, prototype Identifier, source CRUD)
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) GetBaseURL ¶
func (i API) GetBaseURL() string
type APIContexter ¶
type APIContexter interface {
context.Context
Set(key string, value interface{})
Get(key string) (interface{}, bool)
}
APIContexter embedding context.Context and requesting two helper functions
type CRUD ¶
type CRUD interface {
// FindOne returns an object by its ID
// Possible Responder success status code 200
FindOne(id string, req Request) (Responder, error)
// Create a new object. Newly created object/struct must be in Responder.
// Possible Responder status codes are:
// - 201 Created: Resource was created and needs to be returned
// - 202 Accepted: Processing is delayed, return nothing
// - 204 No Content: Resource created with a client generated ID, and no
// fields were modified by the server
Create(obj interface{}, req Request) (Responder, error)
// Delete an object
// Possible Responder status codes are:
// - 200 OK: Deletion was a success, returns meta information, currently not
// implemented! Do not use this
// - 202 Accepted: Processing is delayed, return nothing
// - 204 No Content: Deletion was successful, return nothing
Delete(id string, req Request) (Responder, error)
// Update an object
// Possible Responder status codes are:
// - 200 OK: Update successful, however some field(s) were changed, returns
// updates source
// - 202 Accepted: Processing is delayed, return nothing
// - 204 No Content: Update was successful, no fields were changed by the
// server, return nothing
Update(obj interface{}, req Request) (Responder, error)
}
The CRUD interface MUST be implemented in order to use the api2go api. Use Responder for success status codes and content/meta data. In case of an error, use the error return value preferrably with an instance of our HTTPError struct.
type DefaultLinks ¶
type DefaultLinks struct {
// contains filtered or unexported fields
}
DefaultLinks is helper struct to generate link object for Responder or any struct that embeds it. DefaultLinks handle nil value by return nil to LinksWithSI and RelationshipLinksWithSI to avoid any links object to be generated. Thus provide flexibility to embedding struct to control the link object generations.
func NewDefaultLinks ¶
func NewDefaultLinks(id, name string, withRelation bool) *DefaultLinks
func (*DefaultLinks) LinksWithSI ¶
func (d *DefaultLinks) LinksWithSI(si ja.ServerInformation) *ja.Links
func (*DefaultLinks) RelationshipLinksWithSI ¶
func (d *DefaultLinks) RelationshipLinksWithSI(r string, si ja.ServerInformation) *ja.Links
type Doc ¶
type Doc struct {
// contains filtered or unexported fields
}
Doc implements noder and MarshalJSON
func (*Doc) MarshalJSON ¶
type EditToManyRelations ¶
type EditToManyRelations interface {
AddToManyIDs(name string, IDs []string) error
DeleteToManyIDs(name string, IDs []string) error
}
The EditToManyRelations interface can be optionally implemented to add and delete to-many relationships on a already unmarshalled struct. These methods are used by our API for the to-many relationship update routes.
There are 3 HTTP Methods to edit to-many relations:
PATCH /v1/posts/1/comments
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": [
{ "type": "comments", "id": "2" },
{ "type": "comments", "id": "3" }
]
}
This replaces all of the comments that belong to post with ID 1 and the SetToManyReferenceIDs method will be called.
POST /v1/posts/1/comments
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": [
{ "type": "comments", "id": "123" }
]
}
Adds a new comment to the post with ID 1. The AddToManyIDs method will be called.
DELETE /v1/posts/1/comments
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": [
{ "type": "comments", "id": "12" },
{ "type": "comments", "id": "13" }
]
}
Deletes comments that belong to post with ID 1. The DeleteToManyIDs method will be called.
type HTTPError ¶
type HTTPError struct {
E []*jsonapi.ErrorObject
// contains filtered or unexported fields
}
HTTPError is used for errors
func NewCustomError ¶
func NewHTTPError ¶
NewHTTPError creates a new error with message and status code. `err` will be logged (but never sent to a client), `msg` will be sent and `status` is the http status code. `err` can be nil.
func NewOnlyHTTPError ¶
func (HTTPError) Render ¶
func (e HTTPError) Render(w http.ResponseWriter) error
Error returns a nice string represenation including the status
func (HTTPError) Write ¶
func (e HTTPError) Write(w http.ResponseWriter) error
Write wraps Render() to provide compatibility with older gin versions
func (HTTPError) WriteContentType ¶
func (e HTTPError) WriteContentType(w http.ResponseWriter)
WriteContentType sets the content type
type Identifier ¶
type Identifier interface {
GetID() string
}
The Identifier interface is necessary to give an element a unique ID.
Note: The implementation of this interface is mandatory.
type LinksResponder ¶
type LinksResponder interface {
Responder
Links(*http.Request, jsonapi.ServerInformation) *jsonapi.Links
}
The LinksResponder interface may be used when the response object is able to return a set of links for the top-level response object.
type ObjectInitializer ¶
type ObjectInitializer interface {
InitializeObject(interface{})
}
The ObjectInitializer interface can be implemented to have the ability to change a created object before Unmarshal is called. This is currently only called on Create as the other actions go through FindOne or FindAll which are already controlled by the implementer.
type PaginatedFindAll ¶
type PaginatedFindAll interface {
PaginatedFindAll(req Request) (totalCount uint, resp Responder, err error)
}
The PaginatedFindAll interface can be optionally implemented to fetch a subset of all records. Pagination query parameters must be used to limit the result. Pagination URLs will automatically be generated by the api. You can use a combination of the following 2 query parameters: page[number] AND page[size] OR page[offset] AND page[limit]
type Pagination ¶
type Pagination struct {
Next map[string]string
Prev map[string]string
First map[string]string
Last map[string]string
}
Pagination represents information needed to return pagination links
type RelationNode ¶
type RelationNode struct {
// contains filtered or unexported fields
}
RelationNode implements noder and MarshalJSON
func (*RelationNode) MarshalJSON ¶
func (r *RelationNode) MarshalJSON() ([]byte, error)
type Request ¶
type Request struct {
QueryParams map[string][]string
Pagination map[string]string
APIContexter
*http.Request
}
Request contains additional information for FindOne and Find Requests
type RequestAwareURLResolver ¶
type RequestAwareURLResolver interface {
URLResolver
SetRequest(http.Request)
}
RequestAwareURLResolver allows you to dynamically change generated urls.
This is particulary useful if you have the same API answering to multiple domains, or subdomains e.g customer[1,2,3,4].yourapi.example.com
SetRequest will always be called prior to the GetBaseURL() from `URLResolver` so you have to change the result value based on the last request.
type Responder ¶
type Responder interface {
Result() interface{}
StatusCode() int
}
The Responder interface is used by all Resource Methods as a container for the Response. Metadata is additional Metadata. You can put anything you like into it, see jsonapi spec. Result returns the actual payload. For FindOne, put only one entry in it. StatusCode sets the http status code.
type Response ¶
type Response struct {
Res interface{}
Code int
Meta map[string]interface{}
Pagination Pagination
*DefaultLinks
}
The Response struct implements api2go.Responder and can be used as a default implementation for your responses you can fill the field `Meta` with all the metadata your application needs like license, tokens, etc
func (Response) StatusCode ¶
StatusCode sets the return status code
type URLResolver ¶
type URLResolver interface {
GetBaseURL() string
}
URLResolver allows you to implement a static way to return a baseURL for all incoming requests for one api2go instance.
func NewCallbackResolver ¶
func NewCallbackResolver(callback func(http.Request) string) URLResolver
NewCallbackResolver handles each resolve via your provided callback func
func NewStaticResolver ¶
func NewStaticResolver(baseURL string) URLResolver
NewStaticResolver returns a simple resolver that will always answer with the same url
type UnmarshalIdentifier ¶
The UnmarshalIdentifier interface must be implemented to set the ID during unmarshalling.
type UnmarshalToManyRelations ¶
The UnmarshalToManyRelations interface must be implemented to unmarshal to-many relations.
type UnmarshalToOneRelations ¶
The UnmarshalToOneRelations interface must be implemented to unmarshal to-one relations.