fastglue

package module
v1.8.0 Latest Latest
Warning

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

Go to latest
Published: Jan 24, 2024 License: MIT Imports: 17 Imported by: 11

README

fastglue

Overview Go Reference Zerodha Tech

fastglue is an opinionated, bare bones wrapper that glues together fasthttp and fasthttprouter to act as a micro HTTP framework. It helps eliminate boilerplate that would otherwise be required when using these two libraries to write HTTP servers. It enables:

  • Performance benefits of fasthttp + fasthttprouter.
  • Pre/post middleware hooks on HTTP handlers.
  • Simple middlewares for validating (existence, length range) of params in HTTP requests.
  • Functions for unmarshalling request payloads (Form encoding, JSON, XML) into arbitrary structs.
  • Shortcut functions for registering handlers, GET(), POST() etc.
  • Shortcut for fasthttp listening on TCP and Unix sockets.
  • Shortcut for graceful shutdown hook on the fasthttp server.
  • Opinionated JSON API response and error structures.
  • Shortcut functions for sending strings, bytes, JSON in the envelope structure without serialization or allocation.

Install

go get -u github.com/zerodha/fastglue

Usage

import "github.com/zerodha/fastglue"

Examples

Documentation

Index

Constants

View Source
const (
	// JSON is an alias for the JSON content type
	JSON = "application/json"

	// XML is an alias for the XML content type
	XML = "application/xml"

	// PLAINTEXT is an alias for the plaintext content type
	PLAINTEXT = "text/plain"

	// AuthBasic represents HTTP BasicAuth scheme.
	AuthBasic = 1 << iota
	// AuthToken represents the key:value Token auth scheme.
	AuthToken = 2
)

Variables

This section is empty.

Functions

func BadMethodHandler

func BadMethodHandler(r *fasthttp.RequestCtx)

BadMethodHandler produces an enveloped JSON response for 405 errors.

func NotFoundHandler

func NotFoundHandler(r *fasthttp.RequestCtx)

NotFoundHandler produces an enveloped JSON response for 404 errors.

func ScanArgs

func ScanArgs(args *fasthttp.Args, obj interface{}, fieldTag string) ([]string, error)

ScanArgs takes a fasthttp.Args set, takes its keys and values and applies them to a given struct using reflection. The field names are mapped to the struct fields based on a given tag tag. The field names that have been mapped are also return as a list. Supports string, bool, number types and their slices.

eg:

type Order struct {
	Tradingsymbol string `url:"tradingsymbol"`
	Tags []string `url:"tag"`
}

Types

type Envelope

type Envelope struct {
	Status    string      `json:"status"`
	Message   *string     `json:"message,omitempty"`
	Data      interface{} `json:"data"`
	ErrorType *ErrorType  `json:"error_type,omitempty"`
}

Envelope is a highly opinionated, "standardised", JSON response structure.

type ErrorType

type ErrorType string

ErrorType defines string error constants (eg: TokenException) to be sent with JSON responses.

type FastMiddleware

type FastMiddleware func(*Request) *Request

FastMiddleware is the fastglue middleware handler function that can be registered using Before() and After() functions.

type FastRequestHandler

type FastRequestHandler func(*Request) error

FastRequestHandler is the fastglue HTTP request handler function that wraps over the fasthttp handler.

func ReqLenParams

func ReqLenParams(h FastRequestHandler, fields map[string]int) FastRequestHandler

ReqLenParams is an (opinionated) middleware that checks if a given set of parameters are set in the GET or POST params and if each of them meets a minimum length criteria. If not, it fails the request with an error envelop.

func ReqLenRangeParams

func ReqLenRangeParams(h FastRequestHandler, fields map[string][2]int) FastRequestHandler

ReqLenRangeParams is an (opinionated) middleware that checks if a given set of parameters are set in the GET or POST params and if each of them meets a minimum and maximum length range criteria. If not, it fails the request with an error envelop.

func ReqParams

func ReqParams(h FastRequestHandler, fields []string) FastRequestHandler

ReqParams is an (opinionated) middleware that checks if a given set of parameters are set in the GET or POST params. If not, it fails the request with an error envelope.

type Fastglue

type Fastglue struct {
	Router *fasthttprouter.Router
	Server *fasthttp.Server

	MatchedRoutePathParam string
	// contains filtered or unexported fields
}

Fastglue is the "glue" wrapper over fasthttp and fasthttprouter.

func New

func New() *Fastglue

New creates and returns a new instance of Fastglue.

func NewGlue

func NewGlue() *Fastglue

NewGlue creates and returns a new instance of Fastglue with custom error handlers pre-bound.

func (*Fastglue) After

func (f *Fastglue) After(fm ...FastMiddleware)

