min

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Sep 15, 2019 License: MIT Imports: 2 Imported by: 1

README

min

v1.0.0

GoDoc Go Report Card Build Status Codecov GitHub

min is a BYO*, minimalistic web framework that builds on top of your router of choice and adds some additional functionality—namely, middleware chaining and route grouping. It's meant to be used on projects large and small that require flexibility, and varying degrees of custom code and architecture.

This version of min integrates some of the lessons I've learned recently. For this release, I decided to focus on orthogonality and composability, and took a "pure" TDD approach to the API rewrite. The result is a much smaller library with the same functionality, minus some unnecessary abstractions.

This package takes some inspiration from design decisions in chi and gin.

Usage

Hello World

You can initialize a new instance of the Min type with whichever type that implements min.Handler. An adapter for httprouter is included.

import (
    "fmt"
    "net/http"

    "github.com/julienschmidt/httprouter"

    "github.com/arturovm/min"
    "github.com/arturovm/min/adapter"
)

func main() {
    a := &adapter.Httprouter{Router: httprouter.New()}
    m := min.New(a)

    m.Get("/", helloWorld)

    http.ListenAndServe(":8080", m)
}

func helloWorld(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "hello world!")
}
Route Parameters

min supports all the syntax variations for defining route parameters that the underlying router does. For instance, in the case of httprouter:

import (
    "fmt"
    "net/http"

    "github.com/julienschmidt/httprouter"

    "github.com/arturovm/min"
    "github.com/arturovm/min/adapter"
)

func main() {
    a := &adapter.Httprouter{Router: httprouter.New()}
    m := min.New(a)

    m.Get("/:name", greet)

    http.ListenAndServe(":8080", m)
}

func greet(w http.ResponseWriter, r *http.Request) {
    name := httprouter.ParamsFromContext(r.Context()).ByName("name")
    fmt.Fprintf(w, "hello %s!", name)
}
Route Grouping
import (
    "fmt"
    "net/http"

    "github.com/julienschmidt/httprouter"

    "github.com/arturovm/min"
    "github.com/arturovm/min/adapter"
)

func main() {
    a := &adapter.Httprouter{Router: httprouter.New()}
    m := min.New(a)

    apiRouter := m.NewGroup("/api")
    {
        // GET /api
        apiRouter.Get("/", apiRoot)
        // GET /api/ignacio
        apiRouter.Get("/:name", greet)
    }

    http.ListenAndServe(":8080", m)
}

func apiRoot(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "api root")
}

func greet(w http.ResponseWriter, r *http.Request) {
    name := httprouter.ParamsFromContext(r.Context()).ByName("name")
    fmt.Fprintf(w, "hello %s!", name)
}
Middleware

Middleware in min are simply functions that take an http.Handler (the one next in the chain) and return another one. They are resolved in the order that they are chained. You can chian them together with the Middleware.Then method.

min users are meant to take advantage of context to make better use of middleware.

import (
    "context"
    "fmt"
    "log"
    "net/http"

    "github.com/julienschmidt/httprouter"

    "github.com/arturovm/min"
    "github.com/arturovm/min/adapter"
)

func main() {
    a := &adapter.Httprouter{Router: httprouter.New()}
    m := min.New(a)

    chain := min.Middleware(logger).Then(printer)
    m.Use(chain)

    apiRouter := m.NewGroup("/api")
    {
        apiRouter.Get("/", apiRoot)
        nameRouter := apiRouter.NewGroup("/:name")
        {
            // Every request sent to routes defined on this sub-router will now
            // have a reference to a name in its context.
            // Useful for RESTful design.
            nameRouter.Use(nameExtractor)

            // GET /api/ignacio
            nameRouter.Get("/", greet)
            // GET /api/ignacio/goodbye
            nameRouter.Get("/goodbye", goodbye)
        }
    }

    http.ListenAndServe(":8080", m)
}

// -- Middleware --

// a simple logger
func logger(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        log.Printf("| %s %s", r.Method, r.URL)
        next.ServeHTTP(w, r)
    })
}

// a useless middleware that prints text
func printer(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        log.Println("this prints some text")
        next.ServeHTTP(w, r)
    })
}

// extracts a name from the URL and injects it into the request's context
func nameExtractor(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        name := httprouter.ParamsFromContext(r.Context()).ByName("name")
        ctx := context.WithValue(r.Context(), "name", name)
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

// -- Handlers --

func apiRoot(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "api root")
}

// greets the user with :name
func greet(w http.ResponseWriter, r *http.Request) {
    name := r.Context().Value("name").(string)
    fmt.Fprintf(w, "hello %s!", name)
}

// says "bye" to the user with :name
func goodbye(w http.ResponseWriter, r *http.Request) {
    name := r.Context().Value("name").(string)
    fmt.Fprintf(w, "bye %s!", name)
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Group added in v1.0.0

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

Group represents a route group that shares a middleware chain and a common path.

func (*Group) Delete added in v1.0.0

func (g *Group) Delete(relativePath string, handler http.Handler)

Delete registers a handler for DELETE requests on the given relative path.

func (*Group) FullPath added in v1.0.0

func (g *Group) FullPath() string

FullPath returns the group's full path in the group tree (as opposed to this group's sub-path)

func (*Group) Get added in v1.0.0

func (g *Group) Get(relativePath string, handler http.Handler)

Get registers a handler for GET requests on the given relative path.

func (*Group) NewGroup added in v1.0.0

func (g *Group) NewGroup(path string) *Group

NewGroup creates a new subgroup of group g.

func (*Group) Parent added in v1.0.0

func (g *Group) Parent() *Group

Parent gets the group's parent in the group tree.

func (*Group) Patch added in v1.0.0

func (g *Group) Patch(relativePath string, handler http.Handler)

Patch registers a handler for PATCH requests on the given relative path.

func (*Group) Post added in v1.0.0

func (g *Group) Post(relativePath string, handler http.Handler)

Post registers a handler for POST requests on the given relative path.

func (*Group) Put added in v1.0.0

func (g *Group) Put(relativePath string, handler http.Handler)

Put registers a handler for PUT requests on the given relative path.

func (*Group) Use added in v1.0.0

func (g *Group) Use(m Middleware)

Use sets this group's middleware chain. Each call to Use appends to the chain.

type Handler

type Handler interface {
	http.Handler
	Handle(method, path string, handler http.Handler)
}

Handler represents a type that can register handlers for a given HTTP verb and path.

type Middleware added in v1.0.0

type Middleware func(http.Handler) http.Handler

Middleware is a type alias to a function that takes a handler and returns another handler.

func (Middleware) Then added in v1.0.0

func (m Middleware) Then(mw Middleware) Middleware

Then composes middleware m with middleware mw, returning a Middleware that first resolves m and then mw.

type Min

type Min struct {
	*Group
}

Min is this package's main type. It contains the root route group.

func New

func New(handler Handler) *Min

New takes a Handler and initializes a new Min instance with a root route group.

func (*Min) ServeHTTP

func (m *Min) ServeHTTP(w http.ResponseWriter, r *http.Request)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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