pure

package module
v2.2.0+incompatible Latest Latest
Warning

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

Go to latest
Published: Sep 27, 2016 License: MIT Imports: 13 Imported by: 2

README

##Pure Project status Build Status Coverage Status Go Report Card GoDoc License Gitter

Pure is a fast radix-tree based HTTP router that sticks to the native implimentations of Go's "net/http" package; in essence, keeping the handler implimentations 'pure' by using Go 1.7's "context" package.

Why Another HTTP Router?

I initially created lars, which I still maintain, that wraps the native implimentation, think of this package as a Go pure implimentation of lars

Key & Unique Features

  • It sticks to Go's native implimentations while providing helper functions for convenience
  • Fast & Efficient - pure uses a custom version of httprouter so incredibly fast and efficient.

Installation

Use go get

go get github.com/go-playground/pure

Usage

package main

import (
	"net/http"

	"github.com/go-playground/pure"
	mw "github.com/go-playground/pure/examples/middleware/logging-recovery"
)

func main() {

	p := pure.New()
	p.Use(mw.LoggingAndRecovery)

	p.Get("/", helloWorld)

	http.ListenAndServe(":3007", p.Serve())
}

func helloWorld(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("Hello World"))
}

URL Params

p := p.New()

// the matching param will be stored in the context's params with name "id"
l.Get("/user/:id", UserHandler)

// extract params like so
rv := pure.ReqestVars(r) // done this way so only have to extract from context once
rv.Params().Get(paramname)

// serve css, js etc.. pure.RequestVars(r).Params().Get(pure.WildcardParam) will return the remaining path if 
// you need to use it in a custom handler...
l.Get("/static/*", http.FileServer(http.Dir("static/"))) 

...

Note: Since this router has only explicit matches, you can not register static routes and parameters for the same path segment. For example you can not register the patterns /user/new and /user/:user for the same request method at the same time. The routing of different request methods is independent from each other. I was initially against this, and this router allowed it in a previous version, however it nearly cost me in a big app where the dynamic param value say :type actually could have matched another static route and that's just too dangerous, so it is no longer allowed.

Groups


p.Use(LoggingAndRecovery)
...
p.Post("/users/add", ...)

// creates a group for user + inherits all middleware registered using p.Use()
user := p.Group("/user/:userid")
user.Get("", ...)
user.Post("", ...)
user.Delete("/delete", ...)

contactInfo := user.Group("/contact-info/:ciid")
contactinfo.Delete("/delete", ...)

// creates a group for others + inherits all middleware registered using p.Use() + adds 
// OtherHandler to middleware
others := p.Group("/others", OtherHandler)

// creates a group for admin WITH NO MIDDLEWARE... more can be added using admin.Use()
admin := p.Group("/admin",nil)
admin.Use(SomeAdminSecurityMiddleware)
...

Decoding Body

currently JSON, XML, FORM + Multipart Form's are support out of the box.

	// second argument denotes yes or no I would like URL query parameter fields
	// to be included. i.e. 'id' in route '/user?id=val' should it be included.
	if err := pure.Decode(r, true, maxBytes, &user); err != nil {
		log.Println(err)
	}

Misc


// set custom 404 ( not Found ) handler
l.Register404(404Handler, middleware_like_logging)

// Redirect to or from ending slash if route not found, default is true
l.SetRedirectTrailingSlash(true)

// Handle 405 ( Method Not allowed ), default is false
l.RegisterMethodNotAllowed(middleware)

// automatically handle OPTION requests; manually configured
// OPTION handlers take precedence. default false
l.RegisterAutomaticOPTIONS(middleware)

Middleware

There are some pre-defined middlewares within the middleware folder; NOTE: that the middleware inside will comply with the following rule(s):

  • Are completely reusable by the community without modification

Other middleware will be listed under the examples/middleware/... folder for a quick copy/paste modify. as an example a logging or recovery middleware are very application dependent and therefore will be listed under the examples/middleware/...

Benchmarks

Run on MacBook Pro (Retina, 15-inch, Late 2013) 2.6 GHz Intel Core i7 16 GB 1600 MHz DDR3 using Go version go1.7.1 darwin/amd64

