Skip to content

Commit

Permalink
Added documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Minoxs committed Apr 23, 2022
1 parent d8fc873 commit 10d8066
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 1 deletion.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
20 changes: 20 additions & 0 deletions middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,41 @@ 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,
middlewareStack: make([]SimpleMiddleware, 0),
}
}

// 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)
Expand All @@ -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
Expand Down
10 changes: 10 additions & 0 deletions mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
15 changes: 15 additions & 0 deletions router.go
Original file line number Diff line number Diff line change
Expand Up @@ -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: "",
Expand All @@ -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)
Expand All @@ -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),
Expand All @@ -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)
}
3 changes: 3 additions & 0 deletions utils.go
Original file line number Diff line number Diff line change
@@ -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 "/"
Expand Down

0 comments on commit 10d8066

Please sign in to comment.