api2go

package module
v0.0.0-...-077e2b5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 8, 2020 License: MIT Imports: 14 Imported by: 0

README

api2go

GoDoc Build Status

Forked from project api2go.

Features

  • Most of the features in original project api2go.
  • Gin is the main framework and google/jsonapi marshaler and unmarshaler tool.
  • Original project supports Gin framework as adapter which do not work well with Gin middlewares especially the Gin RouterGroup.

Documentation

Overview

Package api2go enables building REST servers for the JSONAPI.org standard.

See https://github.com/cention-sany/api2go for usage instructions.

Index

Constants

This section is empty.

Variables

View Source
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

func OffsetPage(r *Request) (bool, int, int, error)

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

func (API) GetPrefix

func (i API) GetPrefix() 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 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(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

func (d *Doc) MarshalJSON() ([]byte, error)

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 FindAll

type FindAll interface {
	// FindAll returns all objects
	FindAll(req Request) (Responder, error)
}

The FindAll interface can be optionally implemented to fetch all records at once.

type HTTPError

type HTTPError struct {
	E []*jsonapi.ErrorObject
	// contains filtered or unexported fields
}

HTTPError is used for errors

func NewCustomError

func NewCustomError(err error, httpCode, appCode int) HTTPError

func NewHTTPError

func NewHTTPError(err error, msg string, status int) HTTPError

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 NewOnlyHTTPError(httpCode int) HTTPError

func (HTTPError) Error

func (e HTTPError) Error() string

Error returns a nice string represenation including the status

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 Metable

type Metable interface {
	Metadata() *jsonapi.Meta
}

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

Links returns a jsonapi.Links object to include in the top-level response

func (Response) Metadata

func (r Response) Metadata() map[string]interface{}

Metadata returns additional meta data

func (Response) Result

func (r Response) Result() interface{}

Result returns the actual payload

func (Response) StatusCode

func (r Response) StatusCode() int

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

type UnmarshalIdentifier interface {
	SetID(string) error
}

The UnmarshalIdentifier interface must be implemented to set the ID during unmarshalling.

type UnmarshalToManyRelations

type UnmarshalToManyRelations interface {
	SetToManyReferenceIDs(name string, IDs []string) error
}

The UnmarshalToManyRelations interface must be implemented to unmarshal to-many relations.

type UnmarshalToOneRelations

type UnmarshalToOneRelations interface {
	SetToOneReferenceID(name, ID string) error
}

The UnmarshalToOneRelations interface must be implemented to unmarshal to-one relations.

Directories

Path Synopsis
Package examples shows how to implement a basic CRUD for two data structures with the api2go server functionality.
Package examples shows how to implement a basic CRUD for two data structures with the api2go server functionality.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL