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.
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
= 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
= 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.
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(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(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(s string) string
HTMLEscapeString returns s with special HTML characters escaped.
func HeaderName(name string) string
HeaderName returns the canonical format of the header name.
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(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(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(s string) string
QuoteHeaderValue quotes s using quoted-string rules described in RFC 2616.
func QuoteHeaderValueOrToken(s string) string
QuoteHeaderValueOrToken quotes s if s is not a valid token per RFC 2616.
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(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(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(status int) string
StatusText returns a text description of an HTTP status code.
func UnquoteHeaderValue(s string) string
UnquoteHeaderValue unquotes s if s is surrounded by quotes, otherwise s is returned.
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(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 (c *Cookie) Delete() *Cookie
Delete sets the expiration date to a time in the past.
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 (c *Cookie) HTTPOnly(httpOnly bool) *Cookie
HTTPOnly sets the httponly attribute. The NewCookie function initializes the httponly attribute to true.
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 (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 (c *Cookie) Secure(secure bool) *Cookie
Secure sets the secure attribute.
func (c *Cookie) String() string
String renders the Set-Cookie header value as a string.
type ErrorHandler func(req *Request, status int, reason error, header Header)
ErrorHandler handles request errors.
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 interface {
ServeWeb(req *Request)
}Handler is the interface for web handlers.
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(fname string, options *ServeFileOptions) Handler
FileHandler returns a request handler that serves a static file specified by fname.
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() Handler
NotFoundHandler returns a request handler that responds with 404 not found.
func ProcessForm(maxRequestBodyLen int, checkXSRF bool, handler Handler) Handler
PorcessForm is deprecated. Use FormHandler.
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(url string, permanent bool) Handler
RedirectHandler returns a request handler that redirects to the given URL.
func SetErrorHandler(e ErrorHandler, h Handler) Handler
SetErrorHandler returns a handler that sets the request's error handler e.
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 (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(kvs ...string) Header
NewHeader returns a map initialized with the given key-value pairs.
func (m Header) Add(key string, value string)
Add appends value to slice for given key.
func (m Header) Get(key string) string
Get returns the first value for given key or "" if the key is not found.
func (m Header) GetAccept(key string) []ValueParams
GetAccept returns a parsed Accept-* header in descending quality order.
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 (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 (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 (m Header) Set(key string, value string)
Set value for given key, discarding previous values if any.
func (m Header) WriteHttpHeader(w io.Writer) error
WriteHttpHeader writes the map in HTTP header format.
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(defaultHandler Handler) *HostRouter
NewHostRouter allocates and initializes a new HostRouter.
func (router *HostRouter) Register(hostPattern string, handler Handler) *HostRouter
Register a handler for the given pattern.
func (router *HostRouter) ServeWeb(req *Request)
ServeWeb dispatches the request to a registered handler.
type MultipartReader struct {
// contains filtered or unexported fields
}MultipartReader reads a multipart/form-data request body.
func NewMultipartReader(req *Request, maxRequestBodyLen int) (*MultipartReader, error)
NewMultipartReader returns a multipart/form-data reader.
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 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 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(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 (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 (req *Request) Error(status int, reason error, headerKeysAndValues ...string)
Error responds to the request with an error.
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 (req *Request) Redirect(urlStr string, perm bool, headerKeysAndValues ...string)
Redirect responds to the request with a redirect to the specified URL.
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 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 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() *Router
NewRouter allocates and initializes a new Router.
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 *Router) ServeWeb(req *Request)
ServeWeb dispatches the request to a registered handler.
type ServeFileOptions struct {
// Map file extension to mime type.
MimeType map[string]string
// Response headers.
Header Header
}
type ValueParams struct {
Value string
Param map[string]string
}ValueParams represents a value with parameters.
type Values map[string][]string
Values maps names to slices of values.
func NewValues(kvs ...string) Values
NewValues returns a map initialized with the given key-value pairs.
func (m Values) Add(key string, value string)
Add appends value to slice for given key.
func (m Values) FormEncodedBytes() []byte
FormEncodedBytes returns a buffer containing the URL form encoding of the map.
func (m Values) FormEncodedString() string
FormEncodedString returns a string containing the URL form encoding of the map.
func (m Values) Get(key string) string
Get returns the first value for given key or "" if the key is not found.
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 (m Values) Set(key string, value string)
Set value for given key, discarding previous values if any.
func (m Values) StringMap() map[string]string
StringMap returns a string to string map by discarding all but the first value for a key.
header.go handlers.go fs.go test.go misc.go values.go cookie.go deprecated.go web.go multipart.go middleware.go router.go