gimlet

package module
v0.0.0-...-245537e Latest Latest
Warning

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

Go to latest
Published: Feb 14, 2024 License: Apache-2.0 Imports: 43 Imported by: 76

README

===================================
''``gimlet`` -- HTTP/JSON API Toolkit
===================================

``gimlet`` is a simple collection of tools for creating simple
versioned JSON/HTTP APIs. It builds on standard library tools and
components of `gorilla <http://www.gorillatoolkit.org/>`_ (mux) and
`negroni <https://github.com/codegangsta/negroni>`_.

The goal: 

- Allow developers to implement HTTP/JSON APIs by writing
  `http.HandlerFunc <http://golang.org/pkg/net/#HandlerFunc>`_ methods
  and passing `encoding/json <http://golang.org/pkg/encoding/json/>`_ 
  marshallable types to simple response-writing methods. 
  
- Make it easy to define a set of routes with a version prefix, and
  manage the version prefix at the routing layer rather than in
  handlers. 
  
- Reuse common components as necessary, and avoid recreating existing
  tools or making a large inflexible tool.
  
In short I was writing a JSON/HTTP API, and wanted the above
properties and found that I had written a little library that didn't
really have anything to do with the app I was writing so I'm spinning
it out both because *I* want to use this in my next project and I hope
you may find it useful.

You can `read an introductory blog post
<http://www.tychoish.com/posts/have-a-gimlet-a-go-json-http-api-toolkit/>`_,
if you like. 

Documentation

Overview

Package gimlet is a toolkit for building JSON/HTTP interfaces (e.g. REST).

Gimlet builds on standard library and common tools for building web applciations (e.g. Negroni and gorilla,) and is only concerned with JSON/HTTP interfaces, and omits support for aspects of HTTP applications outside of the scope of JSON APIs (e.g. templating, sessions.) Gimilet attempts to provide minimal convinences on top of great infrastucture so that your application can omit boilerplate and you don't have to build potentially redundant infrastructure.

Index

Constants

This section is empty.

Variables

View Source
var ErrNeedsReauthentication = errors.New("user session has expired so they must be reauthenticated")

Functions

func AddLoggingAnnotation

func AddLoggingAnnotation(r *http.Request, key string, value interface{})

AddLoggingAnnotation adds a key-value pair to be added to logging messages used by the application logging information, overwriting any previous value for the key. This will noop if the logger hasn't already been set up.

func AssembleHandler

func AssembleHandler(router *mux.Router, apps ...*APIApp) (http.Handler, error)

AssembleHandler takes a router and one or more applications and returns an application.

Eventually the router will become an implementation detail of this/related functions.

func AttachUser

func AttachUser(ctx context.Context, u User) context.Context

AttachUser adds a user to a context. This function is public to support teasing workflows.

func GetJSON

func GetJSON(r io.ReadCloser, data interface{}) error

