twister: github.com/garyburd/twister/web Index | Files

package web

import "github.com/garyburd/twister/web"

Package web defines Twister's application programming interface for web applications and implements functionality common to many web applications.

Index

Constants

const (
    HeaderAccept             = "Accept"
    HeaderAcceptCharset      = "Accept-Charset"
    HeaderAcceptEncoding     = "Accept-Encoding"
    HeaderAcceptLanguage     = "Accept-Language"
    HeaderAcceptRanges       = "Accept-Ranges"
    HeaderAge                = "Age"
    HeaderAllow              = "Allow"
    HeaderAuthorization      = "Authorization"
    HeaderCacheControl       = "Cache-Control"
    HeaderConnection         = "Connection"
    HeaderContentDisposition = "Content-Disposition"
    HeaderContentEncoding    = "Content-Encoding"
    HeaderContentLanguage    = "Content-Language"
    HeaderContentLength      = "Content-Length"
    HeaderContentLocation    = "Content-Location"
    HeaderContentMD5         = "Content-Md5"
    HeaderContentRange       = "Content-Range"
    HeaderContentType        = "Content-Type"
    HeaderCookie             = "Cookie"
    HeaderDate               = "Date"
    HeaderETag               = "Etag"
    HeaderEtag               = "Etag"
    HeaderExpect             = "Expect"
    HeaderExpires            = "Expires"
    HeaderFrom               = "From"
    HeaderHost               = "Host"
    HeaderIfMatch            = "If-Match"
    HeaderIfModifiedSince    = "If-Modified-Since"
    HeaderIfNoneMatch        = "If-None-Match"
    HeaderIfRange            = "If-Range"
    HeaderIfUnmodifiedSince  = "If-Unmodified-Since"
    HeaderLastModified       = "Last-Modified"
    HeaderLocation           = "Location"
    HeaderMaxForwards        = "Max-Forwards"
    HeaderOrigin             = "Origin"
    HeaderPragma             = "Pragma"
    HeaderProxyAuthenticate  = "Proxy-Authenticate"
    HeaderProxyAuthorization = "Proxy-Authorization"
    HeaderRange              = "Range"
    HeaderReferer            = "Referer"
    HeaderRetryAfter         = "Retry-After"
    HeaderServer             = "Server"
    HeaderSetCookie          = "Set-Cookie"
    HeaderTE                 = "Te"
    HeaderTrailer            = "Trailer"
    HeaderTransferEncoding   = "Transfer-Encoding"
    HeaderUpgrade            = "Upgrade"
    HeaderUserAgent          = "User-Agent"
    HeaderVary               = "Vary"
    HeaderVia                = "Via"
    HeaderWWWAuthenticate    = "Www-Authenticate"
    HeaderWarning            = "Warning"
    HeaderXXSRFToken         = "X-Xsrftoken"
)

Header names in canonical format.

const (
    XSRFCookieName = "xsrf"
    XSRFParamName  = "xsrf"
)

Name of XSRF cookie and request parameter.

const (
    StatusContinue                     = 100
    StatusSwitchingProtocols           = 101
    StatusOK                           = 200
    StatusCreated                      = 201
    StatusAccepted                     = 202
    StatusNonAuthoritativeInformation  = 203
    StatusNoContent                    = 204
    StatusResetContent                 = 205
    StatusPartialContent               = 206
    StatusMultipleChoices              = 300
    StatusMovedPermanently             = 301
    StatusFound                        = 302
    StatusSeeOther                     = 303
    StatusNotModified                  = 304
    StatusUseProxy                     = 305
    StatusTemporaryRedirect            = 307
    StatusBadRequest                   = 400
    StatusUnauthorized                 = 401
    StatusPaymentRequired              = 402
    StatusForbidden                    = 403
    StatusNotFound                     = 404
    StatusMethodNotAllowed             = 405
    StatusNotAcceptable                = 406
    StatusProxyAuthenticationRequired  = 407
    StatusRequestTimeout               = 408
    StatusConflict                     = 409
    StatusGone                         = 410
    StatusLengthRequired               = 411
    StatusPreconditionFailed           = 412
    StatusRequestEntityTooLarge        = 413
    StatusRequestURITooLong            = 414
    StatusUnsupportedMediaType         = 415
    StatusRequestedRangeNotSatisfiable = 416
    StatusExpectationFailed            = 417
    StatusInternalServerError          = 500
    StatusNotImplemented               = 501
    StatusBadGateway                   = 502
    StatusServiceUnavailable           = 503
    StatusGatewayTimeout               = 504
    StatusHTTPVersionNotSupported      = 505
)

