Help us shape the future of Go! Take the 2026 Go Developer Survey

goji

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 18, 2019 License: MIT Imports: 6 Imported by: 0

README

About Goji

GoDoc Build Status

Goji is a HTTP request multiplexer, similar to net/http.ServeMux. It compares incoming requests to a list of registered Patterns, and dispatches to the http.Handler that corresponds to the first matching Pattern. Goji also supports Middleware (composable shared functionality applied to every request) and uses the standard context package to store request-scoped values.

Quick Start

package main

import (
        "fmt"
        "net/http"

        "github.com/brankas/goji"
)

func hello(w http.ResponseWriter, r *http.Request) {
        name := pat.Param(r, "name")
        fmt.Fprintf(w, "Hello, %s!", name)
}

func main() {
        mux := goji.NewMux()
        mux.HandleFunc(pat.Get("/hello/:name"), hello)

        http.ListenAndServe("localhost:8000", mux)
}

Please refer to Goji's GoDoc Documentation for a full API reference.

Documentation

Overview

Package goji is a minimalistic and flexible context based route matching request multiplexer.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Param

func Param(req *http.Request, name string) string

Param returns a bound, named variable from the context.

For example, given a mux with a single GET route:

mux := goji.NewMux()
mux.HandleFunc(goji.Get("/user/:name"), http.HandlerFunc(/* ... */)

When a HTTP request for is issued:

GET /user/carl

Then a call to goji.Param(req.Context(), "name") will return "carl".

Note: caller should ensure that the variable has been bound. Attempts to access variables that have not been set (or which have been invalidly set) are considered programmer errors and will trigger a panic.

func Path

func Path(ctx context.Context) string

Path returns the path prefix from the context.

func SubMux

func SubMux(m *Mux)

SubMux is a mux option to toggle the mux a sub mux.

func WithHandler

func WithHandler(ctx context.Context, handler http.Handler) context.Context

WithHandler returns a child context with the passed handler.

func WithMatcher

func WithMatcher(ctx context.Context, matcher Matcher) context.Context

WithMatcher returns a child context with the passed Matcher.

func WithPath

func WithPath(ctx context.Context, path string) context.Context

WithPath returns a child context with the passed path prefix.

Types

type Matcher

type Matcher interface {
	// Match examines the input Request to determine if it matches some
	// criteria, and if so returns a non-nil output Request.
	Match(*http.Request) *http.Request

	// Methods returns the set of HTTP methods that the Matcher matches, or nil
	// if it's not possible to determine which HTTP methods might be matched.
	Methods() map[string]struct{}

	// Prefix returns a string which all RawPaths that the Matcher must
	// have as a prefix. Put another way, requests with RawPaths that do not
	// contain the returned string as a prefix are guaranteed to never match
	// this Matcher.
	Prefix() string
}

Matcher determines whether a given request matches some criteria.

type Mux

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

Mux is a HTTP multiplexer and router similar to net/http.ServeMux.

Muxes multiplex traffic between many http.Handlers by selecting the first route registered to a supplied Matcher.

They then call a common middleware stack, finally passing control to the selected http.Handler. See the documentation on the Handle function for more information about how routing is performed, the documentation on the Pattern type for more information about request matching, and the documentation for the Use method for more about middleware.

Muxes cannot be configured concurrently from multiple goroutines, nor can they be configured concurrently with requests.

func New

func New(opts ...MuxOption) *Mux

New returns a new Mux with no configured middleware using the default router.

func NewSubMux

func NewSubMux(opts ...MuxOption) *Mux

NewSubMux returns a new sub-Mux with no configured middleware using the default router.

func (*Mux) Handle

func (m *Mux) Handle(matcher Matcher, handler http.Handler)

Handle adds a new route to the Mux. Requests that match the given Matcher will be dispatched to the given http.Handler.

Routing is performed in the order in which routes are added: the first route with a matching Matcher will be used. In particular, Goji guarantees that routing is performed in a manner that is indistinguishable from the following algorithm:

// Assume routes is a slice that every call to Handle appends to
for _, route := range routes {
	// For performance, Matchers can opt out of this call to Match.
	// See the documentation for Matcher for more.
	if req2 := route.pattern.Match(req); req2 != nil {
		route.handler.ServeHTTP(res, req2)
		break
	}
}

It is not safe to concurrently register routes from multiple goroutines, or to register routes concurrently with requests.

func (*Mux) HandleFunc

func (m *Mux) HandleFunc(matcher Matcher, handler func(http.ResponseWriter, *http.Request))

HandleFunc adds a new route to the Mux. It is equivalent to calling Handle on a handler wrapped with http.HandlerFunc, and is provided only for convenience.

func (*Mux) ServeHTTP

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

ServeHTTP satisfies the http.Handler interface.

func (*Mux) Use

func (m *Mux) Use(middleware func(http.Handler) http.Handler)

Use appends a middleware to the Mux's middleware stack.

Middleware are composable pieces of functionality that augment http.Handlers. Common examples of middleware include request loggers, authentication checkers, and metrics gatherers.

Middleware are evaluated in the reverse order in which they were added, but the resulting http.Handlers execute in "normal" order (i.e., the http.Handler returned by the first Middleware to be added gets called first).

For instance, given middleware A, B, and C, added in that order, Goji will behave similarly to this snippet:

augmentedHandler := A(B(C(yourHandler)))
augmentedHandler.ServeHTTP(res, req)

Assuming each of A, B, and C look something like this:

func A(inner http.Handler) http.Handler {
	log.Print("A: called")
	mw := func(res http.ResponseWriter, req *http.Request) {
		log.Print("A: before")
		inner.ServeHTTP(res, req)
		log.Print("A: after")
	}
	return http.HandlerFunc(mw)
}

we'd expect to see the following in the log:

C: called
B: called
A: called
---
A: before
B: before
C: before
yourHandler: called
C: after
B: after
A: after

Note that augmentedHandler will called many times, producing the log output below the divider, while the outer middleware functions (the log output above the divider) will only be called a handful of times at application boot.

Middleware in Goji is called after routing has been performed. Therefore it is possible to examine any routing information placed into the Request context by Patterns, or to view or modify the http.Handler that will be routed to. Middleware authors should read the documentation for the "middleware" subpackage for more information about how this is done.

The http.Handler returned by the given middleware must be safe for concurrent use by multiple goroutines. It is not safe to concurrently register middleware from multiple goroutines, or to register middleware concurrently with requests.

type MuxOption

type MuxOption func(*Mux)

MuxOption is a Mux option.

func NotFound

func NotFound(h http.Handler) MuxOption

NotFound is a mux option to set not found (404) handler.

func NotFoundFunc

func NotFoundFunc(f http.HandlerFunc) MuxOption

NotFoundFunc is a mux option to set a not found (404) handler func.

type PathSpec

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

PathSpec provides a Matcher that matches requests routes based on named path components, storing matched path components in the request context.

Quick Reference

The following table gives an overview of the language this package accepts. See the subsequent sections for a more detailed explanation of what each path does.

Path			Matches			Does Not Match

/			/			/hello

/hello			/hello			/hi
						/hello/

/user/:name		/user/carl		/user/carl/photos
			/user/alice		/user/carl/
						/user/

/:file.:ext		/data.json		/.json
			/info.txt		/data.
			/data.tar.gz		/data.json/download

/user/*			/user/			/user
			/user/carl
			/user/carl/photos

Static Paths

Most URL paths may be specified directly: the pattern "/hello" matches URLs with precisely that path ("/hello/", for instance, is treated as distinct).

Note that this package operates on raw (i.e., escaped) paths (see the documentation for net/url.URL.EscapedPath). In order to match a character that can appear escaped in a URL path, use its percent-encoded form.

Named Matches

Named matches allow URL paths to contain any value in a particular path segment. Such matches are denoted by a leading ":", for example ":name" in the rule "/user/:name", and permit any non-empty value in that position. For instance, in the previous "/user/:name" example, the path "/user/carl" is matched, while "/user/" or "/user/carl/" (note the trailing slash) are not matched. Pat rules can contain any number of named matches.

Named matches set URL variables by comparing pattern names to the segments they matched. In our "/user/:name" example, a request for "/user/carl" would bind the "name" variable to the value "carl". Use the Param function to extract these variables from the request context. Variable names in a single pattern must be unique.

Matches are ordinarily delimited by slashes ("/"), but several other characters are accepted as delimiters (with slightly different semantics): the period ("."), semicolon (";"), and comma (",") characters. For instance, given the pattern "/:file.:ext", the request "/data.json" would match, binding "file" to "data" and "ext" to "json". Note that these special characters are treated slightly differently than slashes: the above pattern also matches the path "/data.tar.gz", with "ext" getting set to "tar.gz"; and the pattern "/:file" matches names with dots in them (like "data.json").

Prefix Matches

Pat can also match prefixes of routes using wildcards. Prefix wildcard routes end with "/*", and match just the path segments preceding the asterisk. For instance, the pattern "/user/*" will match "/user/" and "/user/carl/photos" but not "/user" (note the lack of a trailing slash).

The unmatched suffix, including the leading slash ("/"), are placed into the request context, which allows subsequent routing (e.g., a subrouter) to continue from where this pattern left off. For instance, in the "/user/*" pattern from above, a request for "/user/carl/photos" will consume the "/user" prefix, leaving the path "/carl/photos" for subsequent patterns to handle. A subrouter pattern for "/:name/photos" would match this remaining path segment, for instance.

func Delete

func Delete(spec string) *PathSpec

Delete returns a PathSpec that matches requests for DELETE HTTP method.

func Get

func Get(spec string) *PathSpec

Get returns a PathSpec that matches requests for GET and HEAD HTTP method. HEAD requests are handled transparently by net/http.

func Head(spec string) *PathSpec

Head returns a PathSpec that matches requests for HEAD HTTP method.

func NewPathSpec

func NewPathSpec(spec string, opts ...PathSpecOption) *PathSpec

NewPathSpec returns a new PathSpec from the given path spec and options.

func Options

func Options(spec string) *PathSpec

Options returns a PathSpec that matches requests for OPTIONS HTTP method.

func Patch

func Patch(spec string) *PathSpec

Patch returns a PathSpec that matches requests for PATCH HTTP method.

func Post

func Post(spec string) *PathSpec

Post returns a PathSpec that matches requests for POST HTTP method.

func Put

func Put(spec string) *PathSpec

Put returns a PathSpec that matches requests for PUT HTTP method.

func (*PathSpec) Match

func (p *PathSpec) Match(req *http.Request) *http.Request

Match runs the path spec against the passed request, returning a modified copy of the request when the path spec matches.

func (*PathSpec) Methods

func (p *PathSpec) Methods() map[string]struct{}

Methods returns the set of HTTP methods that this PathSpec matches.

func (*PathSpec) Prefix

func (p *PathSpec) Prefix() string

Prefix returns the prefix for requests that the path spec matches.

func (*PathSpec) String

func (p *PathSpec) String() string

String satisfies fmt.Stringer interface.

type PathSpecOption

type PathSpecOption func(*PathSpec)

PathSpecOption is a path spec option.

func WithMethod

func WithMethod(methods ...string) PathSpecOption

WithMethod is a path spec option to set the matching HTTP methods.

type Router

type Router interface {
	Handle(Matcher, http.Handler)
	Route(*http.Request) *http.Request
}

Router is the shared router interface.

Directories

Path Synopsis
_example/main.go
_example/main.go

Jump to

Keyboard shortcuts

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