After registers a fastglue middleware that's executed after a registered handler has finished executing. This is useful to do things like central request logging.

func (*Fastglue) Any

func (f *Fastglue) Any(path string, h FastRequestHandler)

Any is fastglue's wrapper over fasthttprouter's handler that attaches a FastRequestHandler to all GET, POST, PUT, DELETE methods.

func (*Fastglue) Before

func (f *Fastglue) Before(fm ...FastMiddleware)

Before registers a fastglue middleware that's executed before an HTTP request is handed over to the registered handler. This is useful for doing "global" checks, for instance, session and cookies.

func (*Fastglue) DELETE

func (f *Fastglue) DELETE(path string, h FastRequestHandler)

DELETE is fastglue's wrapper over fasthttprouter's handler.

func (*Fastglue) GET

func (f *Fastglue) GET(path string, h FastRequestHandler)

GET is fastglue's wrapper over fasthttprouter's handler.

func (*Fastglue) HEAD

func (f *Fastglue) HEAD(path string, h FastRequestHandler)

HEAD is fastglue's wrapper over fasthttprouter's handler.

func (*Fastglue) Handler

func (f *Fastglue) Handler() func(*fasthttp.RequestCtx)

Handler returns fastglue's central fasthttp handler that can be registered to a fasthttp server instance.

func (*Fastglue) ListenAndServe

func (f *Fastglue) ListenAndServe(address string, socket string, s *fasthttp.Server) error

ListenAndServe is a wrapper for fasthttp.ListenAndServe. It takes a TCP address, an optional UNIX socket file path and starts listeners, and an optional fasthttp.Server.

func (*Fastglue) ListenServeAndWaitGracefully

func (f *Fastglue) ListenServeAndWaitGracefully(address string, socket string, s *fasthttp.Server, shutdownServer chan struct{}) error

ListenServeAndWaitGracefully accepts the same parameters as ListenAndServe along with a channel which can receive a signal to shutdown the server.

func (*Fastglue) NotFound added in v1.8.0

func (f *Fastglue) NotFound(h FastRequestHandler)

NotFound is fastglue's wrapper over fasthttprouter's `router.NotFound` handler.

func (*Fastglue) OPTIONS

func (f *Fastglue) OPTIONS(path string, h FastRequestHandler)

OPTIONS is fastglue's wrapper over fasthttprouter's handler.

func (*Fastglue) POST

func (f *Fastglue) POST(path string, h FastRequestHandler)

POST is fastglue's wrapper over fasthttprouter's handler.

func (*Fastglue) PUT

func (f *Fastglue) PUT(path string, h FastRequestHandler)

PUT is fastglue's wrapper over fasthttprouter's handler.

func (*Fastglue) ServeStatic

func (f *Fastglue) ServeStatic(path string, rootPath string, listDirectory bool)

ServeStatic serves static files under `rootPath` on `path` urls. The `path` must end with "/{filepath:*}", files are then served from the local path /defined/root/dir/{filepath:*}. For example `path` can be "/static/{filepath:*}" and `rootPath` as "./dist/static/" to serve all the files "./dist/static/*" as "/static/*". `listDirectory` option enables or disables directory listing.

func (*Fastglue) SetContext

func (f *Fastglue) SetContext(c interface{})

SetContext sets a "context" which is shared and made available in every HTTP request. This is useful for injecting dependencies such as config structs, DB connections etc. Be very careful to only include immutable variables and thread-safe objects.

func (*Fastglue) Shutdown

func (f *Fastglue) Shutdown(s *fasthttp.Server, shutdownComplete chan error)

Shutdown gracefully shuts down the server without interrupting any active connections. It accepts a fasthttp.Server instance along with an error channel, to which it sends a signal with a nil/error after shutdown is complete. It is safe to exit the program after receiving this signal.

The following is taken from the fasthttp docs and applies to fastglue shutdown. Shutdown works by first closing all open listeners and then waiting indefinitely for all connections to return to idle and then shut down.

When Shutdown is called, Serve, ListenAndServe, and ListenAndServeTLS immediately return nil. Make sure the program doesn't exit and waits instead for Shutdown to return.

Shutdown does not close keepalive connections so its recommended to set ReadTimeout to something else than 0.

type MockRequest

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

MockRequest represents a single mock request.

func (*MockRequest) AssertBody

func (mr *MockRequest) AssertBody(body []byte)

AssertBody asserts the response body of the request against the given body.

func (*MockRequest) AssertJSON

func (mr *MockRequest) AssertJSON(body []byte)

AssertJSON asserts the JSON response of the body of the request against the given body.

func (*MockRequest) AssertStatus

func (mr *MockRequest) AssertStatus(code int)