HTTP status codes from RFC 2606

const (
    ProtocolVersion10 = 1000 // HTTP/1.0
    ProtocolVersion11 = 1001 // HTTP/1.1
)

Commonly used protocol versions in format returned by the ProtocolVersion function.

const ContentTypeHTML = "text/html; charset=\"utf-8\""

ContentTypeHTML is the content type for UTF-8 encoded HTML.

Variables

var (
    ErrLineTooLong    = errors.New("HTTP header line too long")
    ErrBadHeaderLine  = errors.New("could not parse HTTP header line")
    ErrHeaderTooLong  = errors.New("HTTP header value too long")
    ErrHeadersTooLong = errors.New("too many HTTP headers")
)
var (
    ErrInvalidState          = errors.New("twister: object in invalid state")
    ErrBadFormat             = errors.New("twister: bad data format")
    ErrRequestEntityTooLarge = errors.New("twister: HTTP request entity too large")
)
var ErrNotMultipartFormData = errors.New("twister: request not multipart/form-data")

func CheckXSRF

func CheckXSRF(req *Request, cookieName string, paramName string) error

CheckXSRF implements cross-site request forgery protection. Here's how it works:

CheckXSRF sets a cookie with name cookieName to a random token.

The application ensures that POSTed forms include a parameter with name paramName and value equal to the token.

POSTed forms are considered valid if the cookieName cookie is set and is equal to the paramName request parameter. A third party site cannot generate a request where the cookie and request parameter are equal because the third party site cannot access the cookie value.

CheckXSRF returns an error if the request is not valid. It is the application's responsibility to respond to the request with an appropriate error.

Before returning, CheckXSRF ensures that the paramName request parameter is set to the token. The application should use the value of the paramName parameter when generating hidden fields in POSTed forms.

CheckXSRF also validates PUT and DELETE requests.

The X-XSRFToken can be used to specify the token in addition to the paramName request parameter.

See http://en.wikipedia.org/wiki/Cross-site_request_forgery for information on cross-site request forgery.

func FilterRespond

func FilterRespond(req *Request, filter func(status int, header Header) (int, Header))

FilterRespond replaces the request's responder with one that filters the arguments to Respond through the supplied filter. This function is intended to be used by middleware.

func HTMLEscapeString

func HTMLEscapeString(s string) string

HTMLEscapeString returns s with special HTML characters escaped.

func HeaderName

func HeaderName(name string) string

HeaderName returns the canonical format of the header name.

func HeaderNameBytes

func HeaderNameBytes(p []byte) string

HeaderNameBytes returns the canonical format for the header name specified by the bytes in p. This function modifies the contents p.

func ParseMultipartForm

func ParseMultipartForm(req *Request, maxRequestBodyLen int) ([]Part, error)

ParseMultipartForm parses a multipart/form-data body. Form fields are added to the request Param. This function loads the entire request body in memory. If this is not appropriate, then the application should use MultipartReader to read the request body incrementally.

func ProtocolVersion

func ProtocolVersion(major int, minor int) int

ProtocolVersion combines HTTP major and minor protocol numbers into a single integer for easy comparison of protocol versions.

func QuoteHeaderValue

func QuoteHeaderValue(s string) string

QuoteHeaderValue quotes s using quoted-string rules described in RFC 2616.

func QuoteHeaderValueOrToken

func QuoteHeaderValueOrToken(s string) string

QuoteHeaderValueOrToken quotes s if s is not a valid token per RFC 2616.

func RunHandler

func RunHandler(urlStr string, method string, reqHeader Header, reqBody []byte, handler Handler) (status int, header Header, respBody []byte)

