travel

package module
v0.0.0-...-b5de3ad Latest Latest
Warning

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

Go to latest
Published: Mar 23, 2015 License: Apache-2.0 Imports: 3 Imported by: 2

README

Traversal-like Dynamic HTTP Routing in Go

Travel is an HTTP router that provides dynamic routing functionality similar to the "traversal" system from the Pyramid web framework in Python.

For details on the original traversal system see: http://docs.pylonsproject.org/docs/pyramid/en/latest/narr/traversal.html

Simply put, traversal allows you to route HTTP requests by providing a nested map[string]interface{} object called the "root tree". Request URLs are tokenized and recursive lookup is performed on the root tree object.

Example:

If the request URL is /foo/bar/baz/123, it is tokenized to the following:

   ["foo", "bar", "baz", "123"]

Then the equivalent of the following lookup is performed:

   root_tree["foo"]["bar"]["baz"]["123"]

The object that results from this lookup is the "current object". If traversal succeeds, a named handler is then invoked (looked up via the "handler map" provided to the router), otherwise the router returns an appropriate error (404, etc).

For details on how lookup translates to handler names, see the godoc documentation linked above. Travel allows users to emulate traditional traversal mechanics while also providing several ways to modify behavior, such as handler name overrides within the root tree object and limitations on subpath length.

Documentation

Overview

Travel is an HTTP router that provides routing similar to the "traversal" system from the Pyramid web framework in Python.

For details on the original traversal system please read: http://docs.pylonsproject.org/docs/pyramid/en/latest/narr/traversal.html

Usage:

func defaultHandler(w http.ResponseWriter, r *http.Request, c *travel.Context) {
	// handler code here
}

func errorHandler(w http.ResponseWriter, r *http.Request, err travel.TraversalError) {
	// HTTP error handler code here
	http.Error(w, err.Error(), err.Code())
}

func getRootTree() {
  // Fetch root tree here
}

handlerMap := map[string]TravelHandler {
	"": defaultHandler,
}

options := travel.TravelOptions{
	StrictTraversal:   true,
	SubpathMaxLength: map[string]int{
		"GET":    travel.UnlimitedSubpath,
		"PUT":    0,
		"POST":   0,
		"DELETE": 0,
	},
}
r, err := travel.NewRouter(getRootTree, handlerMap, errorHandler, &options)
if err != nil {
	log.Fatalf("Error creating Travel router: %v\n", err)
}
http.Handle("/", r)
http.ListenAndServe("127.0.0.1:8000", nil)

Travel provides additional options to modify normal traversal semantincs:

Strict vs Permissive

"Strict" means to follow Pyramid traversal semantics -- handler name can only be "" (empty string) or the latest token in path when root tree lookup failed (everything beyond that is the subpath). Note that this can be modified with handler name overrides in the root tree object.

Non-strict (permissive) means that the handler name is always the latest token in the path (regardless if lookup fully succeeds).

Strict setting has no effect on the following options (they can be used to modify "strict" traversal as needed). Handler names can always be overridden by embedding handler keys within the root tree ('%handler' key within the object, value must be a string).

Handler Overrides

Any level of the root tree can contain a special key "%handler", mapping to a handler name string that will be invoked instead of whatever traversal would otherwise dictate. Handler overrides take precedence over strict/permissive mode rules.

Default Handler

The optional DefaultHandler is used to execute a fallback handler when traversal succeeds but the handler name returned is not found within the handler map. Otherwise a 501 Not Implemented error is returned. As with handler overrides, the DefaultHandler setting is respected regardless of strict/permissive setting.

Subpath Max Length

SubpathMaxLength is a map of method verb (all caps) to an integer representing the allowed number of subpath tokens. If the subpath length is less than or equal to this limit, the request succeeds and the handler is executed per traversal semantics. If the subpath exceeds this limit a 404 Not Found is returned. Traditional Pyramid traversal has an unlimited subpath max length. That can be emulated by setting SubpathMaxLength[verb] to UnlimitedSubpath.

Index

Constants

View Source
const (
	UnlimitedSubpath = -1 // Emulate traditional traversal with unlimited subpath lengths

)

Variables

This section is empty.

Functions

This section is empty.

Types

type Context

type Context struct {
	RootTree   map[string]interface{} // Root tree as processed by this request (thread-local)
	CurrentObj interface{}            // Current object from root tree
	Path       []string               // tokenized URL path
	Subpath    []string               // Tokenized subpath for this request (everything beyond the last token that succeeded traversal)
	// contains filtered or unexported fields
}

Request context passed to request handler

func (*Context) Refresh

func (c *Context) Refresh() TraversalError

Fetch the root tree, re-run traversal and update Context fields.

func (*Context) WalkBack

func (c *Context) WalkBack(n uint) (map[string]interface{}, error)

Walk back n nodes in tokenized path, return root tree object at that node.

type HandlerMap

type HandlerMap map[string]TravelHandler

type RootTreeFunc

type RootTreeFunc func() (map[string]interface{}, error)

type Router

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

Travel router

func NewRouter

func NewRouter(rtf RootTreeFunc, hm HandlerMap, eh TravelErrorHandler, o *TravelOptions) (*Router, error)

Create a new Travel router. Parameters: callback function to fetch root tree, map of handler names to functions, default request error handler, options

func (*Router) ServeHTTP

func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)

type TravelErrorHandler

type TravelErrorHandler func(http.ResponseWriter, *http.Request, TraversalError)

type TravelHandler

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

type TravelOptions

type TravelOptions struct {
	SubpathMaxLength  map[string]int // Map of method verb to subpath length limit for requests of that type
	StrictTraversal   bool           // Obey Pyramid traversal semantics (do not enforce subpath limits, use handler names from path only)
	UseDefaultHandler bool           // If handler name is not found in handler map, execute this instead of returning http.StatusNotImplemented
	DefaultHandler    string         // Default handler name (must exist in handler map)
}

Options for Travel router

type TraversalError

type TraversalError interface {
	Error() string
	Code() int
}

func InternalError

func InternalError(m string) TraversalError

func NotFoundError

func NotFoundError(r []string) TraversalError

func RootTreeError

func RootTreeError(err error) TraversalError

func UnknownHandlerError

func UnknownHandlerError(r []string) TraversalError

type TraversalInternalError

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

func (TraversalInternalError) Code

func (t TraversalInternalError) Code() int

func (TraversalInternalError) Error

func (t TraversalInternalError) Error() string

type TraversalNotFoundError

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

func (TraversalNotFoundError) Code

func (t TraversalNotFoundError) Code() int

func (TraversalNotFoundError) Error

func (t TraversalNotFoundError) Error() string

type TraversalResult

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

Result of running traversal algorithm

type TraversalRootTreeError

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

func (TraversalRootTreeError) Code

func (t TraversalRootTreeError) Code() int

func (TraversalRootTreeError) Error

func (t TraversalRootTreeError) Error() string

type TraversalUnknownHandlerError

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

func (TraversalUnknownHandlerError) Code

func (TraversalUnknownHandlerError) Error

Jump to

Keyboard shortcuts

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