From 10d80665ef11611da5c7f48abf02b15d07f00a5a Mon Sep 17 00:00:00 2001 From: Mino Date: Sat, 23 Apr 2022 03:44:24 -0300 Subject: [PATCH] Added documentation --- README.md | 3 ++- middleware.go | 20 ++++++++++++++++++++ mux.go | 10 ++++++++++ router.go | 15 +++++++++++++++ utils.go | 3 +++ 5 files changed, 50 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 456945a..34e626c 100644 --- a/README.md +++ b/README.md @@ -4,4 +4,5 @@ The base HTTP package does too little Any routing package does too much This one aims to do juuuuust enough -This basically abstracts away some boilerplate code, and tries not to be too fancy. +This basically abstracts away some boilerplate code, and tries not to be too fancy. +Check out the examples to know how to use the package, althought it should be fairly straight forward. diff --git a/middleware.go b/middleware.go index 747ec85..5dbe9c1 100644 --- a/middleware.go +++ b/middleware.go @@ -4,13 +4,20 @@ import ( "net/http" ) +// SimpleMiddleware is the function signature that is supposed to be used with this library's methods. +// It allows for both-way handling. type SimpleMiddleware func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) +// middlewareRouter is the router returned when a middleware is registered. +// This struct is internal and should not be created manually, do it at your own risk. +// Registered middlewares are added to a write-only stack, and once a method is registered +// the methods are peeked from the stack one-by-one and the middleware chain is created. type middlewareRouter struct { *SimpleRouter middlewareStack []SimpleMiddleware } +// newMiddlewareRouter creates a middleware router with default settings func newMiddlewareRouter(root *SimpleRouter) *middlewareRouter { return &middlewareRouter{ SimpleRouter: root, @@ -18,15 +25,20 @@ func newMiddlewareRouter(root *SimpleRouter) *middlewareRouter { } } +// push adds a new middleware to the stack func (r *middlewareRouter) push(m SimpleMiddleware) *middlewareRouter { r.middlewareStack = append(r.middlewareStack, m) return r } +// createChain creates the middleware chain, returning a handler function func (r *middlewareRouter) createChain(h http.HandlerFunc) http.HandlerFunc { chain := h for i := len(r.middlewareStack) - 1; i >= 0; i-- { + // This looks really complicated + // But it's just a janky way of moving the thingies into another scope + // So that you don't get a middleware referencing itself or something silly like that chain = func(current http.HandlerFunc, top SimpleMiddleware) http.HandlerFunc { return func(wrt http.ResponseWriter, req *http.Request) { top(wrt, req, current) @@ -37,29 +49,37 @@ func (r *middlewareRouter) createChain(h http.HandlerFunc) http.HandlerFunc { return chain } +// FileServer creates a file server with files from root. +// Be careful with this thing. Check out http.FileServer for +// more information. func (s *middlewareRouter) FileServer(root string) *middlewareRouter { s.fileServer = s.createChain(http.FileServer(http.Dir(root)).ServeHTTP) return s } +// Get registers a get endpoint func (s *middlewareRouter) Get(pattern string, handle http.HandlerFunc) *middlewareRouter { f := s.createChain(handle) s.SimpleRouter.Get(pattern, f) return s } +// Post registers a post endpoint func (s *middlewareRouter) Post(pattern string, handle http.HandlerFunc) *middlewareRouter { f := s.createChain(handle) s.SimpleRouter.Post(pattern, f) return s } +// Delete register a delete endpoint func (s *middlewareRouter) Delete(pattern string, handle http.HandlerFunc) *middlewareRouter { f := s.createChain(handle) s.SimpleRouter.Delete(pattern, f) return s } +// Use registers a middleware is run in the order they are registered. +// After every middleware the handler is run func (s *middlewareRouter) Use(m SimpleMiddleware) *middlewareRouter { s.push(m) return s diff --git a/mux.go b/mux.go index 3f4efc3..9ace194 100644 --- a/mux.go +++ b/mux.go @@ -2,27 +2,34 @@ package simplerouter import "net/http" +// Helper types type ( method uint8 handlers [3]http.Handler ) +// Helper constants for accessing handler array const ( GET method = 0 POST = 1 DELETE = 2 ) +// SimpleMux is a simple map-based mux. +// Paths are mapped to an array with each possible method's handler. +// Use NewSimpleMux to create. type SimpleMux struct { m map[string]*handlers } +// NewSimpleMux creates a SimpleMux with default settings (there are no settings) func NewSimpleMux() *SimpleMux { return &SimpleMux{ m: make(map[string]*handlers), } } +// HandleFunc register a function handler for a specific method func (s *SimpleMux) HandleFunc(meth method, url string, handler http.Handler) { _, ok := s.m[url] if !ok { @@ -31,6 +38,9 @@ func (s *SimpleMux) HandleFunc(meth method, url string, handler http.Handler) { s.m[url][meth] = handler } +// GetHandler returns the handler method for a given request. +// Also returns if the method is allowed or not. +// If the handler method is nil, then there is no endpoint registered. func (s *SimpleMux) GetHandler(req *http.Request) (http.Handler, bool) { h, ok := s.m[req.URL.Path] if !ok { diff --git a/router.go b/router.go index 9d3e34d..d3ffc87 100644 --- a/router.go +++ b/router.go @@ -5,12 +5,16 @@ import ( "net/http" ) +// SimpleRouter is a HTTP Handler, and is used to simplify creating endpoints. +// While there is no problem with manually creating the struct, using New is +// highly encouraged. type SimpleRouter struct { prefix string mux *SimpleMux fileServer http.Handler } +// New creates a new SimpleRouter with default settings func New() *SimpleRouter { return &SimpleRouter{ prefix: "", @@ -19,6 +23,7 @@ func New() *SimpleRouter { } } +// ServeHTTP is implemented so that SimpleRouter implements http.Handler func (s *SimpleRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Try handling using mux handler, allowed := s.mux.GetHandler(r) @@ -44,11 +49,16 @@ func (s *SimpleRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) { http.NotFound(w, r) } +// FileServer creates a file server with files from root. +// Be careful with this thing. Check out http.FileServer for +// more information. func (s *SimpleRouter) FileServer(root string) *SimpleRouter { s.fileServer = http.FileServer(http.Dir(root)) return s } +// Prefix creates a subrouter that where every endpoint stemming from it +// has to start with... you guessed it! the prefix that was set. func (s *SimpleRouter) Prefix(prefix string) *SimpleRouter { return &SimpleRouter{ prefix: s.prefix + cleanPattern(prefix), @@ -57,24 +67,29 @@ func (s *SimpleRouter) Prefix(prefix string) *SimpleRouter { } } +// Get registers a get endpoint func (s *SimpleRouter) Get(pattern string, handle http.HandlerFunc) *SimpleRouter { pattern = cleanPattern(pattern) s.mux.HandleFunc(GET, s.prefix+pattern, handle) return s } +// Post registers a post endpoint func (s *SimpleRouter) Post(pattern string, handle http.HandlerFunc) *SimpleRouter { pattern = cleanPattern(pattern) s.mux.HandleFunc(POST, s.prefix+pattern, handle) return s } +// Delete register a delete endpoint func (s *SimpleRouter) Delete(pattern string, handle http.HandlerFunc) *SimpleRouter { pattern = cleanPattern(pattern) s.mux.HandleFunc(DELETE, s.prefix+pattern, handle) return s } +// Use registers a middleware is run in the order they are registered. +// After every middleware the handler is run func (s *SimpleRouter) Use(m SimpleMiddleware) *middlewareRouter { return newMiddlewareRouter(s).push(m) } diff --git a/utils.go b/utils.go index 63d29e2..b4d3c68 100644 --- a/utils.go +++ b/utils.go @@ -1,5 +1,8 @@ package simplerouter +// cleanPattern +// Makes sure the patterns are in the right format +// That is, always a leading slash, and no trailing slashes func cleanPattern(pattern string) string { if len(pattern) == 0 { return "/"