RunHandler runs the handler with a request created from the arguments and returns the response. This function is intended to be used in tests.

func ServeFile

func ServeFile(req *Request, fname string, options *ServeFileOptions)

ServeFile responds to the request with the contents of the named file.

If the "v" request parameter is set, then ServeFile sets the expires header and the cache control maximum age parameter to ten years in the future.

func SignValue

func SignValue(secret, context string, maxAge time.Duration, value string) string

SignValue returns a string containing value, an expiration time and a signature. The expiration time is computed from the current time and maxAge. The signature is an HMAC SHA-1 signature of value, context and the expiration time. Use the function VerifyValue to extract the value, check the expiration time and verify the signature.

SignValue can be used to store credentials in a cookie:

var secret string // Initialized by application
const uidCookieMaxAge = 3600 * 24 * 30

// uidCookieValue returns the Set-Cookie header value containing a
// signed and timestamped user id.
func uidCookieValue(uid string) string {
    s := web.SignValue(secret, "uid", uidCookieMaxAge, uid)
    return web.NewCookie("uid", s).MaxAge(uidCookieMaxAge).String()
}

// requestUid returns the user id from the request cookie. An error
// is returned if the cookie is missing, the value has expired or the
// signature is not valid.
func requestUid(req *web.Request) (string, os.Error) {
    return web.VerifyValue(secret, "uid", req.Cookie.Get("uid"))
}

func StatusText

func StatusText(status int) string

StatusText returns a text description of an HTTP status code.

func UnquoteHeaderValue

func UnquoteHeaderValue(s string) string

UnquoteHeaderValue unquotes s if s is surrounded by quotes, otherwise s is returned.

func VerifyValue

func VerifyValue(secret, context string, signedValue string) (string, error)

VerifyValue extracts a value from a string created by SignValue. An error is returned if the expiration time has elapsed or the signature is not correct.

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

Cookie is a helper for constructing Set-Cookie header values.

Cookie supports the ancient Netscape draft specification for cookies (http://goo.gl/1WSx3) and the modern HttpOnly attribute (http://www.owasp.org/index.php/HttpOnly). Cookie does not attempt to support any RFC for cookies because the RFCs are not supported by popular browsers.

As a convenience, the NewCookie function returns a cookie with the path attribute set to "/" and the httponly attribute set to true.

func NewCookie

func NewCookie(name, value string) *Cookie

NewCookie returns a new cookie with the given name and value, the path attribute set to "/" and the httponly attribute set to true.

func (*Cookie) Delete

func (c *Cookie) Delete() *Cookie

Delete sets the expiration date to a time in the past.

func (*Cookie) Domain

func (c *Cookie) Domain(domain string) *Cookie

Domain sets the cookie domain attribute. If the host is "", then the domain attribute is not included in the header value.

func (*Cookie) HTTPOnly

func (c *Cookie) HTTPOnly(httpOnly bool) *Cookie

HTTPOnly sets the httponly attribute. The NewCookie function initializes the httponly attribute to true.

func (*Cookie) MaxAge

func (c *Cookie) MaxAge(maxAge time.Duration) *Cookie

MaxAge specifies the maximum age for a cookie. If the maximum age is 0, then the expiration time is not included in the header value and the browser will handle the cookie as a "session" cookie. To support Internet Explorer, the maximum age is also rendered as an absolute expiration time.

func (*Cookie) Path

func (c *Cookie) Path(path string) *Cookie

Path sets the cookie path attribute. The path must either be "" or start with a '/'. The NewCookie function initializes the path to "/". If the path is "", then the path attribute is not included in the header value.

func (*Cookie) Secure

func (c *Cookie) Secure(secure bool) *Cookie

Secure sets the secure attribute.

func (*Cookie) String

func (c *Cookie) String() string

String renders the Set-Cookie header value as a string.

type ErrorHandler

type ErrorHandler func(req *Request, status int, reason error, header Header)

ErrorHandler handles request errors.

type Flusher

type Flusher interface {
    Flush() error
}

Flusher is implemented by response bodies that allow the HTTP handler to flush buffered data to the network. Flush data to the network is useful for implementing long polling and other Comet mechanisms.

type Handler

type Handler interface {
    ServeWeb(req *Request)
}

Handler is the interface for web handlers.

func DirectoryHandler

func DirectoryHandler(root string, options *ServeFileOptions) Handler

DirectoryHandler returns a request handler that serves static files from root using using the URL parameter "path". The "path" parameter is typically set using a Router pattern match:

r.Register("/static/<path:.*>", "GET", DirectoryHandler(root))

Directory handler does not serve directory listings.

func FileHandler

func FileHandler(fname string, options *ServeFileOptions) Handler

FileHandler returns a request handler that serves a static file specified by fname.

func FormHandler

func FormHandler(maxRequestBodyLen int, checkXSRF bool, h Handler) Handler

FormHandler returns a handler that parses form encoded request bodies.

If xsrfCheck is true, then cross-site request forgery protection is enabled using the cookie name XSRFCookieName and the parameter name XSRFParameterName. See CheckXSRF() for more information on cross-site request forgery protection.

func NotFoundHandler

func NotFoundHandler() Handler

NotFoundHandler returns a request handler that responds with 404 not found.

func ProcessForm

func ProcessForm(maxRequestBodyLen int, checkXSRF bool, handler Handler) Handler

PorcessForm is deprecated. Use FormHandler.

func ProxyHeaderHandler

func ProxyHeaderHandler(addrName, schemeName string, h Handler) Handler

ProxyHeaderHandler returns a handler that overrides the Request.RemoteAddr field with the value of the header specified by addrName and the Request.URL.Scheme field with the value of the header specified by schemeName. No fix up is done for a field if the header name equals "" or the header is not present.

The header names must be in canonical header name format.

Here's an example of how to use this handler with Nginx. In the nginx proxy configuration, specify a header for the IP address and scheme. The host header should also be passed through the proxy:

location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Scheme $scheme;
    proxy_set_header Host $http_host;
    proxy_pass http://127.0.0.1:8080;
}