GetJSON parses JSON from a io.ReadCloser (e.g. http/*Request.Body or http/*Response.Body) into an object specified by the request. Used in handler functiosn to retreve and parse data submitted by the client.

Returns an error if the body is greater than 16 megabytes in size.

func GetJSONUnlimited

func GetJSONUnlimited(r io.ReadCloser, data interface{}) error

GetJSONUnlimited reads data from a io.ReadCloser, as with GetJSON, but does not bound the size of the request.

func GetLogger

func GetLogger(ctx context.Context) grip.Journaler

GetLogger produces a special logger attached to the request. If no request is attached, GetLogger returns a logger instance wrapping the global sender.

func GetRequestID

func GetRequestID(ctx context.Context) int

GetRequestID returns the unique (monotonically increaseing) ID of the request since startup

func GetVars

func GetVars(r *http.Request) map[string]string

GetVars is a helper method that processes an http.Request and returns a map of strings to decoded strings for all arguments passed to the method in the URL. Use this helper function when writing handler functions.

func GetYAML

func GetYAML(r io.ReadCloser, data interface{}) error

GetYAML parses YAML from a io.ReadCloser (e.g. http/*Request.Body or http/*Response.Body) into an object specified by the request. Used in handler functiosn to retreve and parse data submitted by the client.u

func GetYAMLUnlimited

func GetYAMLUnlimited(r io.ReadCloser, data interface{}) error

GetYAMLUnlimited reads data from a io.ReadCloser, as with GetYAML, but does not bound the size of the request.

func HasPermission

func HasPermission(rm RoleManager, opts PermissionOpts, roles []Role) bool

func MergeApplications

func MergeApplications(apps ...*APIApp) (http.Handler, error)

MergeApplications takes a number of gimlet applications and resolves them, returning an http.Handler.

func MergeApplicationsWithRouter

func MergeApplicationsWithRouter(router *mux.Router, apps ...*APIApp) (http.Handler, error)

MergeApplicationsWithRouter takes a preconfigured router and a number of gimlet applications and resolves them, returning an http.Handler.

func SetURLVars

func SetURLVars(r *http.Request, val map[string]string) *http.Request

SetURLVars sets URL variables for testing purposes only.

func WriteBinary

func WriteBinary(w http.ResponseWriter, data interface{})

WriteBinary writes the data, converted to a byte slice as possible, to the response body, with a successful status code.

func WriteBinaryError

func WriteBinaryError(w http.ResponseWriter, data interface{})

WriteBinaryError write the data, converted to a byte slice as possible, to the response body with a bad-request (e.g. 400) response code.

func WriteBinaryInternalError

func WriteBinaryInternalError(w http.ResponseWriter, data interface{})

WriteBinaryInternalError write the data, converted to a byte slice as possible, to the response body with an internal server error (e.g. 500) response code.

func WriteBinaryResponse

func WriteBinaryResponse(w http.ResponseWriter, code int, data interface{})

WriteBinaryResponse writes binary data to a response with the specified code.

func WriteCSV

func WriteCSV(w http.ResponseWriter, data interface{})

WriteCSV is a helper function to write arrays of data in CSV format to a response body. Use this to write the data with a

func WriteCSVError

func WriteCSVError(w http.ResponseWriter, data interface{})

func WriteCSVInternalError

func WriteCSVInternalError(w http.ResponseWriter, data interface{})

func WriteCSVResponse

func WriteCSVResponse(w http.ResponseWriter, status int, data interface{})

WriteToCSVResponse takes in an interface that is a slice or an array and converts the struct to csv for fields that have the the csv struct tag.

func WriteHTML

func WriteHTML(w http.ResponseWriter, data interface{})

WriteHTML writes the data, converted to text as possible, to the response body as HTML with a successful status code.

func WriteHTMLError

func WriteHTMLError(w http.ResponseWriter, data interface{})

WriteHTMLError write the data, converted to text as possible, to the response body as HTML with a bad-request (e.g. 400) response code.

func WriteHTMLInternalError

func WriteHTMLInternalError(w http.ResponseWriter, data interface{})

WriteHTMLInternalError write the data, converted to text as possible, to the response body as HTML with an internal server error (e.g. 500) response code.

func WriteHTMLResponse

func WriteHTMLResponse(w http.ResponseWriter, code int, data interface{})

WriteHTMLResponse writes an HTML response with the specified error code.

func WriteJSON

func WriteJSON(w http.ResponseWriter, data interface{})

WriteJSON is a helper method to write JSON data to the body of an HTTP request and return 200 (successful.)

func WriteJSONError

func WriteJSONError(w http.ResponseWriter, data interface{})

WriteJSONError is a helper method to write JSON data to the body of an HTTP request and return 400 (user error.)

func WriteJSONInternalError

func WriteJSONInternalError(w http.ResponseWriter, data interface{})

WriteJSONInternalError is a helper method to write JSON data to the body of an HTTP request and return 500 (internal error.)

func WriteJSONResponse

func WriteJSONResponse(w http.ResponseWriter, code int, data interface{})

WriteJSONResponse writes a JSON document to the body of an HTTP request, setting the return status of to 500 if the JSON seralization process encounters an error, otherwise return

func WriteResponse

func WriteResponse(rw http.ResponseWriter, resp Responder)

func WriteText

func WriteText(w http.ResponseWriter, data interface{})

WriteText writes the data, converted to text as possible, to the response body, with a successful status code.

func WriteTextError

func WriteTextError(w http.ResponseWriter, data interface{})

WriteTextError write the data, converted to text as possible, to the response body with a bad-request (e.g. 400) response code.

func WriteTextInternalError

func WriteTextInternalError(w http.ResponseWriter, data interface{})

WriteTextInternalError write the data, converted to text as possible, to the response body with an internal server error (e.g. 500) response code.

func WriteTextResponse

func WriteTextResponse(w http.ResponseWriter, code int, data interface{})

WriteTextResponse writes data to the response body with the given code as plain text after attempting to convert the data to a byte array.

func WriteYAML

func WriteYAML(w http.ResponseWriter, data interface{})

WriteYAML is a helper method to write YAML data to the body of an HTTP request and return 200 (successful.)

func WriteYAMLError

func WriteYAMLError(w http.ResponseWriter, data interface{})

WriteYAMLError is a helper method to write YAML data to the body of an HTTP request and return 400 (user error.)

func WriteYAMLInternalError

func WriteYAMLInternalError(w http.ResponseWriter, data interface{})

WriteYAMLInternalError is a helper method to write YAML data to the body of an HTTP request and return 500 (internal error.)

func WriteYAMLResponse

func WriteYAMLResponse(w http.ResponseWriter, code int, data interface{})

WriteYAMLResponse writes a YAML document to the body of an HTTP request, setting the return status of to 500 if the YAML seralization process encounters an error, otherwise return

Types

type APIApp

type APIApp struct {
	StrictSlash    bool
	SimpleVersions bool
	NoVersions     bool
	// contains filtered or unexported fields
}

APIApp is a structure representing a single API service.

func GetPProfApp

func GetPProfApp() *APIApp

GetPProfApp produces an APIApp that has routes registered for pprof access. The routes themselves are copied from the standard library but configured for integration into an existing gimlet-based application.

func NewApp

func NewApp() *APIApp

NewApp returns a pointer to an application instance. These instances have reasonable defaults and include middleware to: recover from panics in handlers, log information about the request, and gzip compress all data. Users must specify a default version for new methods.

func (*APIApp) AddCORS

func (a *APIApp) AddCORS(opts cors.Options) *APIApp

func (*APIApp) AddMiddleware

func (a *APIApp) AddMiddleware(m Middleware)

AddMiddleware adds a negroni handler as middleware to the end of the current list of middleware handlers.

All Middleware is added before the router. If your middleware depends on executing within the context of the router/muxer, add it as a wrapper.

func (*APIApp) AddPrefixRoute

func (a *APIApp) AddPrefixRoute(prefix string) *APIRoute

AddPrefixRoute creates and registers a new route with an application matching everything under the given prefix.

func (*APIApp) AddRoute

func (a *APIApp) AddRoute(r string) *APIRoute

AddRoute is the primary method for creating and registering a new route with an application. Use as the root of a method chain, passing this method the path of the route.

func (*APIApp) AddWrapper

func (a *APIApp) AddWrapper(m Middleware)

AddWrapper adds a negroni handler as a wrapper for a specific route.

These wrappers execute in the context of the router/muxer. If your middleware does not need access to the muxer's state, add it as a middleware.

func (*APIApp) BackgroundRun

func (a *APIApp) BackgroundRun(ctx context.Context) (WaitFunc, error)

BackgroundRun is a non-blocking form of Run that allows you to manage a service running in the background.

func (*APIApp) Handler

func (a *APIApp) Handler() (http.Handler, error)

Handler returns a handler interface for integration with other server frameworks.

func (*APIApp) Merge

func (a *APIApp) Merge(apps ...*APIApp) error

Merge takes multiple application instances and merges all of their routes into a single application.

You must only call Merge once per base application, and you must pass more than one or more application to merge. Additionally, it is not possible to merge applications into a base application that has a prefix specified.

When the merging application does not have a prefix, the merge operation will error if you attempt to merge applications that have duplicate cases. Similarly, you cannot merge multiple applications that have the same prefix: you should treat these errors as fatal.

func (*APIApp) PrefixRoute

func (a *APIApp) PrefixRoute(p string) *APIRoute

PrefixRoute allows you to create a new route with a prefix. Prefixes override the applications global prefix.

func (*APIApp) ResetMiddleware

func (a *APIApp) ResetMiddleware()

ResetMiddleware removes *all* middleware handlers from the current application.

func (*APIApp) Resolve

func (a *APIApp) Resolve() error

Resolve processes the data in an application instance, including all routes and creats a mux.Router object for the application instance.

func (*APIApp) RestWrappers

func (a *APIApp) RestWrappers()

RestWrappers removes all route-specific middleware from the current application.

func (*APIApp) Route

func (a *APIApp) Route() *APIRoute

Route returns a route object without a route name configured.

func (*APIApp) Router

func (a *APIApp) Router() (*mux.Router, error)

Router is the getter for an APIApp's router object. If thetr application isn't resolved, then the error return value is non-nil.

func (*APIApp) Routes

func (a *APIApp) Routes() []*APIRoute

func (*APIApp) Run

func (a *APIApp) Run(ctx context.Context) error

Run configured API service on the configured port. Before running the application, Run also resolves any sub-apps, and adds all routes.

If you cancel the context that you pass to run, the application will gracefully shutdown, and wait indefinitely until the application has returned. To get different waiting behavior use BackgroundRun.

func (*APIApp) SetHost

func (a *APIApp) SetHost(name string) error

SetHost sets the hostname or address for the application to listen on. Errors after resolving the application. You do not need to set this, and if unset the application will listen on the specified port on all interfaces.

func (*APIApp) SetPort

func (a *APIApp) SetPort(port int) error

SetPort allows users to configure a default port for the API service. Defaults to 3000, and return errors will refuse to set the port to something unreasonable.

func (*APIApp) SetPrefix

func (a *APIApp) SetPrefix(p string)

SetPrefix sets the route prefix, adding a leading slash, "/", if necessary.

type APIRoute

type APIRoute struct {
	// contains filtered or unexported fields
}

APIRoute is a object that represents each route in the application and includes the route and associate internal metadata for the route.

func (*APIRoute) AllMethods

func (r *APIRoute) AllMethods() *APIRoute

func (*APIRoute) ClearWrappers

func (r *APIRoute) ClearWrappers()

ClearWrappers resets the routes middlware wrappers.

func (*APIRoute) Delete

func (r *APIRoute) Delete() *APIRoute

Delete is a chainable method to add a handler for the DELETE method to the current route. Routes may specify multiple methods.

func (*APIRoute) Get

func (r *APIRoute) Get() *APIRoute

Get is a chainable method to add a handler for the GET method to the current route. Routes may specify multiple methods.

func (*APIRoute) GetRoute

func (r *APIRoute) GetRoute() string

func (*APIRoute) Handler

func (r *APIRoute) Handler(h http.HandlerFunc) *APIRoute

Handler makes it possible to register an http.HandlerFunc with a route. Chainable. The common pattern for implementing these functions is to write functions and methods in your application that *return* handler functions, so you can pass application state or other data into to the handlers when the applications start, without relying on either global state *or* running into complex typing issues.

func (*APIRoute) HandlerType

func (r *APIRoute) HandlerType(h http.Handler) *APIRoute

HandlerType is equivalent to Handler, but allows you to use a type that implements http.Handler rather than a function object.

func (*APIRoute) HasMethod

func (r *APIRoute) HasMethod(method string) bool

func (*APIRoute) Head

func (r *APIRoute) Head() *APIRoute

Head is a chainable method to add a handler for the HEAD method to the current route. Routes may specify multiple methods.

func (*APIRoute) IsValid

func (r *APIRoute) IsValid() bool

IsValid checks if a route has is valid and populated.

func (*APIRoute) Method

func (r *APIRoute) Method(m string) *APIRoute

Method makes it possible to specify an HTTP method pragmatically.

func (*APIRoute) Options

func (r *APIRoute) Options() *APIRoute

func (*APIRoute) OverridePrefix

func (r *APIRoute) OverridePrefix() *APIRoute

OverridePrefix forces the route's prefix to override the global app prefix. By default, the route's prefix is combined (after a version) with the application's prefix.

When setting override prefix on an application that has a prefix specified, this option will not take effect in cases where you're merging multiple applications together.

func (*APIRoute) Patch

func (r *APIRoute) Patch() *APIRoute

Patch is a chainable method to add a handler for the PATCH method to the current route. Routes may specify multiple methods.

func (*APIRoute) Post

func (r *APIRoute) Post() *APIRoute

Post is a chainable method to add a handler for the POST method to the current route. Routes may specify multiple methods.

func (*APIRoute) Prefix

func (r *APIRoute) Prefix(p string) *APIRoute

Prefix allows per-route prefixes, which will override the application's global prefix if set.

func (*APIRoute) Proxy

func (r *APIRoute) Proxy(opts ProxyOptions) *APIRoute

Proxy adds a simple reverse proxy handler to the specified route, based on the options described in the ProxyOption structure. In most cases you'll want to specify a route matching pattern that captures all routes that begin with a specific prefix.

func (*APIRoute) Put

func (r *APIRoute) Put() *APIRoute

Put is a chainable method to add a handler for the PUT method to the current route. Routes may specify multiple methods.

func (*APIRoute) Route

func (r *APIRoute) Route(route string) *APIRoute

Route allows you to set or reset the route path on an existing route.

func (*APIRoute) RouteHandler

func (r *APIRoute) RouteHandler(h RouteHandler) *APIRoute

RouteHandler defines a handler defined using the RouteHandler interface, which provides additional infrastructure for defining handlers, to separate input parsing, business logic, and response generation.

func (*APIRoute) String

func (r *APIRoute) String() string

func (*APIRoute) Version

func (r *APIRoute) Version(version int) *APIRoute

Version allows you to specify an integer for the version of this route. Version is chainable.

func (*APIRoute) Wrap

func (r *APIRoute) Wrap(m ...Middleware) *APIRoute

Wrap adds a middleware that is applied specifically to this route. Route-specific middlware is applied after application specific middleware (when there's a route or application prefix) and before global application middleware (when merging applications without prefixes.)

type Authenticator

type Authenticator interface {
	CheckResourceAccess(User, string) bool
	CheckGroupAccess(User, string) bool
	CheckAuthenticated(User) bool
}

Authenticator represents a service that answers specific authentication related questions, and is the public interface used for authentication workflows.

func GetAuthenticator

func GetAuthenticator(ctx context.Context) Authenticator

GetAuthenticator returns an the attached interface to the context. If there is no authenticator attached, then GetAutenticator returns nil.

func NewBasicAuthenticator

func NewBasicAuthenticator(groups, resources map[string][]string) Authenticator

func NewSimpleAuthenticator

func NewSimpleAuthenticator(users []User, groups map[string][]string) Authenticator

NewSimpleAuthenticator constructs a minimum viable authenticate implementation, backed by access lists and user tables passed to the constructor. The Authenicator is, therefore, functionally immutable after construction.

type BasicUser

type BasicUser struct {
	ID           string   `bson:"_id" json:"id" yaml:"id"`
	Name         string   `bson:"name" json:"name" yaml:"name"`
	EmailAddress string   `bson:"email" json:"email" yaml:"email"`
	Password     string   `bson:"password" json:"password" yaml:"password"`
	Key          string   `bson:"key" json:"key" yaml:"key"`
	AccessToken  string   `bson:"access_token" json:"access_token" yaml:"access_token"`
	RefreshToken string   `bson:"refresh_token" json:"refresh_token" yaml:"refresh_token"`
	AccessRoles  []string `bson:"roles" json:"roles" yaml:"roles"`
	// contains filtered or unexported fields
}

func NewBasicUser

func NewBasicUser(opts BasicUserOptions) *BasicUser

NewBasicUser constructs a simple user. The underlying type has serialization tags.

func (*BasicUser) DisplayName

func (u *BasicUser) DisplayName() string

func (*BasicUser) Email

func (u *BasicUser) Email() string

func (*BasicUser) GetAPIKey

func (u *BasicUser) GetAPIKey() string

func (*BasicUser) GetAccessToken

func (u *BasicUser) GetAccessToken() string

func (*BasicUser) GetRefreshToken

func (u *BasicUser) GetRefreshToken() string

func (*BasicUser) HasPermission

func (u *BasicUser) HasPermission(opts PermissionOpts) bool

func (*BasicUser) Roles

func (u *BasicUser) Roles() []string

func (*BasicUser) Username

func (u *BasicUser) Username() string

type BasicUserManager

type BasicUserManager struct {
	// contains filtered or unexported fields
}

BasicUserManager implements the UserManager interface and has a list of BasicUsers which is passed into the constructor.

func (*BasicUserManager) ClearUser

func (b *BasicUserManager) ClearUser(u User, all bool) error

func (*BasicUserManager) CreateUserToken

func (um *BasicUserManager) CreateUserToken(username, password string) (string, error)

CreateUserToken finds the user with the same username and password in its list of users and creates a token that is a combination of the index of the list the user is at, the email address and a hash of the username and password and returns that token.

func (*BasicUserManager) GetGroupsForUser

func (b *BasicUserManager) GetGroupsForUser(userId string) ([]string, error)

func (*BasicUserManager) GetLoginCallbackHandler

func (*BasicUserManager) GetLoginCallbackHandler() http.HandlerFunc

func (*BasicUserManager) GetLoginHandler

func (*BasicUserManager) GetLoginHandler(string) http.HandlerFunc

func (*BasicUserManager) GetOrCreateUser

func (um *BasicUserManager) GetOrCreateUser(u User) (User, error)

func (*BasicUserManager) GetUserByID

func (um *BasicUserManager) GetUserByID(id string) (User, error)

func (*BasicUserManager) GetUserByToken

func (um *BasicUserManager) GetUserByToken(_ context.Context, token string) (User, error)

GetUserByToken does a find by creating a temporary token from the index of the user on the list, the email of the user and a hash of the username and password, checking it against the token string and returning a User if there is a match.

func (*BasicUserManager) IsRedirect

func (*BasicUserManager) IsRedirect() bool

func (*BasicUserManager) ReauthorizeUser

func (um *BasicUserManager) ReauthorizeUser(user User) error

type BasicUserOptions

type BasicUserOptions struct {
	// contains filtered or unexported fields
}

func NewBasicUserOptions

func NewBasicUserOptions(id string) (BasicUserOptions, error)

func (BasicUserOptions) AccessToken

func (opts BasicUserOptions) AccessToken(token string) BasicUserOptions

func (BasicUserOptions) Email

func (opts BasicUserOptions) Email(email string) BasicUserOptions

func (BasicUserOptions) Key

func (BasicUserOptions) Name

func (opts BasicUserOptions) Name(name string) BasicUserOptions

func (BasicUserOptions) Password

func (opts BasicUserOptions) Password(password string) BasicUserOptions

func (BasicUserOptions) RefreshToken

func (opts BasicUserOptions) RefreshToken(token string) BasicUserOptions

func (BasicUserOptions) RoleManager

func (opts BasicUserOptions) RoleManager(rm RoleManager) BasicUserOptions

func (BasicUserOptions) Roles

func (opts BasicUserOptions) Roles(roles ...string) BasicUserOptions

type ErrorResponse

type ErrorResponse struct {
	StatusCode   int    `bson:"status" json:"status" yaml:"status"`
	Message      string `bson:"message" json:"message" yaml:"message"`
	message.Base `bson:"metadata" json:"metadata" yaml:"metadata"`
}

ErrorResponse implements the Error() interface and provides a common type for routes to use for returning payloads in error conditions.

ErrorResponse also implements grip's message.Composer interface which can simplify some error reporting on the client side.

func (ErrorResponse) Error

func (e ErrorResponse) Error() string

func (ErrorResponse) Loggable

func (e ErrorResponse) Loggable() bool

func (ErrorResponse) Raw

func (e ErrorResponse) Raw() interface{}

func (ErrorResponse) String

func (e ErrorResponse) String() string

type FindResourceFunc

type FindResourceFunc func(*http.Request) ([]string, int, error)

type HandlerFuncWrapper

type HandlerFuncWrapper func(http.HandlerFunc) http.HandlerFunc

HandlerFuncWrapper provides a way to define a middleware as a function rather than a type.

func (HandlerFuncWrapper) ServeHTTP

ServeHTTP provides a gimlet.Middleware compatible shim for HandlerFuncWrapper-typed middlewares.

type HandlerWrapper

type HandlerWrapper func(http.Handler) http.Handler

HandlerWrapper provides a way to define a middleware as a function rather than a type for improved interoperability with native tools.

func (HandlerWrapper) ServeHTTP

func (w HandlerWrapper) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)

ServeHTTP provides a gimlet.Middleware compatible shim for HandlerWrapper-typed middlewares.

type Middleware

type Middleware negroni.Handler

Middleware is a local alias for negroni.Handler types.

func MakeRecoveryLogger

func MakeRecoveryLogger() Middleware

MakeRecoveryLoger constructs a middleware layer that logs request start, end, and recovers from panics (logging the panic as well).

This logger uses the default grip logger.

func MergeMiddleware

func MergeMiddleware(mws ...Middleware) Middleware

MergeMiddleware combines a number of middleware into a single middleware instance.

func NewAppLogger

func NewAppLogger() Middleware

NewAppLogger creates an logging middlear instance suitable for use with Negroni. Sets the logging configuration to be the same as the default global grip logging object.

func NewAuthenticationHandler

func NewAuthenticationHandler(a Authenticator, um UserManager) Middleware

NewAuthenticationHandler produces middleware that attaches Authenticator and UserManager instances to the request context, enabling the use of GetAuthenticator and GetUserManager accessors.

While your application can have multiple authentication mechanisms, a single request can only have one authentication provider associated with it.

func NewGroupMembershipRequired

func NewGroupMembershipRequired(name string) Middleware

NewGroupMembershipRequired provides middleware that requires that users belong to a group to gain access to a resource. This is access is defined as a property of the authentication system.

func NewGzipDefault

func NewGzipDefault() Middleware

NewGzipDefault produces a gzipping middleware with default compression.

func NewGzipSize

func NewGzipSize() Middleware

NewGzipSize produces a gzipping middleware with best compression.

func NewGzipSpeed

func NewGzipSpeed() Middleware

NewGzipSpeed produces a gzipping middleware with fastest compression.

func NewRecoveryLogger

func NewRecoveryLogger(j grip.Journaler) Middleware

NewRecoveryLogger logs request start, end, and recovers from panics (logging the panic as well).

func NewRequireAuthHandler

func NewRequireAuthHandler() Middleware

NewRequireAuthHandler provides middlesware that requires that users be authenticated generally to access the resource, but does no validation of their access.

func NewRestrictAccessToUsers

func NewRestrictAccessToUsers(userIDs []string) Middleware

NewRestrictAccessToUsers allows you to define a list of users that may access certain resource. This is similar to "groups," but allows you to control access centrally rather than needing to edit or change user documents.

This middleware is redundant to the "access required middleware."

func NewRoleRequired

func NewRoleRequired(role string) Middleware

NewRoleRequired provides middlesware that requires a specific role to access a resource. This access is defined as a property of the user objects.

func NewStatic

func NewStatic(prefix string, fs http.FileSystem) Middleware

NewStatic provides a convince wrapper around negroni's static file server middleware.

func RequiresPermission

func RequiresPermission(opts RequiresPermissionMiddlewareOpts) Middleware

RequiresPermission allows a route to specify that access to a given resource in the route requires a certain permission at a certain level. The resource ID must be defined somewhere in the URL as mux.Vars. The specific URL params to check need to be sent in the last parameter of this function, in order of most to least specific

func UserMiddleware

func UserMiddleware(um UserManager, conf UserMiddlewareConfiguration) Middleware

UserMiddleware produces a middleware that parses requests and uses the UserManager attached to the request to find and attach a user to the request.

func WrapperHandlerMiddleware

func WrapperHandlerMiddleware(w HandlerWrapper) Middleware

WrapperHandlerMiddleware is convenience function to produce middlewares from functions that wrap http.Handlers.

func WrapperMiddleware

func WrapperMiddleware(w HandlerFuncWrapper) Middleware

WrapperMiddleware is convenience function to produce middlewares from functions that wrap http.HandlerFuncs.

type OutputFormat

type OutputFormat int

OutputFormat enumerates output formats for response writers.

const (
	JSON OutputFormat = iota
	TEXT
	HTML
	YAML
	BINARY
	CSV
)

Enumerations of supported output formats used by gimlet rendering facilities.

func (OutputFormat) ContentType

func (o OutputFormat) ContentType() string

ContentType returns a mime content-type string for output formats produced by gimlet's rendering.

func (OutputFormat) IsValid

func (o OutputFormat) IsValid() bool

IsValid provides a predicate to validate OutputFormat values.

func (OutputFormat) String

func (o OutputFormat) String() string

type Page

type Page struct {
	BaseURL         string
	KeyQueryParam   string
	LimitQueryParam string

	Key      string
	Limit    int
	Relation string
	// contains filtered or unexported fields
}

Page represents the metadata required to build pagination links. To build the page, the route must have access to the full realized path, including any extra query parameters, to make it possible to build the metadata.

func (p *Page) GetLink(route string) string

GetLink returns the pagination metadata for this page. It is called by the GetLinks function. Your code need not use this call directly in most cases, except for testing.

func (*Page) Validate

func (p *Page) Validate() error

Validate ensures that the page has populated all of the required data. Additionally Validate parses the BaseURL, and *must* be called before GetLink.

type PermissionOpts

type PermissionOpts struct {
	Resource      string
	ResourceType  string
	Permission    string
	RequiredLevel int
}

PermissionOpts is the required data to be provided when asking if a user has permission for a resource

type Permissions

type Permissions map[string]int

type ProxyOptions

type ProxyOptions struct {
	HeadersToDelete   []string
	HeadersToAdd      map[string]string
	RemotePrefix      string
	StripSourcePrefix bool
	TargetPool        []string
	FindTarget        func(*http.Request) ([]string, error)
	RemoteScheme      string
	ErrorHandler      func(http.ResponseWriter, *http.Request, error)
	Transport         http.RoundTripper
}

ProxyOptions describes a simple reverse proxy service that can be the handler for a route in an application. The proxy implementation can modify the headers of the request. Requests are delgated to backends in the target pool

func (*ProxyOptions) Validate

func (opts *ProxyOptions) Validate() error

Validate checks the default configuration of a proxy configuration.

type RenderTemplate

type RenderTemplate interface {
	ExecuteTemplate(io.Writer, string, interface{}) error
}

RenderTemplate describes the common interface used by Renderer implementations to interact with text or html templates.

type Renderer

type Renderer interface {
	GetTemplate(...string) (RenderTemplate, error)
	Render(io.Writer, interface{}, string, ...string) error
	Stream(http.ResponseWriter, int, interface{}, string, ...string)
	WriteResponse(http.ResponseWriter, int, interface{}, string, ...string)
}

Renderer descibes an interface used to provide template caching and streaming for Go standard library templates.

func NewHTMLRenderer

func NewHTMLRenderer(opts RendererOptions) Renderer

NewHTMLRenderer returns a Renderer implementation that wraps html/template and provides caching and streaming to http responses.

func NewTextRenderer

func NewTextRenderer(opts RendererOptions) Renderer

NewTextRenderer returns an implementation of Renderer that and provides wrappers around text/template for template caching and streaming.

type RendererOptions

type RendererOptions struct {
	Functions    map[string]interface{}
	Directory    string
	Encoding     string
	DisableCache bool
}

RendererOptions descibes the common options passed to the renderer constructors.

type RequiresPermissionMiddlewareOpts

type RequiresPermissionMiddlewareOpts struct {
	RM             RoleManager
	PermissionKey  string
	ResourceType   string
	RequiredLevel  int
	ResourceLevels []string
	DefaultRoles   []Role
	ResourceFunc   FindResourceFunc
}

RequiresPermissionMiddlewareOpts defines what permissions the middleware shoud check and how. The ResourceFunc parameter can be used to specify custom behavior to extract a valid resource name from request variables

type Responder

type Responder interface {
	// Validate returns an error if the page is not properly
	// constructed, although it is implementation specific, what
	// constitutes an invalid page.
	Validate() error

	// The data aspect of the interface holds the body of the
	// response. Implementations may handle multiple calls to
	// AddData differently, and provide different levels of
	// validation.
	Data() interface{}
	AddData(interface{}) error

	// Format represents the serialization format (and/or MIME
	// type) of the data payload on output. These options are
	// defined in gimlet, which supports JSON, YAML, Plain Text,
	// HTML, and Binary.
	Format() OutputFormat
	SetFormat(OutputFormat) error

	// Status returns the HTTP static code for this
	// responses. SetStatus implementations should not allow users
	// to set invalid statuses.
	Status() int
	SetStatus(int) error

	// The ResponsePage methods add and return the pagination
	// metdata for this route.
	//
	// Implementations should return nil pages to have an
	// unpaginated response.
	Pages() *ResponsePages
	SetPages(*ResponsePages) error
}

Responder is an interface for constructing a response from a route. Fundamentally Responders are data types, and provide setters and getters to store data that

In general, users will use one of gimlets response implementations, though clients may wish to build their own implementations to provide features not present in the existing

func MakeJSONErrorResponder

func MakeJSONErrorResponder(err error) Responder

MakeJSONErrorResponder takes an error object and converts it into a responder object that wrap's gimlet's ErrorResponse type. Since ErrorResponse implements the error interface, if you pass an ErrorResposne object, this function will propagate the status code specified in the ErrorResponse if that code is valid, otherwise the status code of the request and the response object will be 400.

func MakeJSONInternalErrorResponder

func MakeJSONInternalErrorResponder(err error) Responder

MakeJSONInternalErrorResponder takes an error object and converts it into a responder object that wrap's gimlet's ErrorResponse type. Since ErrorResponse implements the error interface, if you pass an ErrorResposne object, this function will propagate the status code specified in the ErrorResponse if that code is valid, otherwise the status code of the request and the response object will be 500.

func MakeTextErrorResponder

func MakeTextErrorResponder(err error) Responder

MakeTextErrorResponder takes an error object and converts it into a responder object that wrap's gimlet's ErrorResponse type. Since ErrorResponse implements the error interface, if you pass an ErrorResposne object, this function will propagate the status code specified in the ErrorResponse if that code is valid, otherwise the status code of the request and the response object will be 400.

func MakeTextInternalErrorResponder

func MakeTextInternalErrorResponder(err error) Responder

MakeTextInternalErrorResponder takes an error object and converts it into a responder object that wrap's gimlet's ErrorResponse type. Since ErrorResponse implements the error interface, if you pass an ErrorResposne object, this function will propagate the status code specified in the ErrorResponse if that code is valid, otherwise the status code of the request and the response object will be 500.

func MakeYAMLErrorResponder

func MakeYAMLErrorResponder(err error) Responder

MakeYAMLErrorResponder takes an error object and converts it into a responder object that wrap's gimlet's ErrorResponse type. Since ErrorResponse implements the error interface, if you pass an ErrorResposne object, this function will propagate the status code specified in the ErrorResponse if that code is valid, otherwise the status code of the request and the response object will be 400.

func MakeYAMLInternalErrorResponder

func MakeYAMLInternalErrorResponder(err error) Responder

MakeYAMLInternalErrorResponder takes an error object and converts it into a responder object that wrap's gimlet's ErrorResponse type. Since ErrorResponse implements the error interface, if you pass an ErrorResposne object, this function will propagate the status code specified in the ErrorResponse if that code is valid, otherwise the status code of the request and the response object will be 500.

func NewBasicResponder

func NewBasicResponder(s int, f OutputFormat, data interface{}) (Responder, error)

NewBasicResponder constructs a Responder from the arguments passed to the constructor, though interface remains mutable.

This implementation only allows a single data object, and AddData will overwrite existing data as set.

func NewBinaryErrorResponse

func NewBinaryErrorResponse(data interface{}) Responder

func NewBinaryInternalErrorResponse

func NewBinaryInternalErrorResponse(data interface{}) Responder

func NewBinaryResponse

func NewBinaryResponse(data interface{}) Responder

func NewHTMLErrorResponse

func NewHTMLErrorResponse(data interface{}) Responder

func NewHTMLInternalErrorResponse

func NewHTMLInternalErrorResponse(data interface{}) Responder

func NewHTMLResponse

func NewHTMLResponse(data interface{}) Responder

func NewJSONErrorResponse

func NewJSONErrorResponse(data interface{}) Responder

func NewJSONInternalErrorResponse

func NewJSONInternalErrorResponse(data interface{}) Responder

func NewJSONResponse

func NewJSONResponse(data interface{}) Responder

func NewResponseBuilder

func NewResponseBuilder() Responder

NewResponseBuilder constructs a Responder implementation that can be used to incrementally build a with successive calls to AddData().

The builder defaults to JSON ouptut format and a 200 response code.

func NewTextErrorResponse

func NewTextErrorResponse(data interface{}) Responder

func NewTextInternalErrorResponse

func NewTextInternalErrorResponse(data interface{}) Responder

func NewTextResponse

func NewTextResponse(data interface{}) Responder

func NewYAMLErrorResponse

func NewYAMLErrorResponse(data interface{}) Responder

func NewYAMLInternalErrorResponse

func NewYAMLInternalErrorResponse(data interface{}) Responder

func NewYAMLResponse

func NewYAMLResponse(data interface{}) Responder

type ResponsePages

type ResponsePages struct {
	Next *Page
	Prev *Page
}

ResponsePages holds pagination metadata for a route built with the Responder interface.

The pagination types and methods are

func (r *ResponsePages) GetLinks(route string) string

GetLinks returns the strings for use in the links header

func (*ResponsePages) Validate

func (r *ResponsePages) Validate() error

Validate checks each page, if present, and ensures that the pagination metadata are consistent.

type Role

type Role struct {
	ID          string      `json:"id" bson:"_id"`
	Name        string      `json:"name" bson:"name"`
	Scope       string      `json:"scope" bson:"scope"`
	Permissions Permissions `json:"permissions" bson:"permissions"`
	Owners      []string    `json:"owners" bson:"owners"`
}

Role is the data structure used to read and manipulate user roles and permissions

type RoleManager

type RoleManager interface {
	// GetAllRoles returns all roles known by the manager
	GetAllRoles() ([]Role, error)

	// GetAllRoles returns roles matching the specified IDs
	GetRoles([]string) ([]Role, error)

	// DeleteRole deletes a single role
	DeleteRole(string) error

	// UpdateRole adds the given role to the manager if it does not exist, or updates the role
	// with the same ID
	UpdateRole(Role) error

	// FilterForResource takes a list of roles and returns the subset of those applicable for a certain resource
	FilterForResource([]Role, string, string) ([]Role, error)

	// FilterScopesByResourceType takes a list of scope IDs and a resource
	// type and returns a list of scopes filtered by the resource type.
	FilterScopesByResourceType([]string, string) ([]Scope, error)

	// FindScopeForResources returns a scope that exactly matches a given set of resources
	FindScopeForResources(string, ...string) (*Scope, error)

	// AddScope adds a scope to the manager
	AddScope(Scope) error

	// DeleteScope removes a scope from the manager
	DeleteScope(Scope) error

	// GetScope returns the given scope
	GetScope(context.Context, string) (*Scope, error)

	// AddResourceToScope adds the specified resource to the given scope, updating parents
	AddResourceToScope(string, string) error

	// RemoveResourceFromScope deletes the specified resource from the given scope, updating parents
	RemoveResourceFromScope(string, string) error

	// RegisterPermissions adds a list of strings to the role manager as valid permission keys. Returns an
	// error if the same permission is registered more than once
	RegisterPermissions([]string) error

	// FindRoleWithResources returns all roles that apply to exactly the given resources
	FindRolesWithResources(string, []string) ([]Role, error)

	// FindRolesWithPermissions returns a role that exactly matches the given resources and permissions
	FindRoleWithPermissions(string, []string, Permissions) (*Role, error)

	// Clear deletes all roles and scopes. This should only be used in tests
	Clear() error

	// IsValidPermissions checks if the passed permissions are registered
	IsValidPermissions(Permissions) error
}

RoleManager provides methods to get and set role data and is often used along with Users to check permissions

type RouteHandler

type RouteHandler interface {
	// Factory produces, this makes it possible for you to store
	// request-scoped data in the implementation of the Handler
	// rather than attaching data to the context. The factory
	// allows gimlet to, internally, reconstruct a handler interface
	// for every request.
	//
	// Factory is always called at the beginning of the request.
	Factory() RouteHandler

	// Parse makes it possible to modify the request context and
	// populate the implementation of the RouteHandler. This also
	// allows you to isolate your interaction with the request
	// object.
	Parse(context.Context, *http.Request) error

	// Runs the core buinsess logic for the route, returning a
	// Responder interface to provide structure around returning
	//
	// Run methods do not return an error. Implementors are
	// responsible for forming a response, even in error cases.
	Run(context.Context) Responder
}

RouteHandler provides an alternate method for defining routes with the goals of separating the core operations of handling a rest result.

type Scope

type Scope struct {
	ID          string   `json:"id" bson:"_id"`
	Name        string   `json:"name" bson:"name"`
	Type        string   `json:"type" bson:"type"`
	Resources   []string `json:"resources" bson:"resources"`
	ParentScope string   `json:"parent" bson:"parent"`
}

Scope describes one or more resources and can be used to roll up certain resources into others

type Server

type Server interface {
	Close() error
	ListenAndServe() error
	ListenAndServeTLS(string, string) error
	Serve(net.Listener) error
	Shutdown(context.Context) error

	// Run provides a simple wrapper around default http.Server
	// functionality to allow clean shutdown that uses a context
	// with a wait function
	Run(context.Context) (WaitFunc, error)
	// GetServer allows you to access the underlying http server.
	GetServer() *http.Server
}

Server provides a wrapper around *http.Server methods, with an Run method which provides a clean-shutdown compatible listen operation.

func BuildNewServer

func BuildNewServer(addr string, n http.Handler, tlsConf *tls.Config) (Server, error)

BuildNewServer constructs a new server that uses TLS, returning an error if you pass a nil TLS configuration.

func NewServer

func NewServer(addr string, n http.Handler) (Server, error)

NewServer constructs a server based on a handler and an address. Uses a default 1 minute timeout.

type ServerConfig

type ServerConfig struct {
	Timeout time.Duration
	Handler http.Handler
	App     *APIApp
	TLS     *tls.Config
	Address string
	Info    string
	// contains filtered or unexported fields
}

func (*ServerConfig) Resolve

func (c *ServerConfig) Resolve() (Server, error)

Resolve validates a config and constructs a server from the configuration if possible.

func (*ServerConfig) Validate

func (c *ServerConfig) Validate() error

Validate returns an error if there are any problems with a ServerConfig that would make it impossible to render a server from the configuration.

type User

type User interface {
	DisplayName() string
	Email() string
	Username() string
	GetAPIKey() string
	GetAccessToken() string
	GetRefreshToken() string
	Roles() []string
	HasPermission(PermissionOpts) bool
}

User provides a common way of interacting with users from authentication systems.

Note: this is the User interface from Evergreen with the addition of the Roles() method.

func GetUser

func GetUser(ctx context.Context) User

GetUser returns the user attached to the request. The User object is nil when

type UserManager

type UserManager interface {
	// The first 5 methods are borrowed directly from evergreen without modification
	GetUserByToken(context.Context, string) (User, error)
	CreateUserToken(string, string) (string, error)
	// GetLoginHandler returns the function that starts the login process for auth mechanisms
	// that redirect to a thirdparty site for authentication
	GetLoginHandler(url string) http.HandlerFunc
	// GetLoginRedirectHandler returns the function that does login for the
	// user once it has been redirected from a thirdparty site.
	GetLoginCallbackHandler() http.HandlerFunc

	// IsRedirect returns true if the user must be redirected to a
	// thirdparty site to authenticate.
	// TODO: should add a "do redirect if needed".
	IsRedirect() bool

	// ReauthorizeUser reauthorizes a user that is already logged in.
	ReauthorizeUser(User) error

	// These methods are simple wrappers around the user
	// persistence layer. May consider moving them to the
	// authenticator.
	GetUserByID(string) (User, error)
	GetOrCreateUser(User) (User, error)

	// Log out user or all users
	ClearUser(user User, all bool) error

	// Returns the groups or roles to which a user belongs
	GetGroupsForUser(string) ([]string, error)
}

UserManager sets and gets user tokens for implemented authentication mechanisms, and provides the data that is sent by the api and ui server after authenticating

func GetUserManager

func GetUserManager(ctx context.Context) UserManager

GetUserManager returns the attached UserManager to the current request, returning nil if no such object is attached.

func NewBasicUserManager

func NewBasicUserManager(users []BasicUser, rm RoleManager) (UserManager, error)

NewBasicUserManager is a constructor to create a BasicUserManager from a list of basic users. It requires a user created by NewBasicUser.

func NewMultiUserManager

func NewMultiUserManager(readWrite []UserManager, readOnly []UserManager) UserManager

NewMultiUserManager multiplexes several UserManagers into a single UserManager. For write operations, UserManager methods are only invoked on the UserManagers that can read and write. For read operations, the UserManager runs the method against all managers until one returns a valid result. Managers are prioritized in the same order in which they are passed into this function and read/write managers take priority over read-only managers.

type UserMiddlewareConfiguration

type UserMiddlewareConfiguration struct {
	SkipCookie      bool
	SkipHeaderCheck bool
	HeaderUserName  string
	HeaderKeyName   string
	CookieName      string
	CookiePath      string
	CookieTTL       time.Duration
	CookieDomain    string
}

UserMiddlewareConfiguration is an keyed-arguments struct used to produce the user manager middleware.

func (UserMiddlewareConfiguration) AttachCookie

func (umc UserMiddlewareConfiguration) AttachCookie(token string, rw http.ResponseWriter)

AttachCookie sets a cookie with the specified cookie to the request, according to the configuration of the user manager.

func (UserMiddlewareConfiguration) ClearCookie

func (umc UserMiddlewareConfiguration) ClearCookie(rw http.ResponseWriter)

ClearCookie removes the cookie defied in the user manager.

func (*UserMiddlewareConfiguration) Validate

func (umc *UserMiddlewareConfiguration) Validate() error

Validate ensures that the UserMiddlewareConfiguration is correct and internally consistent.

type WaitFunc

type WaitFunc func(context.Context)

WaitFunc is a function type returned by some functions that allows callers to wait on background processes started by the returning function.

If the context passed to a wait function is canceled then the wait function should return immediately. You may wish to pass contexts with a different timeout to the wait function from the one you passed to the outer function to ensure correct waiting semantics.

Directories

Path Synopsis
cmd
Package ldap provides an LDAP authentication service.
Package ldap provides an LDAP authentication service.

Jump to

Keyboard shortcuts

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