AssertStatus asserts the response code of the request against the given code.

func (*MockRequest) GetReq

func (mr *MockRequest) GetReq() *Request

GetReq returns the underlying fastglue.Request that's set on the MockRequest.

type MockResponse

type MockResponse struct {
	StatusCode  int
	ContentType string
	Body        []byte
}

MockResponse represents a mock response produced by the mock server.

type MockServer

type MockServer struct {
	Server *httptest.Server
	// contains filtered or unexported fields
}

MockServer is a mock HTTP server. It uses an httptest.Server mock server that can take an HTTP request and respond with a mock response.

func NewMockServer

func NewMockServer() *MockServer

NewMockServer initializes a mock HTTP server against which any request be sent, and the request can be responded to with a mock response.

func (*MockServer) Do

Do returns a new request handler with which a mock request is made. It takes an HTTP handler and executes it against the given request. The assert.Assertions is optional.

Since there's no real HTTP server+handler that originates the request to the handler, an artificial request (req) context has to be provided.

upstreamResp is the body with which the mock server should respond to the request.

Example:

req := &fastglue.Request{
	RequestCtx: &fasthttp.RequestCtx{Request: *fasthttp.AcquireRequest()},
	Context:    app,
}

req.RequestCtx.Request.SetRequestURI("/fake/path/to/simulate")

req.RequestCtx.SetUserValue("user", authUser{
	UserID: testUser,
	AppID:  1,
})

func (*MockServer) Handle

func (m *MockServer) Handle(method, uri string, r MockResponse)

Handle registers a mock response handler.

func (*MockServer) NewFastglueReq

func (m *MockServer) NewFastglueReq() *Request

NewFastglueReq returns an empty fastglue.Request that can be filled and used to pass to actual fastglue handlers to mock incoming HTTP requests.

func (*MockServer) Reset

func (m *MockServer) Reset()

Reset resets existing registered mock response handlers.

func (*MockServer) URL

func (m *MockServer) URL() string

URL returns the URL of the mock server that can be used as the mock upstream server.

type Request

type Request struct {
	RequestCtx *fasthttp.RequestCtx
	Context    interface{}
}

Request is a wrapper over fasthttp's RequestCtx that's injected into request handlers.

func (*Request) Decode

func (r *Request) Decode(v interface{}, tag string) error

Decode unmarshals the Post body of a fasthttp request based on the ContentType header into value pointed to by v, as long as the content is JSON or XML.

func (*Request) DecodeFail

func (r *Request) DecodeFail(v interface{}, tag string) error

DecodeFail uses Decode() to unmarshal the Post body, but in addition to returning an error on failure, writes the error to the HTTP response directly. This helps avoid repeating read/parse/validate boilerplate inside every single HTTP handler.

func (*Request) ParseAuthHeader

func (r *Request) ParseAuthHeader(schemes uint8) ([]byte, []byte, error)

ParseAuthHeader parses the Authorization header and returns an api_key and access_token based on the auth schemes passed as bit flags (eg: AuthBasic, AuthBasic | AuthToken etc.).

func (*Request) Redirect

func (r *Request) Redirect(url string, code int, args map[string]interface{}, anchor string) error

Redirect redirects to the given URL. Accepts optional query args and anchor tags. Test : curl -I -L -X GET "localhost:8000/redirect"

func (*Request) RedirectURI added in v1.7.0

func (r *Request) RedirectURI(uri string, code int, args map[string]interface{}, anchor string) error

RedirectURI redirects to the given URI. If URI contains hostname, scheme etc then its stripped and only path is used for the redirect. Used for internal app redirect and to prevent open redirect vulnerabilities.

func (*Request) SendBytes

func (r *Request) SendBytes(code int, ctype string, v []byte) error

SendBytes writes a []byte payload to the HTTP response and also sets a given ContentType header.

func (*Request) SendEnvelope

func (r *Request) SendEnvelope(data interface{}) error

SendEnvelope is a highly opinionated method that sends success responses in a predefined structure which has become customary at Rainmatter internally.

func (*Request) SendErrorEnvelope

func (r *Request) SendErrorEnvelope(code int, message string, data interface{}, et ErrorType) error

SendErrorEnvelope is a highly opinionated method that sends error responses in a predefined structure which has become customary at Rainmatter internally.

func (*Request) SendJSON

func (r *Request) SendJSON(code int, v interface{}) error

SendJSON takes an interface, marshals it to JSON, and writes the result to the HTTP response. It implicitly sets ContentType to application/json.

func (*Request) SendString

func (r *Request) SendString(code int, v string) error

SendString writes a string payload to the HTTP response. It implicitly sets ContentType to plain/text.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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