In the main function for the application, wrap the application handler with the proxy fix up:

 import (
     "github.com/garyburd/twister/web"
     "github.com/garyburd/twister/server"
 )

 func main() {
     var h web.Handler
     ... setup the application handler
     h = web.ProxyHeaderHandler("X-Scheme", "X-Real-Ip", h)
	    server.Run(":8080", h)
 }

The original values are added to the request Env with the keys "twister.web.OriginalRemoteAddr" and "twister.web.OriginalScheme".

func RedirectHandler

func RedirectHandler(url string, permanent bool) Handler

RedirectHandler returns a request handler that redirects to the given URL.

func SetErrorHandler

func SetErrorHandler(e ErrorHandler, h Handler) Handler

SetErrorHandler returns a handler that sets the request's error handler e.

type HandlerFunc

type HandlerFunc func(*Request)

HandlerFunc is a type adapter to allow the use of ordinary functions as web handlers. If the function returns an error, then the adapter responds to the request with an error response.

func (HandlerFunc) ServeWeb

func (f HandlerFunc) ServeWeb(req *Request)

ServeWeb calls f(req).

type Header map[string][]string

Header maps header names to a slice of header values.

The header names must be in canonical format: the first letter and letters following '-' are uppercase and all other letters are lowercase. The Header* constants are in canonical format. Use the function HeaderName to convert a string to canonical format.

func NewHeader

func NewHeader(kvs ...string) Header

NewHeader returns a map initialized with the given key-value pairs.

func (Header) Add

func (m Header) Add(key string, value string)

Add appends value to slice for given key.

func (Header) Get

func (m Header) Get(key string) string

Get returns the first value for given key or "" if the key is not found.

func (Header) GetAccept

func (m Header) GetAccept(key string) []ValueParams

GetAccept returns a parsed Accept-* header in descending quality order.

func (Header) GetList

func (m Header) GetList(key string) []string

GetList returns list of comma separated values over multiple header values for the given key. Commas are ignored in quoted strings. Quoted values are not unescaped or unquoted. Whitespace is trimmed.

func (Header) GetValueParam

func (m Header) GetValueParam(key string) (value string, param map[string]string)