NOTICE: pure uses a custom version of httprouter, benchmarks can be found here the slowdown is with the use of the context package, as you can see when no params, and therefore no need to store anything in the context, it is faster than even lars.

go test -bench=. -benchmem=true
#GithubAPI Routes: 203
   Pure: 37816 Bytes

#GPlusAPI Routes: 13
   Pure: 3144 Bytes

#ParseAPI Routes: 26
   Pure: 5328 Bytes

#Static Routes: 157
   Pure: 21720 Bytes

BenchmarkPure_Param        	10000000	       210 ns/op	     288 B/op	       2 allocs/op
BenchmarkPure_Param5       	 5000000	       252 ns/op	     288 B/op	       2 allocs/op
BenchmarkPure_Param20      	 5000000	       384 ns/op	     288 B/op	       2 allocs/op
BenchmarkPure_ParamWrite   	 5000000	       266 ns/op	     288 B/op	       2 allocs/op
BenchmarkPure_GithubStatic 	20000000	        70.5 ns/op	       0 B/op	       0 allocs/op
BenchmarkPure_GithubParam  	 5000000	       289 ns/op	     288 B/op	       2 allocs/op
BenchmarkPure_GithubAll    	   30000	     51338 ns/op	   48098 B/op	     334 allocs/op
BenchmarkPure_GPlusStatic  	30000000	        53.5 ns/op	       0 B/op	       0 allocs/op
BenchmarkPure_GPlusParam   	10000000	       236 ns/op	     288 B/op	       2 allocs/op
BenchmarkPure_GPlus2Params 	 5000000	       252 ns/op	     288 B/op	       2 allocs/op
BenchmarkPure_GPlusAll     	  500000	      2842 ns/op	    3168 B/op	      22 allocs/op
BenchmarkPure_ParseStatic  	30000000	        53.1 ns/op	       0 B/op	       0 allocs/op
BenchmarkPure_ParseParam   	10000000	       209 ns/op	     288 B/op	       2 allocs/op
BenchmarkPure_Parse2Params 	10000000	       222 ns/op	     288 B/op	       2 allocs/op
BenchmarkPure_ParseAll     	  300000	      4355 ns/op	    4608 B/op	      32 allocs/op
BenchmarkPure_StaticAll    	  100000	     15090 ns/op	       0 B/op	       0 allocs/op

Package Versioning

I'm jumping on the vendoring bandwagon, you should vendor this package as I will not be creating different version with gopkg.in like allot of my other libraries.

Why? because my time is spread pretty thin maintaining all of the libraries I have + LIFE, it is so freeing not to worry about it and will help me keep pouring out bigger and better things for you the community.

Licenses

  • MIT License (MIT), Copyright (c) 2016 Dean Karn
  • BSD License, Copyright (c) 2013 Julien Schmidt. All rights reserved.

Documentation

Index

Constants

View Source
const (
	ApplicationJSON                  = "application/json"
	ApplicationJSONCharsetUTF8       = ApplicationJSON + "; " + CharsetUTF8
	ApplicationJavaScript            = "application/javascript"
	ApplicationJavaScriptCharsetUTF8 = ApplicationJavaScript + "; " + CharsetUTF8
	ApplicationXML                   = "application/xml"
	ApplicationXMLCharsetUTF8        = ApplicationXML + "; " + CharsetUTF8
	ApplicationForm                  = "application/x-www-form-urlencoded"
	ApplicationQueryParams           = ""
	ApplicationProtobuf              = "application/protobuf"
	ApplicationMsgpack               = "application/msgpack"
	TextHTML                         = "text/html"
	TextHTMLCharsetUTF8              = TextHTML + "; " + CharsetUTF8
	TextPlain                        = "text/plain"
	TextPlainCharsetUTF8             = TextPlain + "; " + CharsetUTF8
	MultipartForm                    = "multipart/form-data"
	OctetStream                      = "application/octet-stream"

	CharsetUTF8 = "charset=utf-8"

	AcceptedLanguage   = "Accept-Language"
	AcceptEncoding     = "Accept-Encoding"
	Authorization      = "Authorization"
	ContentDisposition = "Content-Disposition"
	ContentEncoding    = "Content-Encoding"
	ContentLength      = "Content-Length"
	ContentType        = "Content-Type"
	Location           = "Location"
	Upgrade            = "Upgrade"
	Vary               = "Vary"
	WWWAuthenticate    = "WWW-Authenticate"
	XForwardedFor      = "X-Forwarded-For"
	XRealIP            = "X-Real-Ip"
	Allow              = "Allow"
	Origin             = "Origin"

	Gzip = "gzip"

	WildcardParam = "*wildcard"
)

