bear

package module
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Sep 25, 2016 License: MIT Imports: 4 Imported by: 28

README

bear: embeddable application router

Coverage status

API documentation

bear.Mux is an HTTP multiplexer. It uses a tree structure for fast routing, supports dynamic parameters, middleware, and accepts both native http.HandlerFunc or bear.HandlerFunc, which accepts an extra *Context argument that allows storing state (using the Get() and Set() methods) and calling the Next() middleware.

Install

go get -u github.com/ursiform/bear

Quick start

Create main.go in a new folder
package main

import (
    "fmt"
    "github.com/ursiform/bear"
    "log"
    "net/http"
)

func logRequest(res http.ResponseWriter, req *http.Request, ctx *bear.Context) {
    log.Printf("%s %s\n", req.Method, req.URL.Path)
    ctx.Next()
}
func notFound(res http.ResponseWriter, req *http.Request, ctx *bear.Context) {
    res.Header().Set("Content-Type", "text/plain")
    res.WriteHeader(http.StatusNotFound)
    res.Write([]byte("Sorry, not found!\n"))
}
func one(res http.ResponseWriter, req *http.Request, ctx *bear.Context) {
    ctx.Set("one", "set in func one").Next() // Set() allows chaining
}
func two(res http.ResponseWriter, req *http.Request, ctx *bear.Context) {
    ctx.Set("two", "set in func two").Next()
}
func three(res http.ResponseWriter, req *http.Request, ctx *bear.Context) {
    greet := fmt.Sprintf("Hello, %s!\n", ctx.Params["user"])
    first := ctx.Get("one").(string)  // assert type: interface{} as string
    second := ctx.Get("two").(string) // assert type: interface{} as string
    state := fmt.Sprintf("state one: %s\nstate two: %s\n", first, second)
    res.Header().Set("Content-Type", "text/plain")
    res.Write([]byte(greet + state))
}
func main() {
    mux := bear.New()
    mux.Always(logRequest)                          // log each incoming request
    mux.On("GET", "/hello/{user}", one, two, three) // dynamic URL param {user}
    mux.On("*", "/*", notFound)                     // wildcard method + path
    http.ListenAndServe(":1337", mux)
}

###Build and start a server

$ go build -o ./server && ./server

###Test using curl

$ curl http://localhost:1337/hello/world
Hello, world!
state one: set in func one
state two: set in func two
$ curl http://localhost:1337/hello/world/foo
Sorry, not found!

###Check server log output

2016/02/06 15:19:50 GET /hello/world
2016/02/06 15:20:00 GET /hello/world/foo

Test

go test -cover github.com/ursiform/bear

API

API documentation

License

MIT License

Documentation

Overview

Package bear provides HTTP multiplexing with dynamic URL components and request contexts to form the nucleus of a middleware-based web service.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Context

type Context struct {
	// Params is a map of string keys with string values that is populated
	// by the dynamic URL parameters (if any).
	// Wildcard params are accessed by using an asterisk: Params["*"]
	Params map[string]string

	// Request is the same as the *http.Request that all handlers receive
	// and is referenced in Context for convenience.
	Request *http.Request
	// ResponseWriter is the same as the http.ResponseWriter that all handlers
	// receive and is referenced in Context for convenience.
	ResponseWriter http.ResponseWriter
	// contains filtered or unexported fields
}

Context is state of each request.

func (*Context) Get

func (ctx *Context) Get(key string) interface{}

Get allows retrieving a state value (interface{})

func (*Context) Next

func (ctx *Context) Next()

Next calls the next middleware (if any) that was registered as a handler for a particular request pattern.

func (*Context) Set

func (ctx *Context) Set(key string, value interface{}) *Context

Set allows setting an arbitrary value (interface{}) to a string key to allow one middleware to pass information to the next. It returns a pointer to the current Context to allow chaining.

type HandlerFunc

type HandlerFunc func(http.ResponseWriter, *http.Request, *Context)

HandlerFunc is similar to http.HandlerFunc, except it requires an extra argument for the *Context of a request.

type Mux

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

Mux is an HTTP multiplexer. It uses a tree structure for fast routing, supports dynamic parameters, middleware, and accepts both native http.HandlerFunc or bear.HandlerFunc, which accepts an extra *Context argument that allows storing state (using the Get() and Set() methods) and calling the Next() middleware.

func New

func New() *Mux

New returns a pointer to a Mux instance

func (*Mux) Always

func (mux *Mux) Always(handlers ...interface{}) error

Always adds one or more handlers that will run before every single request. Multiple calls to Always will append the current list of Always handlers with the newly added handlers.

Handlers must be either bear.HandlerFunc functions or functions that match the bear.HandlerFunc signature and they should call (*Context).Next to continue the response life cycle.

func (*Mux) On

func (mux *Mux) On(verb string, pattern string, handlers ...interface{}) error

On adds HTTP verb handler(s) for a URL pattern. The handler argument(s) should either be http.HandlerFunc or bear.HandlerFunc or conform to the signature of one of those two. NOTE: if http.HandlerFunc (or a function conforming to its signature) is used no other handlers can *follow* it, i.e. it is not middleware.

It returns an error if it fails, but does not panic. Verb strings are uppercase HTTP methods. There is a special verb "*" which can be used to answer *all* HTTP methods. It is not uncommon for the verb "*" to return errors, because a path may already have a listener associated with one HTTP verb before the "*" verb is called. For example, this common and useful pattern will return an error that can safely be ignored (see error example).

Pattern strings are composed of tokens that are separated by "/" characters. There are three kinds of tokens:

1. static path strings: "/foo/bar/baz/etc"

2. dynamically populated parameters "/foo/{bar}/baz" (where "bar" will be populated in the *Context.Params)

3. wildcard tokens "/foo/bar/*" where * has to be the final token. Parsed URL params are available in handlers via the Params map of the *Context argument.

Notes:

1. A trailing slash / is always implied, even when not explicit.

2. Wildcard (*) patterns are only matched if no other (more specific) pattern matches. If multiple wildcard rules match, the most specific takes precedence.

3. Wildcard patterns do *not* match empty strings: a request to /foo/bar will not match the pattern "/foo/bar/*". The only exception to this is the root wildcard pattern "/*" which will match the request path / if no root handler exists.

Example (Error)
package main

import (
	"fmt"
	"net/http"

	"github.com/ursiform/bear"
)

func main() {
	mux := bear.New()
	handlerOne := func(http.ResponseWriter, *http.Request) {}
	handlerTwo := func(http.ResponseWriter, *http.Request) {}
	if err := mux.On("GET", "/foo/", handlerOne); err != nil {
		fmt.Println(err)
	} else if err := mux.On("*", "/foo/", handlerTwo); err != nil {
		fmt.Println(err)
	}
}
Output:

bear: GET /foo/ exists, ignoring

func (*Mux) ServeHTTP

func (mux *Mux) ServeHTTP(res http.ResponseWriter, req *http.Request)

ServeHTTP allows a Mux instance to conform to the http.Handler interface.

Jump to

Keyboard shortcuts

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