Documentation ¶
Overview ¶
Package ab is the main package of the Alien Bunny web development kit.
This package contains the server and the middlewares of the framework. If you want to get started, you probably want to take a look at Hop and PetBunny.
The lowest level component is the Server component. It is a wrapper on the top of httprouter that adds middlewares along with a few useful features. On the server you can configure Services. Services are logical units of endpoints that share a piece of schema. On the top of the services, there are resources. Resources are CRUD endpoints. There are delegates and event handlers that help augmenting the functionality of the ResourceController.
Entities are a pointer to a struct that can be stored in a database. EntityController automatically does CRUD on entities, and the operations can be customized with delegates and event handlers.
EntityResource combines the EntityController and the ResourceController to easily expose an entity through API endpoints.
Quick and dirty usage:
func main() { ab.Hop(func(cfg *viper.Viper, s *ab.Server) error { ec := ab.NewEntityController(s.GetDBConnection()) ec.Add(&Content{}, contentEntityDelegate{}) res := ab.EntityResource(ec, &Content{}, ab.EntityResourceConfig{ DisableList: true, DisablePost: true, DisablePut: true, DisableDelete: true, }) s.RegisterService(res) return nil }, nil) }
Index ¶
- Variables
- func CSRFGetMiddleware(urlParam string) func(http.Handler) http.Handler
- func CSRFMiddleware(next http.Handler) http.Handler
- func CSRFTokenHandler(w http.ResponseWriter, r *http.Request)
- func CSVDecoder(body io.Reader, v interface{}) error
- func ConstraintErrorConverter(msgMap map[string]string) func(*pq.Error) VerboseError
- func ConstraintExists(db DB, constraint string) bool
- func ConvertDBError(err error, conv func(*pq.Error) VerboseError) error
- func DBErrorToVerboseString(err *pq.Error) string
- func DBMiddleware(connectString string, maxIdleConnections, maxOpenConnections int) (func(http.Handler) http.Handler, *sql.DB)
- func Decode(r *http.Request, v interface{}) error
- func DefaultLoggerMiddleware(level log.LogLevel) func(http.Handler) http.Handler
- func ErrorHandlerMiddleware(displayErrors bool) func(http.Handler) http.Handler
- func Fail(code int, err error)
- func GetCSRFToken(r *http.Request) string
- func GetParams(r *http.Request) httprouter.Params
- func GetRequestID(r *http.Request) string
- func HSTSMiddleware(config HSTSConfig) func(http.Handler) http.Handler
- func HTTPSRedirectServer(httpsAddr, httpAddr string) error
- func Hop(configure func(cfg *viper.Viper, s *Server) error, cfg *viper.Viper, ...)
- func JSONDecoder(body io.Reader, v interface{}) error
- func LogTrace(r *http.Request) log.Logger
- func LogUser(r *http.Request) log.Logger
- func LogVerbose(r *http.Request) log.Logger
- func LoggerMiddleware(level log.LogLevel, ...) func(http.Handler) http.Handler
- func MaybeFail(code int, err error, excludedErrors ...error)
- func MustDecode(r *http.Request, v interface{})
- func Pager(r *http.Request, limit int) int
- func RedirectDestination(r *http.Request) string
- func RedirectServer(addr, redirectAddr, certFile, keyFile string) error
- func RendererMiddleware(next http.Handler) http.Handler
- func RequestIDMiddleware(next http.Handler) http.Handler
- func RequestLoggerMiddleware(lw io.Writer) func(http.Handler) http.Handler
- func RequestLogs(r *http.Request) string
- func RestrictAddressMiddleware(addresses ...string) func(http.Handler) http.Handler
- func RestrictPrivateAddressMiddleware() func(http.Handler) http.Handler
- func SessionMiddleware(prefix string, key SecretKey, cookieURL *url.URL, expiresAfter time.Duration) func(http.Handler) http.Handler
- func SetContext(r *http.Request, key, value interface{}) *http.Request
- func TableExists(db DB, table string) bool
- func TransactionMiddleware(next http.Handler) http.Handler
- func XMLDecoder(body io.Reader, v interface{}) error
- type DB
- type DefaultResourceFormatter
- type EndpointLinker
- type Entity
- type EntityController
- func (ec *EntityController) Add(e Entity, delegate EntityDelegate) *EntityController
- func (ec *EntityController) AddDeleteEvent(evt ...EntityWriteEvent) *EntityController
- func (ec *EntityController) AddInsertEvent(evt ...EntityWriteEvent) *EntityController
- func (ec *EntityController) AddLoadEvent(evt ...EntityReadEvent) *EntityController
- func (ec *EntityController) AddUpdateEvent(evt ...EntityWriteEvent) *EntityController
- func (ec *EntityController) Delete(db DB, e Entity) error
- func (ec *EntityController) Empty(name string) Entity
- func (ec *EntityController) FieldList(name string) string
- func (ec *EntityController) Insert(db DB, e Entity) error
- func (ec *EntityController) Load(db DB, entityType string, keys ...interface{}) (Entity, error)
- func (ec *EntityController) LoadFromQuery(db DB, entityType string, query string, args ...interface{}) ([]Entity, error)
- func (ec *EntityController) SchemaSQL(e Entity) string
- func (ec *EntityController) TableAbbrev(name string) string
- func (ec *EntityController) Type(e Entity) string
- func (ec *EntityController) Update(db DB, e Entity) error
- func (ec *EntityController) Validate(e Entity) error
- type EntityDelegate
- type EntityDeleter
- type EntityInserter
- type EntityReadEvent
- type EntityResourceConfig
- type EntityResourceExtraSchema
- type EntityResourceLister
- type EntityResourceLoader
- type EntityUpdater
- type EntityWriteEvent
- type ErrorPageData
- type HALCurie
- type HSTSConfig
- type Panic
- type Renderer
- func (r *Renderer) AddOffer(mediaType string, handler func(w http.ResponseWriter)) *Renderer
- func (r *Renderer) Binary(mediaType, filename string, reader io.Reader) *Renderer
- func (r *Renderer) CSV(records [][]string) *Renderer
- func (r *Renderer) CSVChannel(records <-chan []string) *Renderer
- func (r *Renderer) CSVGenerator(recgen func(http.Flusher) ([]string, error)) *Renderer
- func (r *Renderer) HALJSON(v interface{}) *Renderer
- func (r *Renderer) HTML(t *template.Template, v interface{}) *Renderer
- func (r *Renderer) JSON(v interface{}) *Renderer
- func (rr *Renderer) Render(w http.ResponseWriter, r *http.Request)
- func (r *Renderer) SetCode(code int) *Renderer
- func (r *Renderer) Text(t string) *Renderer
- func (r *Renderer) XML(v interface{}, pretty bool) *Renderer
- type Resource
- type ResourceController
- func (res *ResourceController) AddDeleteEvent(evt ...ResourceEvent) *ResourceController
- func (res *ResourceController) AddGetEvent(evt ...ResourceEvent) *ResourceController
- func (res *ResourceController) AddListEvent(evt ...ResourceListEvent) *ResourceController
- func (res *ResourceController) AddPostEvent(evt ...ResourceEvent) *ResourceController
- func (res *ResourceController) AddPutEvent(evt ...ResourceEvent) *ResourceController
- func (res *ResourceController) Delete(d ResourceDeleteDelegate, middlewares ...func(http.Handler) http.Handler) *ResourceController
- func (res *ResourceController) Get(d ResourceGetDelegate, middlewares ...func(http.Handler) http.Handler) *ResourceController
- func (res *ResourceController) GetName() string
- func (res *ResourceController) List(d ResourceListDelegate, middlewares ...func(http.Handler) http.Handler) *ResourceController
- func (res *ResourceController) Post(d ResourcePostDelegate, middlewares ...func(http.Handler) http.Handler) *ResourceController
- func (res *ResourceController) Put(d ResourcePutDelegate, middlewares ...func(http.Handler) http.Handler) *ResourceController
- func (res *ResourceController) Register(srv *Server) error
- func (res *ResourceController) SchemaInstalled(db DB) bool
- func (res *ResourceController) SchemaSQL() string
- type ResourceControllerDelegate
- type ResourceDeleteDelegate
- type ResourceEvent
- type ResourceEventCallback
- type ResourceFormatter
- type ResourceGetDelegate
- type ResourceList
- type ResourceListDelegate
- type ResourceListEvent
- type ResourceListEventCallback
- type ResourcePathOverrider
- type ResourcePostDelegate
- type ResourcePutDelegate
- type SecretKey
- type Server
- func (s *Server) AddFile(path, file string) *Server
- func (s *Server) AddLocalDir(prefix, path string) *Server
- func (s *Server) Delete(path string, handler http.Handler, ...)
- func (s *Server) DeleteF(path string, handler http.HandlerFunc, ...)
- func (s *Server) EnableAutocert(caDirEndpoint, cacheDir string, hostWhitelist ...string)
- func (s *Server) EnableLetsEncrypt(cacheDir string, hostWhitelist ...string)
- func (s *Server) Get(path string, handler http.Handler, ...)
- func (s *Server) GetDBConnection() DB
- func (s *Server) GetF(path string, handler http.HandlerFunc, ...)
- func (s *Server) Handle(method, path string, handler http.Handler, ...)
- func (s *Server) Handler() http.Handler
- func (s *Server) Head(path string, handler http.Handler, ...)
- func (s *Server) HeadF(path string, handler http.HandlerFunc, ...)
- func (s *Server) Options(path string, handler http.Handler, ...)
- func (s *Server) OptionsF(path string, handler http.HandlerFunc, ...)
- func (s *Server) Patch(path string, handler http.Handler, ...)
- func (s *Server) PatchF(path string, handler http.HandlerFunc, ...)
- func (s *Server) Post(path string, handler http.Handler, ...)
- func (s *Server) PostF(path string, handler http.HandlerFunc, ...)
- func (s *Server) Put(path string, handler http.Handler, ...)
- func (s *Server) PutF(path string, handler http.HandlerFunc, ...)
- func (s *Server) RegisterService(svc Service)
- func (s *Server) StartHTTP(addr string) error
- func (s *Server) StartHTTPS(addr, certFile, keyFile string) error
- func (s *Server) Use(middleware ...func(http.Handler) http.Handler)
- func (s *Server) UseHandler(h http.Handler)
- func (s *Server) UseTop(middlewares ...func(http.Handler) http.Handler)
- type Service
- type Session
- type TestClient
- func (tc *TestClient) AssertFile(resp *http.Response, path string)
- func (tc *TestClient) AssertJSON(resp *http.Response, v, d interface{})
- func (tc *TestClient) ConsumePrefix(r *http.Response) bool
- func (tc *TestClient) GetToken()
- func (tc *TestClient) JSONBuffer(v interface{}) io.Reader
- func (tc *TestClient) ReadBody(r *http.Response, JSONPrefix bool) string
- func (tc *TestClient) Request(method, endpoint string, body io.Reader, processReq func(*http.Request), ...)
- type TestServer
- type Validator
- type VerboseError
Constants ¶
This section is empty.
Variables ¶
var ( OtherForegroundColor = "fdf6e3" WarningForegroundColor = "fdf6e3" ErrorForegroundColor = "fdf6e3" OtherBackgroundColor = "268bd2" WarningBackgroundColor = "b58900" ErrorBackgroundColor = "dc322f" )
Color codes for HTML error pages
var ( MalformedCookieError = errors.New("malformed cookie") SignatureVerificationFailedError = errors.New("signature verification failed") )
var Decoders = map[string]func(body io.Reader, v interface{}) error{ "application/json": JSONDecoder, "application/xml": XMLDecoder, "text/xml": XMLDecoder, "text/csv": CSVDecoder, }
POST data decoders. The key is the content type, the value is a decoder that decodes the contents of the Reader into v.
var EntityDBTypeMap = map[string]string{
"string": "character varying",
"int64": "int8",
"int32": "int4",
"int16": "int2",
"int": "int",
"float32": "float4",
"float64": "float8",
"bool": "bool",
"Time": "timestamp with time zone",
"struct": "jsonb",
}
EntityDBTypeMap maps Go types to PostgreSQL types
var ErrNoEndpoints = errors.New("no endpoints are enabled for this resource")
var ErrorPage = template.Must(template.New("ErrorPage").Parse(`<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta charset="utf8" />
<title>Error</title>
<style type="text/css">
body {
background-color: #{{.BackgroundColor}};
color: #{{.ForegroundColor}};
}
</style>
</head>
<body>
<h1>HTTP Error {{.Code}}</h1>
<p>{{.Message}}</p>
<hr/>
{{if .RequestID}}<p> Request ID: {{.RequestID}} </p>
<hr/>{{end}}
<pre>{{.Logs}}</pre>
</body>
</html>
`))
ErrorPage is the default HTML template for the standard HTML error page.
var JSONPrefix = true
JSONPrefix is a global switch for the ")]}',\n" JSON response prefix.
This prefix increases security for browser-based applications, but requires extra support on the client side.
var NoDecoderErr = errors.New("no decoder found for the request content type")
Functions ¶
func CSRFGetMiddleware ¶
CSRFGetMiddleware checks the CSRF token in the urlParam URL parameter.
This is useful if you want CSRF protection in a GET request. For example, this middleware is used on the auth service's login/logout endpoints. Adding this to the server is discouraged. The middlware should be used only on the individual handlers.
func CSRFMiddleware ¶
CSRFMiddleware enforces the correct X-CSRF-Token header on all POST, PUT, DELETE, PATCH requests.
To obtain a token, use CSRFTokenHandler on a path.
func CSRFTokenHandler ¶
func CSRFTokenHandler(w http.ResponseWriter, r *http.Request)
CSRFTokenHandler returns the valid csrf token for the current client.
The return format is either JSON or text.
func CSVDecoder ¶
CSVDecoder decodes the request body using the built-in CSV reader into v.
v must be *[][]string
func ConstraintErrorConverter ¶
func ConstraintErrorConverter(msgMap map[string]string) func(*pq.Error) VerboseError
ConstraintErrorConverter converts a constraint violation error into a user-friendly message.
func ConstraintExists ¶
ConstraintExists checks if a constraint exists in the database
func ConvertDBError ¶
func ConvertDBError(err error, conv func(*pq.Error) VerboseError) error
ConvertDBError converts an error with conv if that error is *pq.Error.
Useful when processing database errors (e.g. constraint violations), so the user can get a nice error message.
func DBErrorToVerboseString ¶
DBErrorToVerboseString is a helper function that converts a *pq.Error into a detailed string.
func DBMiddleware ¶
func DBMiddleware(connectString string, maxIdleConnections, maxOpenConnections int) (func(http.Handler) http.Handler, *sql.DB)
DBMiddleware manages the database connection. Currently only PostgreSQL is supported.
Automatically added to the server with PetBunny if the server has a connect string.
func Decode ¶
Decode decodes a request body into v. After decoding, it closes the body.
This function considers only the Content-Type header, and requires its presence. See the Decoders variable for more information.
func DefaultLoggerMiddleware ¶
DefaultLoggerMiddleware creates created a LoggerMiddleware with the recommended settings.
func ErrorHandlerMiddleware ¶
ErrorHandlerMiddleware injects an ErrorHandler into the request context, and then recovers if the ErrorHandler paniced.
The caller of the function should also supply a logger that will log the errors. The displayErrors sends the error messages to the user. This is useful in a development environment.
This middleware is automatically added to the Server with PetBunny.
func GetCSRFToken ¶
GetCSRFToken returns the CSRF token for the current session.
If the token is not exists, the function generates one and places it inside the session.
func GetParams ¶
func GetParams(r *http.Request) httprouter.Params
GetParams returns the path parameter values from the request.
func GetRequestID ¶
GetRequestID returns the current request's request id.
func HSTSMiddleware ¶
func HSTSMiddleware(config HSTSConfig) func(http.Handler) http.Handler
HSTSMiddleware adds HTTP Strict Transport Security headers to the responses.
func HTTPSRedirectServer ¶
HTTPSRedirectServe redirects HTTP requests to HTTPS.
httpsAddr and httpAddr must be host:port format, where the port can be omitted.
func Hop ¶
func Hop(configure func(cfg *viper.Viper, s *Server) error, cfg *viper.Viper, topMiddlewares ...func(http.Handler) http.Handler)
Hop sets up and starts a server.
This function is a wrapper around PetBunny(). The cfg parameter can be nil, in that case a new one will be created.
Extra viper values:
- secret: sets util.SetKey(). Must be a 32 byte hex-encoded string.
func JSONDecoder ¶
JSONDecoder decodes the request body using the built-in JSON decoder into v.
func LogVerbose ¶
LogVerbose returns the verbose level logger from the request context.
func LoggerMiddleware ¶
func LoggerMiddleware(level log.LogLevel, userLogFactory, verboseLogFactory, traceLogFactory func(w io.Writer) log.Logger, lw io.Writer) func(http.Handler) http.Handler
LoggerMiddleware injects a logger and a per request log buffer into the request context.
func MustDecode ¶
MustDecode is the same as Decode(), but it panics instead of returning an error.
When using the kit with the recommended settings, this method is recommended instead of Decode(), because the panic will get caught by the error handler middleware.
func Pager ¶
Pager is a function that implements pagination for listing endpoints.
It extracts the "page" query from the url, and returns the offset to that given page. The parameter limit specifies the number of elements on a given page.
func RedirectDestination ¶
RedirectDestination constucts an URL to the redirect destination.
The redirect destination is read from the destination URL parameter.
func RedirectServer ¶
RedirectServer sets up and starts a http server that redirects all requests to redirectAddr.
func RendererMiddleware ¶
RendererMiddleware is the middleware for the Render API.
This middleware is automatically added with PetBunny.
This changes the behavior of the ResponseWriter in the following middlewares and the page handler. The ResponseWriter's WriteHeader() method will not write the headers, just sets the Code attribute of the Renderer struct in the page context. This hack is necessary, because else a middleware could write the headers before the Renderer. Given the default configuration, the session middleware comes after the RendererMiddleware (so the session middleware has a chance to set its session cookie), and the session middleware always calls WriteHeader(). See the rendererResponseWriter.WriteHeader() method's documentation for more details.
func RequestIDMiddleware ¶
RequestIDMiddleware generates a request id for every request. Useful for logging.
func RequestLoggerMiddleware ¶
RequestLoggerMiddleware logs request data (method, length, path).
func RequestLogs ¶
RequestLogs returns the contents of the log buffer of the request.
func RestrictAddressMiddleware ¶
RestrictAddressMiddleware restricts access based on the IP address of the client.
Only IP addresses in the given CIDR address ranges will be allowed.
func RestrictPrivateAddressMiddleware ¶
RestrictPrivateAddressMiddleware restricts access to private addresses.
func SessionMiddleware ¶
func SessionMiddleware(prefix string, key SecretKey, cookieURL *url.URL, expiresAfter time.Duration) func(http.Handler) http.Handler
SessionMiddleware creates a session middleware.
The prefix is an optional prefix for the cookie name. The cookie name after the prefix is "_SESSION". The key holds the secret key to sign and verify the cookies. The cookie URL determines the domain and the path parts of the HTTP cookie that will be set. It can be nil. If the cookie URL starts with https://, then the cookie will be forced to work only on HTTPS. The expiresAfter sets a duration for the cookies to expire.
func SetContext ¶
SetContext sets a value in the context of *http.Request, and returns a new one with the updated context.
func TableExists ¶
TableExists checks if a table exists in the database.
func TransactionMiddleware ¶
TransactionMiddleware turns the DB connection in the context into a transaction.
The transaction gets committed automatically, or rolled back if an error occours.
func XMLDecoder ¶
XMLDecoder decodes the request body using the built-in XML decoder into v.
Types ¶
type DB ¶
type DB interface { Exec(string, ...interface{}) (sql.Result, error) Query(string, ...interface{}) (*sql.Rows, error) QueryRow(string, ...interface{}) *sql.Row Prepare(string) (*sql.Stmt, error) }
DB is an abstraction over *sql.DB and *sql.Tx
type DefaultResourceFormatter ¶
type DefaultResourceFormatter struct { }
DefaultResourceFormatter is a simple formatter that formats resources as HAL+JSON, JSON and XML.
func (*DefaultResourceFormatter) FormatMulti ¶
func (f *DefaultResourceFormatter) FormatMulti(res ResourceList, r *Renderer)
func (*DefaultResourceFormatter) FormatSingle ¶
func (f *DefaultResourceFormatter) FormatSingle(res Resource, r *Renderer)
type EndpointLinker ¶
EndpointLinker adds links and curies to an endpoint.
If an entity implements this, HAL data will be added to the response with the HALJSON Render type.
type Entity ¶
type Entity interface {
GetID() string
}
Entity is the interface for the entities.
Types implementing the Entity interface are expected to be pointers to structs.
type EntityController ¶
type EntityController struct {
// contains filtered or unexported fields
}
EntityController manages CRUD on entities.
func NewEntityController ¶
func NewEntityController(db DB) *EntityController
NewEntityController initializes an EntityController with a default database connection.
func (*EntityController) Add ¶
func (ec *EntityController) Add(e Entity, delegate EntityDelegate) *EntityController
Adds an entity type to the controller.
The entity parameter should be an empty entity.
func (*EntityController) AddDeleteEvent ¶
func (ec *EntityController) AddDeleteEvent(evt ...EntityWriteEvent) *EntityController
AddDeleteEvent adds a delete event handler to the entity controller.
func (*EntityController) AddInsertEvent ¶
func (ec *EntityController) AddInsertEvent(evt ...EntityWriteEvent) *EntityController
AddInsertEvent adds an insert event handler to the entity controller.
func (*EntityController) AddLoadEvent ¶
func (ec *EntityController) AddLoadEvent(evt ...EntityReadEvent) *EntityController
AddLoadEvent adds a load event handler to the entity controller.
func (*EntityController) AddUpdateEvent ¶
func (ec *EntityController) AddUpdateEvent(evt ...EntityWriteEvent) *EntityController
AddUpdateEvent adds an update event handler to the entity controller.
func (*EntityController) Delete ¶
func (ec *EntityController) Delete(db DB, e Entity) error
Delete deletes an entity from the database.
func (*EntityController) Empty ¶
func (ec *EntityController) Empty(name string) Entity
Empty creates a new empty value of the given entity.
func (*EntityController) FieldList ¶
func (ec *EntityController) FieldList(name string) string
FieldList returns a comma-separated list of the columns for the given entity.
func (*EntityController) Insert ¶
func (ec *EntityController) Insert(db DB, e Entity) error
Insert inserts an entity into the database.
func (*EntityController) Load ¶
func (ec *EntityController) Load(db DB, entityType string, keys ...interface{}) (Entity, error)
Load loads the given entity type for the given keys.
func (*EntityController) LoadFromQuery ¶
func (ec *EntityController) LoadFromQuery(db DB, entityType string, query string, args ...interface{}) ([]Entity, error)
LoadFromQuery loads entities from a query.
The entity is stored in the table that has the same name as the entity type (returned by the Type method). All fields must be included (FieldList returns a comma-separated list). Using a table alias is mandatory in this case. The table alias is returned by the TableAbbrev method.
Example:
tablename := ec.Type(&Ent{}) alias := ec.TableAbbrev(tablename) from := tablename + " " + alias entities, err := ec.LoadFromQuery(nil, tablename, `SELECT `+ec.FieldList(tablename)+` FROM `+from+` WHERE ...`, args...)
func (*EntityController) SchemaSQL ¶
func (ec *EntityController) SchemaSQL(e Entity) string
SchemaSQL creates a schema for the parameter entity.
func (*EntityController) TableAbbrev ¶
func (ec *EntityController) TableAbbrev(name string) string
TableAbbrev returns the table name abbreviation.
func (*EntityController) Type ¶
func (ec *EntityController) Type(e Entity) string
Type returns the name of the entity parameter.
func (*EntityController) Update ¶
func (ec *EntityController) Update(db DB, e Entity) error
Update updates an entity in the database.
func (*EntityController) Validate ¶
func (ec *EntityController) Validate(e Entity) error
Validate validates an entity.
type EntityDelegate ¶
EntityDelegate helps out EntityController to deal with an entity type.
type EntityDeleter ¶
EntityDeleter is implemented by an entity that uses a different method to delete itself from the database.
type EntityInserter ¶
EntityInserter is implemented by an entity that uses a different method to insert itself into the database.
type EntityReadEvent ¶
type EntityReadEvent interface { Before(entityType string, query string, args []interface{}) (string, []interface{}) After(entityType string, entities []Entity, err error) ([]Entity, error) }
EntityReadEvent is a read event handler for an *EntityController.
type EntityResourceConfig ¶
type EntityResourceConfig struct { PageLen int Validator func(data Resource, r *http.Request) DisableList bool DisablePost bool DisableGet bool DisablePut bool DisableDelete bool ListMiddlewares []func(http.Handler) http.Handler PostMiddlewares []func(http.Handler) http.Handler GetMiddlewares []func(http.Handler) http.Handler PutMiddlewares []func(http.Handler) http.Handler DeleteMiddlewares []func(http.Handler) http.Handler EntityResourceLister EntityResourceLoader EntityResourceExtraSchema }
EntityResourceConfig is the configuration struct for the EntityResource.
type EntityResourceExtraSchema ¶
EntityResourceExtraSchema generates extra schema that is appended to the entity's schema.
type EntityResourceLister ¶
type EntityResourceLister interface {
List(r *http.Request, start, limit int) (string, []interface{})
}
EntityResourceLister overrides the default listing of the entity controller.
type EntityResourceLoader ¶
EntityResourceLoader overrides the default loader of the entity controller.
type EntityUpdater ¶
EntityUpdater is implemented by an entity that uses a different method to update itself in the database.
type EntityWriteEvent ¶
type EntityWriteEvent interface { Before(entityType string, e Entity) After(entityType string, e Entity, err error) error }
EntityWriteEvent is a write event handler for an *EntityController.
type ErrorPageData ¶
type ErrorPageData struct { BackgroundColor string ForegroundColor string Code int Message string Logs string RequestID string }
ErrorPageData contains data for the ErrorPage template.
type HALCurie ¶
type HALCurie struct { Name string `json:"name"` Href string `json:"href"` Templated bool `json:"templated"` }
HALCurie contains documentation information for the endpoint.
type HSTSConfig ¶
HSTSConfig contains configuration for HSTSMiddleware.
func (HSTSConfig) String ¶
func (c HSTSConfig) String() string
type Panic ¶
type Panic struct { Code int Err error StackTrace string // contains filtered or unexported fields }
Panic is a custom panic data structure for the ErrorHandler.
func (Panic) ServeHTTP ¶
func (p Panic) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP outputs the error to the HTTP response.
It can render the error in 3 formats: HTML, JSON and text, depending on the Accept header. The default is HTML.
func (Panic) VerboseError ¶
type Renderer ¶
type Renderer struct { Code int // HTTP status code. // contains filtered or unexported fields }
Renderer is a per-request struct for the Render API.
The Render API handles content negotiation with the client. The server's preference is the order how the offers are added by either the AddOffer() low-level method or the JSON()/HTML()/Text() higher level methods.
A quick example how to use the Render API:
func pageHandler(w http.ResponseWriter, r *http.Request) { ... ab.Render(r). HTML(pageTemplate, data). JSON(data) }
In this example, the server prefers rendering an HTML page / fragment, but it can render a JSON if that's the client's preference. The default is HTML, because that is the first offer.
func (*Renderer) AddOffer ¶
func (r *Renderer) AddOffer(mediaType string, handler func(w http.ResponseWriter)) *Renderer
AddOffer adds an offer for the content negotiation.
See the Render() method for more information. The mediaType is the content type, the handler renders the data to the ResponseWriter. You probably want to use the JSON(), HTML(), Text() methods instead of this.
func (*Renderer) Binary ¶
Binary adds a binary file offer for the Renderer struct.
If reader is an io.ReadCloser, it will be closed automatically.
func (*Renderer) CSV ¶
CSV adds a CSV offer for the Renderer object.
Use this function for smaller CSV responses.
func (*Renderer) CSVChannel ¶
CSVChannel adds a CSV offer for the Renderer object.
The records are streamed through a channel.
func (*Renderer) CSVGenerator ¶
CSVGenerator adds a CSV offer for the Renderer object.
The records are generated with a generator function. If the function returns an error, the streaming to the output stops.
func (*Renderer) Render ¶
func (rr *Renderer) Render(w http.ResponseWriter, r *http.Request)
Render renders the best offer to the ResponseWriter according to the client's content type preferences.
type Resource ¶
type Resource interface { }
Resource labels data for CRUD operation through API endpoints.
type ResourceController ¶
type ResourceController struct { ResourceFormatter ExtraEndpoints func(s *Server) error // contains filtered or unexported fields }
ResourceController represents a CRUD service.
func EntityResource ¶
func EntityResource(ec *EntityController, entity Entity, config EntityResourceConfig) *ResourceController
EntityResource creates a ResourceController that exposes the entity's CRUD functions through API endpoints.
func NewResourceController ¶
func NewResourceController(delegate ResourceControllerDelegate) *ResourceController
NewResourceController creates a ResourceController with a given delegate and sensible defaults.
func (*ResourceController) AddDeleteEvent ¶
func (res *ResourceController) AddDeleteEvent(evt ...ResourceEvent) *ResourceController
AddDeleteEvent adds event handlers for the delete event.
func (*ResourceController) AddGetEvent ¶
func (res *ResourceController) AddGetEvent(evt ...ResourceEvent) *ResourceController
AddGetEvent adds event handlers for the get event.
func (*ResourceController) AddListEvent ¶
func (res *ResourceController) AddListEvent(evt ...ResourceListEvent) *ResourceController
AddListEvent adds event handlers for the list event.
func (*ResourceController) AddPostEvent ¶
func (res *ResourceController) AddPostEvent(evt ...ResourceEvent) *ResourceController
AddPostEvent adds event handlers for the post event.
func (*ResourceController) AddPutEvent ¶
func (res *ResourceController) AddPutEvent(evt ...ResourceEvent) *ResourceController
AddPutEvent adds event handlers for the put event.
func (*ResourceController) Delete ¶
func (res *ResourceController) Delete(d ResourceDeleteDelegate, middlewares ...func(http.Handler) http.Handler) *ResourceController
Delete enables the DELETE endpoint.
func (*ResourceController) Get ¶
func (res *ResourceController) Get(d ResourceGetDelegate, middlewares ...func(http.Handler) http.Handler) *ResourceController
Get enables the GET endpoint.
func (*ResourceController) GetName ¶
func (res *ResourceController) GetName() string
GetName returns the name of this ResourceController.
func (*ResourceController) List ¶
func (res *ResourceController) List(d ResourceListDelegate, middlewares ...func(http.Handler) http.Handler) *ResourceController
List enables the listing endpoint.
func (*ResourceController) Post ¶
func (res *ResourceController) Post(d ResourcePostDelegate, middlewares ...func(http.Handler) http.Handler) *ResourceController
Post enables the POST endpoint.
func (*ResourceController) Put ¶
func (res *ResourceController) Put(d ResourcePutDelegate, middlewares ...func(http.Handler) http.Handler) *ResourceController
Put enables the PUT endpoint.
func (*ResourceController) Register ¶
func (res *ResourceController) Register(srv *Server) error
func (*ResourceController) SchemaInstalled ¶
func (res *ResourceController) SchemaInstalled(db DB) bool
func (*ResourceController) SchemaSQL ¶
func (res *ResourceController) SchemaSQL() string
type ResourceControllerDelegate ¶
type ResourceControllerDelegate interface { GetName() string GetTables() []string GetSchemaSQL() string SchemaInstalled(db DB) bool }
ResourceControllerDelegate customizes a ResourceController.
type ResourceDeleteDelegate ¶
type ResourceDeleteDelegate interface { Load(id string, r *http.Request) (Resource, error) Delete(data Resource, r *http.Request) error }
ResourceDeleteDelegate helps a ResourceController to handle DELETE for a resource.
type ResourceEvent ¶
type ResourceEvent interface { Before(*http.Request, Resource) Inside(*http.Request, Resource) After(*http.Request, Resource) }
ResourceEvent is used as an event handler for ResourceController endpoints.
type ResourceEventCallback ¶
type ResourceEventCallback struct { BeforeCallback func(*http.Request, Resource) InsideCallback func(*http.Request, Resource) AfterCallback func(*http.Request, Resource) }
ResourceEventCallback is a simple implementation of ResourceEvent that invokes callbacks.
func (ResourceEventCallback) After ¶
func (c ResourceEventCallback) After(r *http.Request, res Resource)
type ResourceFormatter ¶
type ResourceFormatter interface { FormatSingle(Resource, *Renderer) FormatMulti(ResourceList, *Renderer) }
ResourceFormatter formats resources for the HTTP response.
type ResourceGetDelegate ¶
ResourceGetDelegate helps a ResourceController to handle GET for a resource.
type ResourceList ¶
type ResourceList struct { Items []Resource `json:"items"` Curies []HALCurie `json:"-"` Rels map[string][]interface{} `json:"-"` // contains filtered or unexported fields }
ResourceList is an extended list of resources.
func (ResourceList) MarshalJSON ¶
func (rl ResourceList) MarshalJSON() ([]byte, error)
type ResourceListDelegate ¶
type ResourceListDelegate interface { List(r *http.Request, start, limit int) ([]Resource, error) PageLength() int }
ResourceListDelegate helps a ResourceController to list resources.
type ResourceListEvent ¶
type ResourceListEvent interface { Before(*http.Request) After(*http.Request, *ResourceList) }
ResourceListEvent is used as an event handler for a listing endpoint.
type ResourceListEventCallback ¶
type ResourceListEventCallback struct { BeforeCallback func(*http.Request) AfterCallback func(*http.Request, *ResourceList) }
ResourceListEventCallback is a simple implementation of ResourceListEvent that invokes callbacks.
func (ResourceListEventCallback) After ¶
func (c ResourceListEventCallback) After(r *http.Request, res *ResourceList)
func (ResourceListEventCallback) Before ¶
func (c ResourceListEventCallback) Before(r *http.Request)
type ResourcePathOverrider ¶
ResourcePathOverrider can be implemented by a ResourceDelegate to change the path pattern for the given resource operation.
type ResourcePostDelegate ¶
type ResourcePostDelegate interface { Empty() Resource Validate(data Resource, r *http.Request) Insert(data Resource, r *http.Request) error }
ResourcePostDelegate helps a ResourceController to handle POST for a resource.
type ResourcePutDelegate ¶
type ResourcePutDelegate interface { Empty() Resource Load(id string, r *http.Request) (Resource, error) GetID(Resource) string Validate(data Resource, r *http.Request) Update(data Resource, r *http.Request) error }
ResourcePutDelegate helps a ResourceController to handle PUT for a resource.
type Server ¶
type Server struct { *httprouter.Router Logger *log.Log TLSConfig *tls.Config // contains filtered or unexported fields }
Server is the main server struct.
func PetBunny ¶
func PetBunny(cfg *viper.Viper, logger *log.Log, topMiddlewares ...func(http.Handler) http.Handler) (*Server, error)
PetBunny sets up a Server with recommended middlewares.
The parameters logger and eh can be nil, defaults will be log.DefaultOSLogger() and HandleErrors().
topMiddlewares are middlewares that gets applied right after the logger middlewares, but before anything else.
Viper has to be set up, and it has to contain a few values:
- CookieSecret string: hex representation of the key bytes. Must be set.
- db string: connection string to Postgres. Must be set.
- DBMaxIdleConn int: max idle connections. Defaults to 0 (no open connections are retained).
- DBMaxOpenConn int: max open connections. Defaults to 0 (unlimited).
- LogLevel int: log level for the logger. Use the numeric values of the log.LOG_* constants.
- hsts (hsts.maxage float, hsts.includesubdomains bool, hsts.hostblacklist []string): configuration values for the HSTS middleware. See HSTSConfig structure
- gzip bool: enabled the gzip middleware. Default is true.
- CookiePrefix string: prefix for the session and the csrf cookies.
- CookieURL string: domain and path configuration for the cookies.
- assetsDir string: assets directory. The value - skips setting it up.
- publicDir string: public directory. The value - skips setting it up.
- root bool: sets / to serve assetsDir/index.html. Default is true.
- hostwhitelist: a string array of hosts that are whitelisted for letsencrypt. If set, https will be enabled with letsencrypt.
func (*Server) AddLocalDir ¶
AddLocalDir adds a local directory to the router.
func (*Server) Delete ¶
func (s *Server) Delete(path string, handler http.Handler, middlewares ...func(http.Handler) http.Handler)
Delete adds a DELETE handler to the router.
func (*Server) DeleteF ¶
func (s *Server) DeleteF(path string, handler http.HandlerFunc, middlewares ...func(http.Handler) http.Handler)
DeleteF adds a DELETE HandlerFunc to the router.
func (*Server) EnableAutocert ¶
EnableAutocert adds autocert to the server.
caDirEndpoint points to a ca directory endpoint. cacheDir defaults to "private/autocert-cache" when empty. If you use the recommended app layout, leave it empty. hostWhitelist is a list of hosts where the SSL certificate is valid. Supply at least one domain, else it won't work.
func (*Server) EnableLetsEncrypt ¶
EnableLetsEncrypt adds autocert to the server with LetsEncrypt CA dir.
See the documentation of EnableAutocert for cacheDir and hostWhitelist
func (*Server) Get ¶
func (s *Server) Get(path string, handler http.Handler, middlewares ...func(http.Handler) http.Handler)
Get adds a GET handler to the router.
func (*Server) GetDBConnection ¶
GetDBConnection returns the server's DB connection if there's any.
func (*Server) GetF ¶
func (s *Server) GetF(path string, handler http.HandlerFunc, middlewares ...func(http.Handler) http.Handler)
GetF adds a GET HandlerFunc to the router.
func (*Server) Handle ¶
func (s *Server) Handle(method, path string, handler http.Handler, middlewares ...func(http.Handler) http.Handler)
Handle adds a handler to the router.
The middleware list will be applied to this handler only.
func (*Server) Handler ¶
Handler creates a http.Handler from the server (using the middlewares and the router).
func (*Server) Head ¶
func (s *Server) Head(path string, handler http.Handler, middlewares ...func(http.Handler) http.Handler)
Head adds a HEAD handler to the router.
func (*Server) HeadF ¶
func (s *Server) HeadF(path string, handler http.HandlerFunc, middlewares ...func(http.Handler) http.Handler)
HeadF adds a HEAD HandlerFunc to the router.
func (*Server) Options ¶
func (s *Server) Options(path string, handler http.Handler, middlewares ...func(http.Handler) http.Handler)
Options adds an OPTIONS handler to the router.
func (*Server) OptionsF ¶
func (s *Server) OptionsF(path string, handler http.HandlerFunc, middlewares ...func(http.Handler) http.Handler)
OptionsF adds an OPTIONS HandlerFunc to the router.
func (*Server) Patch ¶
func (s *Server) Patch(path string, handler http.Handler, middlewares ...func(http.Handler) http.Handler)
Patch adds a PATCH handler to the router.
func (*Server) PatchF ¶
func (s *Server) PatchF(path string, handler http.HandlerFunc, middlewares ...func(http.Handler) http.Handler)
PatchF adds a PATCH HandlerFunc to the router.
func (*Server) Post ¶
func (s *Server) Post(path string, handler http.Handler, middlewares ...func(http.Handler) http.Handler)
Post adds a POST handler to the router.
func (*Server) PostF ¶
func (s *Server) PostF(path string, handler http.HandlerFunc, middlewares ...func(http.Handler) http.Handler)
PostF adds a POST HandlerFunc to the router.
func (*Server) Put ¶
func (s *Server) Put(path string, handler http.Handler, middlewares ...func(http.Handler) http.Handler)
Put adds a PUT handler to the router.
func (*Server) PutF ¶
func (s *Server) PutF(path string, handler http.HandlerFunc, middlewares ...func(http.Handler) http.Handler)
PutF adds a PUT HandlerFunc to the router.
func (*Server) RegisterService ¶
RegisterService adds a service on the server.
See the Service interface for more information.
func (*Server) StartHTTPS ¶
StartHTTPS starts the server.
func (*Server) UseHandler ¶
UseHandler uses a http.Handler as a middleware.
type Service ¶
type Service interface { // Register the Service endpoints Register(*Server) error // Checks if the schema is installed SchemaInstalled(db DB) bool // Construct SQL string to install the schema SchemaSQL() string }
Service is a collection of endpoints that logically belong together or operate on the same part of the database schema.
type Session ¶
Session represents a session which will be stored in the session cookies.
func GetSession ¶
GetSession returns the session from the http request context.
type TestClient ¶
type TestClient struct { Client *http.Client Token string // contains filtered or unexported fields }
TestClient is a wrapper on the top of http.Client for integration tests.
func NewTestClient ¶
func NewTestClient(base string) *TestClient
NewTestClient initializes TestClient.
The wrapped http.Client will get an empty cookie jar.
func NewTestClientWithToken ¶
func NewTestClientWithToken(base string) *TestClient
NewTestClientWithToken initializes a TestClient and retrieves a CSRF token.
func (*TestClient) AssertFile ¶
func (tc *TestClient) AssertFile(resp *http.Response, path string)
AssertFile asserts that the response body is equal to a file.
func (*TestClient) AssertJSON ¶
func (tc *TestClient) AssertJSON(resp *http.Response, v, d interface{})
AssetJSON decodes the JSON body of the response into v, and matches it with d.
func (*TestClient) ConsumePrefix ¶
func (tc *TestClient) ConsumePrefix(r *http.Response) bool
ConsumePrefix consumes the JSONPrefix from the response body.
func (*TestClient) GetToken ¶
func (tc *TestClient) GetToken()
GetToken retrieves the token from the TestServer for TestClient.
func (*TestClient) JSONBuffer ¶
func (tc *TestClient) JSONBuffer(v interface{}) io.Reader
JSONBuffer creates an in-memory buffer of a serialized JSON value.
func (*TestClient) ReadBody ¶
func (tc *TestClient) ReadBody(r *http.Response, JSONPrefix bool) string
ReadBody reads the response body into a string.
func (*TestClient) Request ¶
func (tc *TestClient) Request(method, endpoint string, body io.Reader, processReq func(*http.Request), processResp func(*http.Response), statusCode int)
Request sends a request to a TestServer.
The method and endpoint parameters are mandatory. The body can be nil if the request does not have a body. The prcessReq function can modify the request, but it can be nil. The processResp function can deal with the response, but it can be nil as well. The statusCode parameter is the expected status code.
type TestServer ¶
TestServer is a temporary Server for integration tests.
func (*TestServer) StartAndCleanUp ¶
StartAndCleanUp takes control of the TestMain function.
It starts a Server and when the tests are finished it clears the database.
type Validator ¶
type Validator interface {
Validate() error
}
Validator interface is implemented by types that require validation during some point in their lifecycle.
type VerboseError ¶
type VerboseError interface { // Error that is displayed in the logs and debug messages. Should contain diagnostical information. Error() string // Error that is displayed to the end user. VerboseError() string }
VerboseError extends the built-in error interface with a message that is displayed to the end user.
func NewVerboseError ¶
func NewVerboseError(err, verboseMessage string) VerboseError
Creates a new verbose error message.
If err is an empty string, then verboseMessage will be used it instead.
func WrapError ¶
func WrapError(err error, verboseMessage string) VerboseError
WrapError wraps an error message into a VerboseError.