HTTP Constant Terms and Variables

Variables

View Source
var (
	// DefaultDecoder is pure's default form decoder
	DefaultDecoder = form.NewDecoder()
)

Functions

func AcceptedLanguages

func AcceptedLanguages(r *http.Request) (languages []string)

AcceptedLanguages returns an array of accepted languages denoted by the Accept-Language header sent by the browser NOTE: some stupid browsers send in locales lowercase when all the rest send it properly

func Attachment

func Attachment(w http.ResponseWriter, r io.Reader, filename string) (err error)

Attachment is a helper method for returning an attachement file to be downloaded, if you with to open inline see function Inline

func ClientIP

func ClientIP(r *http.Request) (clientIP string)

ClientIP implements a best effort algorithm to return the real client IP, it parses X-Real-IP and X-Forwarded-For in order to work properly with reverse-proxies such us: nginx or haproxy.

func Decode

func Decode(r *http.Request, includeFormQueryParams bool, maxMemory int64, v interface{}) (err error)

Decode takes the request and attempts to discover it's content type via the http headers and then decode the request body into the provided struct. Example if header was "application/json" would decode using json.NewDecoder(io.LimitReader(r.Body, maxMemory)).Decode(v).

NOTE: when includeFormQueryParams=true both query params and SEO query params will be parsed and included eg. route /user/:id?test=true both 'id' and 'test' are treated as query params and added to the request.Form prior to decoding; in short SEO query params are treated just like normal query params.

func Inline

func Inline(w http.ResponseWriter, r io.Reader, filename string) (err error)

Inline is a helper method for returning a file inline to be rendered/opened by the browser

func JSON

func JSON(w http.ResponseWriter, status int, i interface{}) (err error)

JSON marshals provided interface + returns JSON + status code

func JSONBytes

func JSONBytes(w http.ResponseWriter, status int, b []byte) (err error)

JSONBytes returns provided JSON response with status code

func JSONP

func JSONP(w http.ResponseWriter, status int, i interface{}, callback string) (err error)

JSONP sends a JSONP response with status code and uses `callback` to construct the JSONP payload.

func ParseForm added in v1.1.0

func ParseForm(r *http.Request) error

ParseForm calls the underlying http.Request ParseForm but also adds the URL params to the request Form as if they were defined as query params i.e. ?id=13&ok=true but does not add the params to the http.Request.URL.RawQuery for SEO purposes

func ParseMultipartForm added in v1.1.0

func ParseMultipartForm(r *http.Request, maxMemory int64) error

ParseMultipartForm calls the underlying http.Request ParseMultipartForm but also adds the URL params to the request Form as if they were defined as query params i.e. ?id=13&ok=true but does not add the params to the http.Request.URL.RawQuery for SEO purposes

func XML

func XML(w http.ResponseWriter, status int, i interface{}) (err error)

XML marshals provided interface + returns XML + status code

func XMLBytes

func XMLBytes(w http.ResponseWriter, status int, b []byte) (err error)

XMLBytes returns provided XML response with status code

Types

type FormDecoder

type FormDecoder interface {
	Decode(interface{}, url.Values) error
}

FormDecoder is the type used for decoding a form for use

type IRouteGroup

type IRouteGroup interface {
	IRoutes
	Group(prefix string, middleware ...Middleware) IRouteGroup
}

IRouteGroup interface for router group

type IRoutes

IRoutes interface for routes

type Middleware

type Middleware func(h http.HandlerFunc) http.HandlerFunc