GetValueParam returns a value and optional semi-colon prefixed name-value pairs for header with name key. The value and parameter keys are converted to lowercase. All whitespace is trimmed. This format is used by the Content-Type and Content-Disposition headers.

func (Header) ParseHttpHeader

func (m Header) ParseHttpHeader(br *bufio.Reader) (err error)

ParseHttpHeader parses the HTTP headers and appends the values to the supplied map. Header names are converted to canonical format.

func (Header) Set

func (m Header) Set(key string, value string)

Set value for given key, discarding previous values if any.

func (Header) WriteHttpHeader

func (m Header) WriteHttpHeader(w io.Writer) error

WriteHttpHeader writes the map in HTTP header format.

type HostRouter

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

HostRouter is a request handler that dispatches HTTP requests to other handlers using the host HTTP header.

A host router has a list of routes where each route is a (pattern, handler) pair. The router dispatches requests by matching the host header against the patterns in the order that the routes were registered. If a matching route is found, the request is dispatched to the route's handler.

A pattern is a string with embedded parameters. A parameter has the syntax:

'<' name (':' regexp)? '>'

If the regular expression is not specified, then the regular expression [^.]+ is used.

Any matching parameters are in route pattern are stored in the in the request URLParam field.

func NewHostRouter

func NewHostRouter(defaultHandler Handler) *HostRouter

NewHostRouter allocates and initializes a new HostRouter.

func (*HostRouter) Register

func (router *HostRouter) Register(hostPattern string, handler Handler) *HostRouter

Register a handler for the given pattern.

func (*HostRouter) ServeWeb

func (router *HostRouter) ServeWeb(req *Request)

ServeWeb dispatches the request to a registered handler.

type MultipartReader

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

MultipartReader reads a multipart/form-data request body.

func NewMultipartReader

func NewMultipartReader(req *Request, maxRequestBodyLen int) (*MultipartReader, error)

NewMultipartReader returns a multipart/form-data reader.

func (*MultipartReader) Next

func (m *MultipartReader) Next() (Header, io.Reader, error)

Next returns the next part of a multipart/form-data body. Next returns os.EOF if no more parts remain.

type Part

type Part struct {
    Name         string
    Filename     string
    ContentType  string
    ContentParam map[string]string
    Data         []byte
}

Part represents an element of a multi-part request entity.

type Request

type Request struct {
    // The response.
    Responder Responder

    // Uppercase request method. GET, POST, etc.
    Method string

    // Raw URI from the first line of the request.
    RequestURI string

    // Protocol version: major version * 1000 + minor version
    ProtocolVersion int

    // The request URL with host and scheme set appropriately.
    URL *url.URL

    // The IP address of the client sending the request to the server.
    RemoteAddr string

    // Header maps canonical header names to slices of header values.
    Header Header

    // Request parameters from the query string and post body.
    Param Values

    // Cookies.
    Cookie Values

    // Parameters extracted from the request URL by a router.
    URLParam map[string]string

    // Lowercase content type, not including params.
    ContentType string

    // Parameters from Content-Type header
    ContentParam map[string]string

    // ErrorHandler responds to the request with the given status code.
    // Applications can set the error handler using middleware.
    ErrorHandler ErrorHandler

    // ContentLength is the length of the request body or -1 if the content
    // length is not known.
    ContentLength int

    // The request body.
    Body io.Reader

    // Attributes attached to the request by middleware.
    Env map[string]interface{}
}

Request represents an HTTP request to the server.

func NewRequest

func NewRequest(remoteAddr string, method string, requestURI string, protocolVersion int, u *url.URL, header Header) (req *Request, err error)

NewRequest allocates and initializes a request. This function is provided for the convenience of protocol adapters (fcgi, native http server, ...).

func (*Request) BodyBytes

func (req *Request) BodyBytes(maxLen int) ([]byte, error)

BodyBytes returns the request body a slice of bytes. If maxLen is negative, then no limit is imposed on the length of the body. If the body is longer than maxLen, then ErrRequestEntityTooLarge is returned.

func (*Request) Error

func (req *Request) Error(status int, reason error, headerKeysAndValues ...string)

Error responds to the request with an error.

func (*Request) ParseForm

