uf

package module
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: Apr 6, 2022 License: BSD-3-Clause Imports: 9 Imported by: 2

README

Microframework

A set of utility functions and a wrapper around HTTPRouter. I wrote this to help me learn go and therefore will forever be in a state of flux as my skills improve.

License

BSD-3-clause

Documentation

Overview

A set of utility functions and a router provided by HTTPRouter (https://github.com/julienschmidt/httprouter).

Example:

import (

"github.com/blacksfk/uf"
// ...

)

func main() {
	// create a new server
	config := &uf.Config{...}

	// middlewareX and Y are middleware that will be applied to every route defined
	server := uf.NewServer(config, middlewareX, middlewareY, ...)

	// configure CORS or any other settings exported by HTTPRouter
	server.GlobalOPTIONS = func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Access-Control-Request-Method") != "" {
			h := w.Header()

			h.Set("Access-Control-Allow-Methods", header.Get("Allow"))
			h.Set("Access-Control-Allow-Origin", "example.com")

			// ...
		}

		// reply to options
		w.WriteHeader(http.StatusNoContent)
	}

	// add routes to the server (supports GET, POST, PUT, PATCH, DELETE convenience methods)
	// middleware functions X, Y, A, B, C will be called before the handler in order
	server.Get("/book", handler, middlewareA, middlewareB, middlewareC)

	// ...

	// add route groups to the server
	// middleware functions X, Y, A, B will be called in order before each middleware
	// and handler defined below
	server.Group("/author", middlewareA, middlewareB).

		// middlewareC will be called after X, Y, A, and B but only for GET requests on this route
		Get(author.HandleGet, middlewareC).

		// middlewareD will be called after X, Y, A, and B for the following route definitions
		Middleware(middlewareD).
		Post(author.HandlePost).
		Put(author.HandlePut).

		// middlewareE will be called after X, Y, A, B, and D but only for PATCH
		// requests on this route
		Patch(author.HandlePatch, middlewareE).
		Delete(author.HandleDelete)

	// start the server
	e := http.ListenAndServe("localhost:6060", server)

	// ...
}
func handler(w http.ResponseWriter, r *http.Request) error {
	books := database.ObtainBooks()

	return uf.SendJSON(w, books)
}
func middlewareA(r *http.Request) error {
	// get the auth key and user (somehow)
	key := r.Header.Get("Authorization")
	user := database.FindUser()

	if !user.Valid(key) {
		// user needs to re-authenticate
		return uf.Unauthorized("Invalid login")
	}

	// authenticated
	*r = *r.WithContext(user.ToContext(r.Context()))

	// progress to next handler
	return nil
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DecodeBodyJSON

func DecodeBodyJSON(r *http.Request, ptr interface{}) error

Decode the request body into ptr. Returns a 400 Bad Request error if the received Content-Type header is not application/json.

func EmbedParams

func EmbedParams(r *http.Request, params ...Param)

Embed Param into a request's context. To be used for testing purposes only.

func GetParam

func GetParam(r *http.Request, name string) string

Get a URL parameter.

In order to test handlers that require parameters to operate, a mock request shoud be created and then passed to EmbedParams with the parameters the controller method needs to perform its task. Example (error handling omitted for the sake of brevity):

// URL: example.com/mk/:char r, _ := http.NewRequest(http.MethodGet, "example.com/mk/kitana", nil)

uf.EmbedParams(r, httprouter.Param{Key: "char", Value: "kitana"}, ...)

w := http.NewRecorder()

controller.Handle(w, r)

// determine whether the test case passes...

func GetParamInt

func GetParamInt(r *http.Request, name string) (int, error)

Get a URL parameter type-cast as an int. See GetParam for an example on how to test parameters in handlers.

func GetParamInt64

func GetParamInt64(r *http.Request, name string) (int64, error)

Get a URL parameter as an int64. See GetParam for an example on how to test parameters in handlers.

func LogStdout

func LogStdout(r *http.Request, duration int64, unit string)

Logs requests to stdout. Format: "method uri duration(unit)s"

func NewHttpTestHandler

func NewHttpTestHandler(h Handler) http.Handler

Create a test queue in order to use and test the uf.Handler with functions that only accept http.Handler. Eg. httptest.NewServer.

func ReadBody

func ReadBody(r *http.Request, contentTypes ...string) ([]byte, error)

Returns the bytes read from r.Body. Returns a Bad Request error if the received Content-Type header does not match any of the provided content types.

func SendErrorJSON

func SendErrorJSON(w http.ResponseWriter, he HttpError) error

Send an HttpError as a JSON response

func SendJSON

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

Send a JSON response

Types

type AccessLogger

type AccessLogger func(*http.Request, int64, string)

Functions implementing this type are supplied the request and duration of the request along with an appropriate unit i.e. m, u, or n.

type Config

type Config struct {
	// Logs errors that occur during requests
	ErrorLogger ErrorLogger

	// Logs requests
	AccessLogger AccessLogger
}

Server configuration

type ErrorLogger

type ErrorLogger func(error)

Functions implementing this type are supplied an HttpError if an error occurs while processing a request.

type Group

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

Stores the underlying endpoint, route-wide middleware, and server

func (*Group) Delete

func (g *Group) Delete(h Handler, methodOnly ...Middleware) *Group

Bind this route to support DELETE requests, with methodOnly middleware only applied here

func (*Group) Get

func (g *Group) Get(h Handler, methodOnly ...Middleware) *Group

Bind this route to support GET requests, with methodOnly middleware only applied here

func (*Group) Middleware

func (g *Group) Middleware(nextRoutes ...Middleware) *Group

Add middleware to be called for handlers following this method call for this group

func (*Group) Patch

func (g *Group) Patch(h Handler, methodOnly ...Middleware) *Group

Bind this route to support PATCH requests, with methodOnly middleware only applied here

func (*Group) Post

func (g *Group) Post(h Handler, methodOnly ...Middleware) *Group

Bind this route to support POST requests, with methodOnly middleware only applied here

func (*Group) Put

func (g *Group) Put(h Handler, methodOnly ...Middleware) *Group

Bind this route to support PUT requests, with methodOnly middleware only applied here

type Handler

type Handler func(http.ResponseWriter, *http.Request) error

Extension of http.Handler that returns an error to the framework's error handler

type HttpError

type HttpError struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

func BadRequest

func BadRequest(m string) HttpError

400 Bad Request error

func Forbidden

func Forbidden(m string) HttpError

403 Forbidden error

func InternalServerError

func InternalServerError(m string) HttpError

500 Internal Server Error error

func MethodNotAllowed

func MethodNotAllowed(m string) HttpError

405 Method Not Allowed error

func NotFound

func NotFound(m string) HttpError

404 Not Found error

func Unauthorized

func Unauthorized(m string) HttpError

401 Unauthorized error

func (HttpError) Error

func (e HttpError) Error() string

get the error in string format

type Middleware

type Middleware func(*http.Request) error

Middleware functions are called in order after route matching but before the Handler.

type Param added in v0.9.0

type Param httprouter.Param

type Queue

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

Queue handles errors returned from middleware and handlers along with implementing http.Handler. A Queue should not be created directly, and is only exposed to serve testing purposes with the httptest library (or alternatives) using the NewHttpTestHandler factory method.

func (*Queue) ServeHTTP

func (q *Queue) ServeHTTP(w http.ResponseWriter, r *http.Request)

Queue implements http.Handler.

type Server

type Server struct {
	Config           *Config
	GlobalMiddleware []Middleware
	*httprouter.Router
}

Wrapper around vestigo.Router

func NewServer

func NewServer(config *Config, m ...Middleware) *Server

Create a new server; optionally specifying global middleware.

func (*Server) AddGlobalMiddleware

func (s *Server) AddGlobalMiddleware(m ...Middleware)

Append (or set if not existing) middleware to apply to all routes.

func (*Server) Delete

func (s *Server) Delete(endpoint string, c Handler, m ...Middleware)

Bind endpoint to support DELETE requests.

func (*Server) Get

func (s *Server) Get(endpoint string, c Handler, m ...Middleware)

Bind endpoint to support GET requests.

func (*Server) NewGroup

func (s *Server) NewGroup(endpoint string, routeWide ...Middleware) *Group

Create a group to bind multiple HTTP verbs to a single endpoint concisely

func (*Server) Patch

func (s *Server) Patch(endpoint string, c Handler, m ...Middleware)

Bind endpoint to support PATCH requests.

func (*Server) Post

func (s *Server) Post(endpoint string, c Handler, m ...Middleware)

Bind endpoint to support POST requests.

func (*Server) Put

func (s *Server) Put(endpoint string, c Handler, m ...Middleware)

Bind endpoint to support PUT requests.

Jump to

Keyboard shortcuts

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