Middleware is pure's middleware definition

type Mux

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

Mux is the main request multiplexer

func New

func New() *Mux

New Creates and returns a new Pure instance

func (*Mux) Any

func (g *Mux) Any(path string, h http.HandlerFunc)

Any adds a route & handler to the router for all HTTP methods.

func (*Mux) Connect

func (g *Mux) Connect(path string, h http.HandlerFunc)

Connect adds a CONNECT route & handler to the router.

func (*Mux) Delete

func (g *Mux) Delete(path string, h http.HandlerFunc)

Delete adds a DELETE route & handler to the router.

func (*Mux) Get

func (g *Mux) Get(path string, h http.HandlerFunc)

Get adds a GET route & handler to the router.

func (*Mux) Group

func (g *Mux) Group(prefix string, middleware ...Middleware) IRouteGroup

Group creates a new sub router with prefix. It inherits all properties from the parent. Passing middleware overrides parent middleware but still keeps the root level middleware intact.

func (*Mux) Handle

func (g *Mux) Handle(method string, path string, h http.HandlerFunc)

Handle allows for any method to be registered with the given route & handler. Allows for non standard methods to be used like CalDavs PROPFIND and so forth.

func (*Mux) Head

func (g *Mux) Head(path string, h http.HandlerFunc)

Head adds a HEAD route & handler to the router.

func (*Mux) Match

func (g *Mux) Match(methods []string, path string, h http.HandlerFunc)

Match adds a route & handler to the router for multiple HTTP methods provided.

func (*Mux) Options

func (g *Mux) Options(path string, h http.HandlerFunc)

Options adds an OPTIONS route & handler to the router.

func (*Mux) Patch

func (g *Mux) Patch(path string, h http.HandlerFunc)

Patch adds a PATCH route & handler to the router.

func (*Mux) Post

func (g *Mux) Post(path string, h http.HandlerFunc)

Post adds a POST route & handler to the router.

func (*Mux) Put

func (g *Mux) Put(path string, h http.HandlerFunc)

Put adds a PUT route & handler to the router.

func (*Mux) Register404

func (p *Mux) Register404(notFound http.HandlerFunc, middleware ...Middleware)

Register404 alows for overriding of the not found handler function. NOTE: this is run after not finding a route even after redirecting with the trailing slash

func (*Mux) RegisterAutomaticOPTIONS

func (p *Mux) RegisterAutomaticOPTIONS(middleware ...Middleware)

RegisterAutomaticOPTIONS tells pure whether to automatically handle OPTION requests; manually configured OPTION handlers take precedence. default true

func (*Mux) RegisterMethodNotAllowed

func (p *Mux) RegisterMethodNotAllowed(middleware ...Middleware)

RegisterMethodNotAllowed tells pure whether to handle the http 405 Method Not Allowed status code

func (*Mux) Serve

func (p *Mux) Serve() http.Handler

Serve returns an http.Handler to be used.

func (*Mux) SetRedirectTrailingSlash

func (p *Mux) SetRedirectTrailingSlash(set bool)

SetRedirectTrailingSlash tells pure whether to try and fix a URL by trying to find it lowercase -> with or without slash -> 404

func (*Mux) Trace

func (g *Mux) Trace(path string, h http.HandlerFunc)

Trace adds a TRACE route & handler to the router.

func (*Mux) Use

func (g *Mux) Use(m ...Middleware)

Use adds a middleware handler to the group middleware chain.

type Param

type Param struct {
	Key   string
	Value string
}

Param is a single URL parameter, consisting of a key and a value.

type Params

type Params []Param

Params is a Param-slice, as returned by the router. The slice is ordered, the first URL parameter is also the first slice value. It is therefore safe to read values by the index.

func (Params) Get

func (p Params) Get(key string) (param string)

Get returns the URL parameter for the given key, or blank if not found

type ReqVars

type ReqVars interface {
	URLParam(pname string) string
	QueryParams() url.Values
}

ReqVars is the interface of request scoped variables tracked by pure

func RequestVars

func RequestVars(r *http.Request) ReqVars

RequestVars returns the request scoped variables tracked by pure

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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