func (req *Request) ParseForm(maxRequestBodyLen int) error

ParseForm parses url-encoded form bodies. ParseForm is idempotent. Most applications should use the FormHandler middleware instead of calling this method directly.

func (*Request) Redirect

func (req *Request) Redirect(urlStr string, perm bool, headerKeysAndValues ...string)

Redirect responds to the request with a redirect to the specified URL.

func (*Request) Respond

func (req *Request) Respond(status int, headerKeysAndValues ...string) io.Writer

Respond is a convenience function that adds (key, value) pairs in headerKeysAndValues to a Header and calls through to the responder's Respond method.

type Responder

type Responder interface {
    // Respond commits the status and headers to the network and returns
    // a writer for the response body.
    Respond(status int, header Header) (responseBody io.Writer)

    // Hijack lets the caller take over the connection from the HTTP server.
    // The caller is responsible for closing the connection. Returns connection
    // and bufio Reader with any data that might be buffered by the server.
    // Hijack is not supported by all servers.
    Hijack() (conn net.Conn, br *bufio.Reader, err error)
}

Responder represents the response.

type Router

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

Router is a request handler that dispatches HTTP requests to other handlers using the request URL path and the request method.

A router has a list of routes. A route is a request path pattern and a collection of (method, handler) pairs.

A path pattern is a string with embedded parameters. A parameter has the syntax:

'<' name (':' regular-expression)? '>'

If the regular expression is not specified, then the regular expression [^/]+ is used.

The pattern must begin with the character '/'.

A router dispatches requests by matching the request URL path against the registered route patterns in the order that the routes were registered. If a matching route is not found, then the router responds to the request with HTTP status 404.

If a matching route is found, then the router looks for a handler using the request method, "GET" if the request method is "HEAD" and "*". If a handler is not found, then the router responds to the request with HTTP status 405.

Any matching parameters are in route pattern are stored in the in the request URLParam field.

If a pattern ends with '/', then the router redirects the URL without the trailing slash to the URL with the trailing slash.

func NewRouter

func NewRouter() *Router

NewRouter allocates and initializes a new Router.

func (*Router) Register

func (router *Router) Register(pattern string, handlers ...interface{}) *Router

Register the route with the given pattern and handlers. The structure of the handlers argument is:

(method handler)+

where method is a string and handler is a Handler or a func(*Request). Use "*" to match all methods.

func (*Router) ServeWeb

func (router *Router) ServeWeb(req *Request)

ServeWeb dispatches the request to a registered handler.

type ServeFileOptions

type ServeFileOptions struct {
    // Map file extension to mime type.
    MimeType map[string]string

    // Response headers.
    Header Header
}

type ValueParams

type ValueParams struct {
    Value string
    Param map[string]string
}

ValueParams represents a value with parameters.

type Values

type Values map[string][]string

Values maps names to slices of values.

func NewValues

func NewValues(kvs ...string) Values

NewValues returns a map initialized with the given key-value pairs.

func (Values) Add

func (m Values) Add(key string, value string)

Add appends value to slice for given key.

func (Values) FormEncodedBytes

func (m Values) FormEncodedBytes() []byte

FormEncodedBytes returns a buffer containing the URL form encoding of the map.

func (Values) FormEncodedString

func (m Values) FormEncodedString() string

FormEncodedString returns a string containing the URL form encoding of the map.

func (Values) Get

func (m Values) Get(key string) string

Get returns the first value for given key or "" if the key is not found.

func (Values) ParseFormEncodedBytes

func (m Values) ParseFormEncodedBytes(p []byte) error

ParseFormEncodedBytes parses the URL-encoded form and appends the values to the supplied map. This function modifies the contents of p.

func (Values) Set

func (m Values) Set(key string, value string)

Set value for given key, discarding previous values if any.

func (Values) StringMap

func (m Values) StringMap() map[string]string

StringMap returns a string to string map by discarding all but the first value for a key.

Files

header.go handlers.go fs.go test.go misc.go values.go cookie.go deprecated.go web.go multipart.go middleware.go router.go

Package web imports 22 packages (graph) and is imported by 5 packages. Updated 2013-03-22. Refresh.