Documentation ¶
Overview ¶
Package safehttp provides a framework for building secure-by-default web applications. See https://github.com/google/go-safeweb#readme to learn about the goals and features.
Safe Responses ¶
HTTP responses need to be crafted carefully in order to prevent common web vulnerabilities like Cross-site Scripting (XSS). To help with this, we use Safe Responses.
Safe Responses are HTTP responses which have been determined to be safe when received by a modern, popular web browser. For example, we consider HTML responses generated using a template system enforcing contextual autoescaping to be safe, e.g. modern Angular or github.com/google/safehtml/template. Read more about contextual autoescaping here: https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/42934.pdf.
The Go Safe Web ResponseWriter implementation only accepts Safe Responses instead of byte slices.
Since different projects will consider different ways of crafting a response safe, we offer a way of configuring this in the framework. Whether a response is considered safe or not is determined by the Dispatcher.
Dispatcher ¶
An implementation of a Dispatcher should be provided by security experts in your project. The Dispatcher is called for every write method of the ResponseWriter and is used to determine whether the passed response should be considered safe. The Dispatcher is responsible for writing the response to the underlying http.ResponseWriter in a safe way.
Go Safe Web provides a DefaultDispatcher implementation which supports github.com/google/safehtml responses.
Warning: the security of the web application depends on a sound Dispatcher implementation. Make sure it is security-reviewed and keep it simple.
Interceptors ¶
Not all security features can be implemented using the Dispatcher alone. For instance, some requests should be rejected before they reach the handler in order to prevent from Cross-site Request Forgery (CSRF, XSRF). To support this, the framework uses Interceptors.
An Interceptor implements methods that run before the request is passed to the handler, and after the handler has committed a response. These are, respectively, Before and Commit.
Life of a Request ¶
To tie it all together, we will explain how a single request goes through the framework.
When the request reaches the server, the following happens:
1. The ServeMux routes the request (i.e. picks the appropriate Handler that will be eventually called). The HTTP method of the request is checked whether it matches any registered Handler.
2. [Before phase] The request is passed to all installed Interceptors, via their Before methods, in the order of installation on the ServeMux. Each of the Before methods can either let the execution continue by returning safehttp.NotWritten() (and not using any ResponseWriter write methods), or by actually writing a response. This would prevent further Before method calls of subsequent Interceptors.
3. The request is passed to the Handler. The Handler calls a write method of the ResponseWriter (e.g. Write, WriteError, Redirect...).
5. [Commit phase] Commit methods of the installed Interceptors are called, in LIFO order (i.e. first Interceptor to be called in Before phase is called last in the Commit phase). Commit methods can no longer influence the flow of the request, but can still set headers, cookies, response HTTP status code or even modify the response (if its type allows it).
6. Dispatcher After all Commit methods have been called, the framework passes the request to the Dispatcher. The Dispatcher determines the Content-Type of the response and whether the response should be considered a Safe Response. The Dispatcher is responsible for writing the response to the underlying http.ResponseWriter in a safe way.
7. The Handler returns the value returned by the ResponseWriter write method used. After the first write, any further writes are considered fatal errors. It is safe to use defer statements for cleanup tasks (e.g. closing a file that was used in a safehtml/template.Template response).
Stack trace of the flow:
Mux.ServeHTTP() --+ Mux routes the request and checks the method. --+ InterceptorFoo.Before() --+ InterceptorBar.Before() --+ InterceptorBaz.Before() --+ Handler() ----+ ResponseWriter.Write ------+ InterceptorBaz.Commit() // notice the inverted order ------+ InterceptorBar.Commit() ------+ InterceptorFoo.Commit() ------+ Dispatcher.Write() ----+ The result of the Response.Write() call is returned.
Error Responses ¶
Error responses are written using ResponseWriter.WriteError. They go through the usual Commit and Dispatcher phases.
Configuring the Mux ¶
TODO ¶
Incremental Adoption ¶
In order to migrate your service using http.Handlers to the safehttp package, we recommend you start doing that one endpoint at a time. Use RegisteredHandler to do this.
safeMuxConfig := /* configured ServeMuxConfig, including interceptors */ safeMuxConfig.Handle("/bar", safehttp.MethodGET, barGETSafeHandler) safeMuxConfig.Handle("/bar", safehttp.MethodPOST, barPOSTSafeHandler) safeMuxConfig.Handle("/xyz", safehttp.MethodPOST, xyzSafeHandler) safeMux := safeMuxConfig.Mux() // old, not yet migrated http.Handle("/foo", fooHandler) // new, migrated http.Handle("/bar", safehttp.RegisteredHandler(safeMux, "/bar")) http.Handle("/xyz", safehttp.RegisteredHandler(safeMux, "/xyz"))
Restricting Risky APIs ¶
Some APIs are easy-to-misuse in a security sensitive context. We choose to restrict these and require a security review for their usage in order to prevent vulnerabilities.
cmd/bancheck allows you to restrict APIs and check for their usage as part of the CI/CD pipeline and prevent potentially vulnerable code from being deployed. For detailed usage instructions, please see: https://pkg.go.dev/github.com/google/go-safeweb/cmd/bancheck
Index ¶
- Constants
- func IsLocalDev() bool
- func RegisteredHandler(mux *ServeMux, pattern string) http.Handler
- func UseLocalDev()
- type Cookie
- func (c *Cookie) DisableHTTPOnly()
- func (c *Cookie) DisableSecure()
- func (c *Cookie) Domain(domain string)
- func (c *Cookie) Name() string
- func (c *Cookie) Path(path string)
- func (c *Cookie) SameSite(s SameSite)
- func (c *Cookie) SetMaxAge(maxAge int)
- func (c *Cookie) String() string
- func (c *Cookie) Value() string
- type DefaultDispatcher
- type Dispatcher
- type ErrorResponse
- type FileServerResponse
- type Form
- func (f *Form) Bool(param string, defaultValue bool) bool
- func (f *Form) Err() error
- func (f *Form) Float64(param string, defaultValue float64) float64
- func (f *Form) Int64(param string, defaultValue int64) int64
- func (f *Form) Slice(param string, slicePtr interface{})
- func (f *Form) String(param string, defaultValue string) string
- func (f *Form) Uint64(param string, defaultValue uint64) uint64
- type Handler
- type HandlerFunc
- type Header
- type IncomingRequest
- func (r *IncomingRequest) Body() io.ReadCloser
- func (r *IncomingRequest) Context() context.Context
- func (r *IncomingRequest) Cookie(name string) (*Cookie, error)
- func (r *IncomingRequest) Cookies() []*Cookie
- func (r *IncomingRequest) Host() string
- func (r *IncomingRequest) Method() string
- func (r *IncomingRequest) MultipartForm(maxMemory int64) (*MultipartForm, error)
- func (r *IncomingRequest) PostForm() (*Form, error)
- func (r *IncomingRequest) URL() *URL
- func (r *IncomingRequest) WithContext(ctx context.Context) *IncomingRequest
- func (r *IncomingRequest) WithStrippedURLPrefix(prefix string) (*IncomingRequest, error)
- type Interceptor
- type InterceptorConfig
- type JSONResponse
- type Map
- type MultipartForm
- type NoContentResponse
- type RedirectResponse
- type Response
- type ResponseHeadersWriter
- type ResponseWriter
- type Result
- func ExecuteNamedTemplate(w ResponseWriter, t Template, name string, data interface{}) Result
- func ExecuteNamedTemplateWithFuncs(w ResponseWriter, t Template, name string, data interface{}, ...) Result
- func ExecuteTemplate(w ResponseWriter, t Template, data interface{}) Result
- func ExecuteTemplateWithFuncs(w ResponseWriter, t Template, data interface{}, fm map[string]interface{}) Result
- func NotWritten() Result
- func Redirect(w ResponseWriter, r *IncomingRequest, location string, code StatusCode) Result
- func WriteJSON(w ResponseWriter, data interface{}) Result
- type SameSite
- type ServeMux
- type ServeMuxConfig
- type Server
- func (s *Server) Clone() *Server
- func (s *Server) Close() error
- func (s *Server) ListenAndServe() error
- func (s *Server) ListenAndServeTLS(certFile, keyFile string) error
- func (s *Server) Serve(l net.Listener) error
- func (s *Server) ServeTLS(l net.Listener, certFile, keyFile string) error
- func (s *Server) Shutdown(ctx context.Context) error
- type StatusCode
- type Template
- type TemplateResponse
- type URL
Constants ¶
const ( MethodConnect = "CONNECT" // RFC 7231, 4.3.6 MethodDelete = "DELETE" // RFC 7231, 4.3.5 MethodGet = "GET" // RFC 7231, 4.3.1 MethodHead = "HEAD" // RFC 7231, 4.3.2 MethodOptions = "OPTIONS" // RFC 7231, 4.3.7 MethodPatch = "PATCH" // RFC 5789 MethodPost = "POST" // RFC 7231, 4.3.3 MethodPut = "PUT" // RFC 7231, 4.3.4 MethodTrace = "TRACE" // RFC 7231, 4.3.8 )
The HTTP request methods defined by RFC.
Variables ¶
This section is empty.
Functions ¶
func IsLocalDev ¶
func IsLocalDev() bool
IsLocalDev returns whether the framework is set up to use local development rules. Please see the doc on UseLocalDev.
func RegisteredHandler ¶
RegisteredHandler returns the combined (all request methods) handler registered for a given pattern. Returns nil if the exact pattern wasn't used to register any handlers.
This method is helpful for migrating services incrementally, endpoint by endpoint. The handler runs all the installed interceptors and the dispatcher.
Important ¶
This function does not attempt to do any kind of path matching. If the handler was registered using the ServeMuxConfig for a pattern "/foo/", this method will return the handler only when given "/foo/" as an argument, not "/foo" nor "/foo/x".
func UseLocalDev ¶
func UseLocalDev()
UseLocalDev instructs the framework to disable some security mechanisms that would make local development hard or impossible. This cannot be undone without restarting the program and should only be done before any other function or type of the framework is used. This function should ideally be called by the main package immediately after flag parsing. This configuration is not valid for production use.
Types ¶
type Cookie ¶
type Cookie struct {
// contains filtered or unexported fields
}
A Cookie represents an HTTP cookie as sent in the Set-Cookie header of an HTTP response or the Cookie header of an HTTP request.
See https://tools.ietf.org/html/rfc6265 for details.
func NewCookie ¶
NewCookie creates a new Cookie with safe default settings. Those safe defaults are:
- Secure: true (if the framework is not in dev mode)
- HttpOnly: true
- SameSite: Lax
For more info about all the options, see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
func (*Cookie) DisableHTTPOnly ¶
func (c *Cookie) DisableHTTPOnly()
DisableHTTPOnly disables the HttpOnly attribute.
func (*Cookie) DisableSecure ¶
func (c *Cookie) DisableSecure()
DisableSecure disables the secure attribute.
func (*Cookie) SetMaxAge ¶
SetMaxAge sets the MaxAge attribute.
- MaxAge = 0 means no 'Max-Age' attribute specified. - MaxAge < 0 means delete cookie now, equivalently 'Max-Age: 0' - MaxAge > 0 means Max-Age attribute present and given in seconds
type DefaultDispatcher ¶
type DefaultDispatcher struct{}
DefaultDispatcher is responsible for writing safe responses.
func (DefaultDispatcher) Error ¶
func (DefaultDispatcher) Error(rw http.ResponseWriter, resp ErrorResponse) error
Error writes the error response to the http.ResponseWriter.
Error sets the Content-Type to "text/plain; charset=utf-8" through calling WriteTextError.
func (DefaultDispatcher) Write ¶
func (DefaultDispatcher) Write(rw http.ResponseWriter, resp Response) error
Write writes the response to the http.ResponseWriter if it's deemed safe. It returns a non-nil error if the response is deemed unsafe or if the writing operation fails.
For JSONResponses, the underlying object is serialised and written if it's a valid JSON.
For TemplateResponses, the parsed template is applied to the provided data object. If the funcMap is non-nil, its elements override the existing names to functions mappings in the template. An attempt to define a new name to function mapping that is not already in the template will result in a panic.
Write sets the Content-Type accordingly.
type Dispatcher ¶
type Dispatcher interface { // Write writes a Response to the underlying http.ResponseWriter. // // Write is responsible for setting the Content-Type response header. If the // Dispatcher doesn't set the HTTP response status code, the default // behavior of http.ResponseWriter applies (i.e. 200 OK is set on first // Write). // // It should return an error if the writing operation fails or if the // provided Response should not be written to the http.ResponseWriter // because it's unsafe. Write(rw http.ResponseWriter, resp Response) error // Error writes an ErrorResponse to the underlying http.ResponseWriter. // // Error is responsible for setting the Content-Type response header and the // HTTP response status code. // // It should return an error if the writing operation fails. // // Error should always attempt to write a response, no matter what is the // underlying type of resp. As a fallback, the Dispatcher can use WriteTextError. Error(rw http.ResponseWriter, resp ErrorResponse) error }
Dispatcher is responsible for writing a response received from the ResponseWriter to the underlying http.ResponseWriter.
The implementation of a custom Dispatcher should be thoroughly reviewed by the security team to avoid introducing vulnerabilities.
type ErrorResponse ¶
type ErrorResponse interface {
Code() StatusCode
}
ErrorResponse is an HTTP error response. The Dispatcher is responsible for determining whether it is safe.
type FileServerResponse ¶
type FileServerResponse struct { // The URL path. Path string // contains filtered or unexported fields }
FileServerResponse represents a FileServer response.
func (FileServerResponse) ContentType ¶
func (resp FileServerResponse) ContentType() string
ContentType is the Content-Type of the response.
type Form ¶
type Form struct {
// contains filtered or unexported fields
}
Form contains parsed data from form parameters, part of the body of POST, PATCH or PUT requests that are not multipart requests.
func (*Form) Bool ¶
Bool returns the first form parameter value. If the first value is not a valid bool, the defaultValue is returned instead and an error is set (retrievable by Err()).
func (*Form) Err ¶
Err returns nil unless an error occurred while accessing a parsed form value. Calling this method will return the last error that occurred while parsing form values.
func (*Form) Float64 ¶
Float64 returns the first form parameter value. If the first value is not a valid float64, the defaultValue is returned instead and an error is set (retrievable by Err()).
func (*Form) Int64 ¶
Int64 returns the first form parameter value. If the first value is not a valid int64, the defaultValue is returned instead and an error is set (retrievable by Err()).
func (*Form) Slice ¶
Slice returns the form parameter values. If the values don't have the same type, slicePtr will point to a nil slice instead and an error is set (retrievable by Err()). This function should be used in case a form parameter maps to multiple values.
TODO(mihalimara22): Simplify this function to avoid duplicate logic
type Handler ¶
type Handler interface { // ServeHTTP writes the response exactly once, returning the result // // Except for reading the body, handlers should not modify the provided Request. // // TODO: Add documentation about error handling when properly implemented. ServeHTTP(ResponseWriter, *IncomingRequest) Result }
Handler responds to an HTTP request.
func FileServer ¶
FileServer returns a handler that serves HTTP requests with the contents of the file system rooted at root.
func FileServerEmbed ¶
func StripPrefix ¶
StripPrefix returns a handler that serves HTTP requests by removing the given prefix from the request URL's Path (and RawPath if set) and invoking the handler h.
StripPrefix handles a request for a path that doesn't begin with prefix by panicking, as this is a server configuration error. The prefix must match exactly (e.g. escaped and unescaped characters are considered different).
type HandlerFunc ¶
type HandlerFunc func(ResponseWriter, *IncomingRequest) Result
HandlerFunc is used to convert a function into a Handler.
func (HandlerFunc) ServeHTTP ¶
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *IncomingRequest) Result
ServeHTTP calls f(w, r).
type Header ¶
type Header struct {
// contains filtered or unexported fields
}
Header represents the key-value pairs in an HTTP header. The keys will be in canonical form, as returned by textproto.CanonicalMIMEHeaderKey.
func (Header) Add ¶
Add adds a new header with the given name and the given value to the collection of headers. The name is first canonicalized using textproto.CanonicalMIMEHeaderKey. It panics when applied on claimed headers or on the Set-Cookie header.
func (Header) Claim ¶
Claim claims the header with the given name and returns a function which can be used to set the header. The name is first canonicalized using textproto.CanonicalMIMEHeaderKey. Other methods in the struct can't write to, change or delete the header with this name. These methods will instead panic when applied on a claimed header. The only way to modify the header is to use the returned function. The Set-Cookie header can't be claimed.
func (Header) Del ¶
Del deletes all headers with the given name. The name is first canonicalized using textproto.CanonicalMIMEHeaderKey. It panics when applied on claimed headers or on the Set-Cookie header.
func (Header) Get ¶
Get returns the value of the first header with the given name. The name is first canonicalized using textproto.CanonicalMIMEHeaderKey. If no header exists with the given name then "" is returned.
func (Header) IsClaimed ¶
IsClaimed reports whether the provided header is already claimed. The name is first canonicalized using textproto.CanonicalMIMEHeaderKey. The Set-Cookie header is treated as claimed.
func (Header) Set ¶
Set sets the header with the given name to the given value. The name is first canonicalized using textproto.CanonicalMIMEHeaderKey. This method first removes all other values associated with this header before setting the new value. It panics when applied on claimed headers or on the Set-Cookie header.
func (Header) Values ¶
Values returns all the values of all the headers with the given name. The name is first canonicalized using textproto.CanonicalMIMEHeaderKey. The values are returned in the same order as they were sent in the request. The values are returned as a copy of the original slice of strings in the internal header map. This is to prevent modification of the original slice. If no header exists with the given name then an empty slice is returned.
type IncomingRequest ¶
type IncomingRequest struct { // Header is the collection of HTTP headers. // // The Host header is removed from this struct and can be retrieved using Host() Header Header // TLS is set just like this TLS field of the net/http.Request. For more information // see https://pkg.go.dev/net/http?tab=doc#Request. TLS *tls.ConnectionState // contains filtered or unexported fields }
IncomingRequest represents an HTTP request received by the server.
func NewIncomingRequest ¶
func NewIncomingRequest(req *http.Request) *IncomingRequest
NewIncomingRequest creates an IncomingRequest from the underlying http.Request.
func (*IncomingRequest) Body ¶
func (r *IncomingRequest) Body() io.ReadCloser
Body returns the request body reader. It is always non-nil but will return EOF immediately when no body is present.
func (*IncomingRequest) Context ¶
func (r *IncomingRequest) Context() context.Context
Context returns the context of a safehttp.IncomingRequest. This is always non-nil and will default to the background context. The context of a safehttp.IncomingRequest is the context of the underlying http.Request.
The context is cancelled when the client's connection closes, the request is canceled (with HTTP/2), or when the ServeHTTP method returns.
func (*IncomingRequest) Cookie ¶
func (r *IncomingRequest) Cookie(name string) (*Cookie, error)
Cookie returns the named cookie provided in the request or net/http.ErrNoCookie if not found. If multiple cookies match the given name, only one cookie will be returned.
func (*IncomingRequest) Cookies ¶
func (r *IncomingRequest) Cookies() []*Cookie
Cookies parses and returns the HTTP cookies sent with the request.
func (*IncomingRequest) Host ¶
func (r *IncomingRequest) Host() string
Host returns the host the request is targeted to. This value comes from the Host header.
func (*IncomingRequest) Method ¶
func (r *IncomingRequest) Method() string
Method returns the HTTP method of the IncomingRequest.
func (*IncomingRequest) MultipartForm ¶
func (r *IncomingRequest) MultipartForm(maxMemory int64) (*MultipartForm, error)
MultipartForm parses the form parameters provided in the body of a POST, PATCH or PUT request that has Content-Type set to multipart/form-data. It returns a MultipartForm object containing the parsed form parameters and file uploads (if any) or the parsing error together with a nil MultipartForm otherwise.
If the parsed request body is larger than maxMemory, up to maxMemory bytes will be stored in main memory, with the rest stored on disk in temporary files.
func (*IncomingRequest) PostForm ¶
func (r *IncomingRequest) PostForm() (*Form, error)
PostForm parses the form parameters provided in the body of a POST, PATCH or PUT request that does not have Content-Type: multipart/form-data. It returns the parsed form parameters as a Form object. If a parsing error occurs it will return it, together with a nil Form. Unless we expect the header Content-Type: multipart/form-data in a POST request, this method should always be used for forms in POST requests.
func (*IncomingRequest) URL ¶
func (r *IncomingRequest) URL() *URL
URL specifies the URL that is parsed from the Request-Line. For most requests, only URL.Path() will return a non-empty result. (See RFC 7230, Section 5.3)
func (*IncomingRequest) WithContext ¶
func (r *IncomingRequest) WithContext(ctx context.Context) *IncomingRequest
WithContext returns a shallow copy of the request with its context changed to ctx. The provided ctx must be non-nil.
This is similar to the net/http.Request.WithContext method.
func (*IncomingRequest) WithStrippedURLPrefix ¶
func (r *IncomingRequest) WithStrippedURLPrefix(prefix string) (*IncomingRequest, error)
WithStrippedURLPrefix returns a shallow copy of the request with its URL stripped of a prefix. The prefix has to match exactly (e.g. escaped and unescaped characters are considered different).
type Interceptor ¶
type Interceptor interface { // Before runs before the IncomingRequest is sent to the handler. If a // response is written to the ResponseWriter, then the remaining // interceptors and the handler won't execute. If Before panics, it will be // recovered and the ServeMux will respond with 500 Internal Server Error. Before(w ResponseWriter, r *IncomingRequest, cfg InterceptorConfig) Result // Commit runs before the response is written by the Dispatcher. If an error // is written to the ResponseWriter, then the Commit phases from the // remaining interceptors won't execute. Commit(w ResponseHeadersWriter, r *IncomingRequest, resp Response, cfg InterceptorConfig) // Match checks whether the given config is meant to be applied to the Interceptor. Match(InterceptorConfig) bool }
Interceptor alter the processing of incoming requests.
See the documentation for ServeMux.ServeHTTP to understand how interceptors are run, what happens in case of errors during request processing (i.e. which interceptor methods are guaranteed to be run) etc.
Interceptors keep their state across many requests and their methods can be called concurrently. If you need per-request state, use FlightValues.
type InterceptorConfig ¶
type InterceptorConfig interface{}
InterceptorConfig is a configuration for an interceptor.
type JSONResponse ¶
type JSONResponse struct {
Data interface{}
}
JSONResponse should encapsulate a valid JSON object that will be serialised and written to the http.ResponseWriter using a JSON encoder.
type Map ¶
type Map interface { // Put inserts a key/value pair into the map. If the key already exists in // the map, it's value is replaced. Put(key, value interface{}) // Get returns a value for a given key in the map. If the entry with a given // key does not exist, nil is returned. Get(key interface{}) interface{} }
Map is a key/value map.
func FlightValues ¶
FlightValues returns a map associated with the given request processing flight. Use it if your interceptors need state that has the lifetime of the request.
type MultipartForm ¶
type MultipartForm struct { Form // contains filtered or unexported fields }
MultipartForm extends a parsed multipart form, part of the body of a PATCH, POST or PUT request. A multipart form can include both form values and file uploads, stored either in memory or on disk.
func (*MultipartForm) File ¶
func (f *MultipartForm) File(param string) []*multipart.FileHeader
File returns the file parts associated with form key param or a nil slice, if none. These can be then opened individually by calling FileHeader.Open.
func (*MultipartForm) RemoveFiles ¶
func (f *MultipartForm) RemoveFiles() error
RemoveFiles removes any temporary files associated with a Form and returns the first error that occured, if any.
type NoContentResponse ¶
type NoContentResponse struct{}
NoContentResponse is used to write a "No Content" response.
type RedirectResponse ¶
type RedirectResponse struct { // Code is the status to use for the redirect. Code StatusCode // Location is the value to use for the redirect Location. Location string // Request is the matching request for which this response is being written. // It is used to build the redirect response. Request *IncomingRequest }
RedirectResponse is used to generate redirect responses.
type Response ¶
type Response interface{}
Response should encapsulate the data passed to the ResponseWriter to be written by the Dispatcher. Any implementation of the interface should be supported by the Dispatcher.
type ResponseHeadersWriter ¶
type ResponseHeadersWriter interface { // Header returns the collection of headers that will be set // on the response. Headers must be set before writing a // response (e.g. Write, WriteTemplate). Header() Header // AddCookie adds a Set-Cookie header to the provided ResponseWriter's headers. // The provided cookie must have a valid Name, otherwise an error will be // returned. AddCookie(c *Cookie) error }
ResponseHeadersWriter is used to alter the HTTP response headers.
A ResponseHeadersWriter may not be used after the Handler.ServeHTTP method has returned.
type ResponseWriter ¶
type ResponseWriter interface { ResponseHeadersWriter // Write writes a safe response. Write(resp Response) Result // WriteError writes an error response (400-599). // // If the ResponseWriter has already been written to, then this method panics. WriteError(resp ErrorResponse) Result }
ResponseWriter is used to construct an HTTP response. When a Response is passed to the ResponseWriter, it will invoke the Dispatcher with the Response. An attempt to write to the ResponseWriter twice will cause a panic.
A ResponseWriter may not be used after the Handler.ServeHTTP method has returned.
type Result ¶
type Result struct{}
Result is the result of writing an HTTP response.
Use ResponseWriter methods to obtain it.
func ExecuteNamedTemplate ¶
func ExecuteNamedTemplate(w ResponseWriter, t Template, name string, data interface{}) Result
ExecuteNamedTemplate creates a TemplateResponse from the provided Template and its data and calls the Write function of the ResponseWriter, passing the response. Leaving name empty is valid if the template does not have associated templates.
func ExecuteNamedTemplateWithFuncs ¶
func ExecuteNamedTemplateWithFuncs(w ResponseWriter, t Template, name string, data interface{}, fm map[string]interface{}) Result
ExecuteNamedTemplateWithFuncs creates a TemplateResponse from the provided Template, its data and the name to function mappings and calls the Write function of the ResponseWriter, passing the response. Leaving name empty is valid if the template does not have associated templates.
func ExecuteTemplate ¶
func ExecuteTemplate(w ResponseWriter, t Template, data interface{}) Result
ExecuteTemplate creates a TemplateResponse from the provided Template and its data and calls the Write function of the ResponseWriter, passing the response.
func ExecuteTemplateWithFuncs ¶
func ExecuteTemplateWithFuncs(w ResponseWriter, t Template, data interface{}, fm map[string]interface{}) Result
ExecuteTemplateWithFuncs creates a TemplateResponse from the provided Template, its data and the name to function mappings and calls the Write function of the ResponseWriter, passing the response. Leaving name empty is valid if the template does not have associated templates.
func NotWritten ¶
func NotWritten() Result
NotWritten returns a Result which indicates that nothing has been written yet. It can be used in all functions that return a Result, such as in the ServeHTTP method of a Handler or in the Before method of an Interceptor. When returned, NotWritten indicates that the writing of the response should take place later. When this is returned by the Before method in Interceptors the next Interceptor in line is run. When this is returned by a Handler, a 204 No Content response is written.
func Redirect ¶
func Redirect(w ResponseWriter, r *IncomingRequest, location string, code StatusCode) Result
Redirect creates a RedirectResponse and writes it to w. If the given code is not a valid Redirect code this function will panic.
func WriteJSON ¶
func WriteJSON(w ResponseWriter, data interface{}) Result
WriteJSON creates a JSONResponse from the data object and calls the Write function of the ResponseWriter, passing the response. The data object should be valid JSON, otherwise an error will occur.
type SameSite ¶
type SameSite int
SameSite allows a server to define a cookie attribute making it impossible for the browser to send this cookie along with cross-site requests. The main goal is to mitigate the risk of cross-origin information leakage, and provide some protection against cross-site request forgery attacks.
See https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00 for details.
const ( // SameSiteLaxMode allows sending cookies with same-site requests and // cross-site top-level navigations. SameSiteLaxMode SameSite = iota + 1 // SameSiteStrictMode allows sending cookie only with same-site requests. SameSiteStrictMode // SameSiteNoneMode allows sending cookies with all requests, including the // ones made cross-origin. SameSiteNoneMode )
type ServeMux ¶
type ServeMux struct {
// contains filtered or unexported fields
}
ServeMux is an HTTP request multiplexer. It matches the URL of each incoming request against a list of registered patterns and calls the handler for the pattern that most closely matches the URL.
Patterns names are fixed, rooted paths, like "/favicon.ico", or rooted subtrees like "/images/" (note the trailing slash). Longer patterns take precedence over shorter ones, so that if there are handlers registered for both "/images/" and "/images/thumbnails/", the latter handler will be called for paths beginning "/images/thumbnails/" and the former will receive requests for any other paths in the "/images/" subtree.
Note that since a pattern ending in a slash names a rooted subtree, the pattern "/" matches all paths not matched by other registered patterns, not just the URL with Path == "/".
If a subtree has been registered and a request is received naming the subtree root without its trailing slash, ServeMux redirects that request to the subtree root (adding the trailing slash). This behavior can be overridden with a separate registration for the path without the trailing slash. For example, registering "/images/" causes ServeMux to redirect a request for "/images" to "/images/", unless "/images" has been registered separately.
Patterns may optionally begin with a host name, restricting matches to URLs on that host only. Host-specific patterns take precedence over general patterns, so that a handler might register for the two patterns "/codesearch" and "codesearch.google.com/" without also taking over requests for "http://www.google.com/".
ServeMux also takes care of sanitizing the URL request path and the Host header, stripping the port number and redirecting any request containing . or .. elements or repeated slashes to an equivalent, cleaner URL.
Multiple handlers can be registered for a single pattern, as long as they handle different HTTP methods.
func (*ServeMux) Handle ¶
func (m *ServeMux) Handle(pattern string, method string, h Handler, cfgs ...InterceptorConfig)
Handle registers a handler for the given pattern and method. If a handler is registered twice for the same pattern and method, Build will panic.
InterceptorConfigs can be passed in order to modify the behavior of the interceptors on a registered handler. Passing an InterceptorConfig whose corresponding Interceptor was not installed will produce no effect. If multiple configurations are passed for the same Interceptor, Mux will panic.
func (*ServeMux) ServeHTTP ¶
func (m *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP dispatches the request to the handler whose method matches the incoming request and whose pattern most closely matches the request URL.
For each incoming request: - [Before Phase] Interceptor.Before methods are called for every installed interceptor, until an interceptor writes to a ResponseWriter (including errors) or panics, - the handler is called after a [Before Phase] if no writes or panics occured, - the handler triggers the [Commit Phase] by writing to the ResponseWriter, - [Commit Phase] Interceptor.Commit methods run for every interceptor whose Before method was called, - [Dispatcher Phase] after the [Commit Phase], the Dispatcher's appropriate write method is called; the Dispatcher is responsible for determining whether the response is indeed safe and writing it, - if the handler attempts to write more than once, it is treated as an unrecoverable error; the request processing ends abrubptly with a panic and nothing else happens (note: this will change as soon as [After Phase] is introduced)
Interceptors should NOT rely on the order they're run.
type ServeMuxConfig ¶
type ServeMuxConfig struct {
// contains filtered or unexported fields
}
ServeMuxConfig is a builder for ServeMux.
func NewServeMuxConfig ¶
func NewServeMuxConfig(disp Dispatcher) *ServeMuxConfig
NewServeMuxConfig crates a ServeMuxConfig with the provided Dispatcher. If the provided Dispatcher is nil, the DefaultDispatcher is used.
func (*ServeMuxConfig) Clone ¶
func (s *ServeMuxConfig) Clone() *ServeMuxConfig
Clone creates a copy of the current config. This can be used to create several instances of Mux that share the same set of plugins.
func (*ServeMuxConfig) HandleMethodNotAllowed ¶
func (s *ServeMuxConfig) HandleMethodNotAllowed(h Handler, cfgs ...InterceptorConfig)
HandleMethodNotAllowed registers a handler that runs when a given method is not allowed for a registered path.
func (*ServeMuxConfig) Intercept ¶
func (s *ServeMuxConfig) Intercept(is ...Interceptor)
Intercept installs the given interceptors.
Interceptors order is respected and interceptors are always run in the order they've been installed.
Calling Intercept multiple times is valid. Interceptors that are added last will run last.
func (*ServeMuxConfig) Mux ¶
func (s *ServeMuxConfig) Mux() *ServeMux
Mux returns the ServeMux with a copy of the current configuration.
type Server ¶
type Server struct { // Addr optionally specifies the TCP address for the server to listen on, // in the form "host:port". If empty, ":http" (port 80) is used. // The service names are defined in RFC 6335 and assigned by IANA. // See net.Dial for details of the address format. Addr string // Mux is the ServeMux to use for the current server. A nil Mux is invalid. Mux *ServeMux // ReadTimeout is the maximum duration for reading the entire // request, including the body. ReadTimeout time.Duration // WriteTimeout is the maximum duration before timing out // writes of the response. It is reset whenever a new // request's header is read. WriteTimeout time.Duration // IdleTimeout is the maximum amount of time to wait for the // next request when keep-alives are enabled. IdleTimeout time.Duration // MaxHeaderBytes controls the maximum number of bytes the // server will read parsing the request header's keys and // values, including the request line. It does not limit the // size of the request body. MaxHeaderBytes int // TLSConfig optionally provides a TLS configuration for use // by ServeTLS and ListenAndServeTLS. Note that this value is // cloned on serving, so it's not possible to modify the // configuration with methods like tls.Config.SetSessionTicketKeys. // // When the server is started the cloned configuration will be changed // to set the minimum TLS version to 1.2 and to prefer Server Ciphers. TLSConfig *tls.Config // OnShutdown is a slice of functions to call on Shutdown. // This can be used to gracefully shutdown connections that have undergone // ALPN protocol upgrade or that have been hijacked. // These functions should start protocol-specific graceful shutdown, but // should not wait for shutdown to complete. OnShutdown []func() // DisableKeepAlives controls whether HTTP keep-alives should be disabled. DisableKeepAlives bool // contains filtered or unexported fields }
Server is a safe wrapper for a standard HTTP server. The zero value is safe and ready to use and will apply safe defaults on serving. Changing any of the fields after the server has been started is a no-op.
func (*Server) Clone ¶
Clone returns an unstarted deep copy of Server that can be re-configured and re-started.
func (*Server) Close ¶
Close is a wrapper for https://golang.org/pkg/net/http/#Server.Close
func (*Server) ListenAndServe ¶
ListenAndServe is a wrapper for https://golang.org/pkg/net/http/#Server.ListenAndServe
func (*Server) ListenAndServeTLS ¶
ListenAndServeTLS is a wrapper for https://golang.org/pkg/net/http/#Server.ListenAndServeTLS
func (*Server) Serve ¶
Serve is a wrapper for https://golang.org/pkg/net/http/#Server.Serve
func (*Server) ServeTLS ¶
ServeTLS is a wrapper for https://golang.org/pkg/net/http/#Server.ServeTLS
type StatusCode ¶
type StatusCode int
StatusCode contains HTTP status codes as registered with IANA. See: https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
const ( StatusContinue StatusCode = 100 // RFC 7231, 6.2.1 StatusSwitchingProtocols StatusCode = 101 // RFC 7231, 6.2.2 StatusProcessing StatusCode = 102 // RFC 2518, 10.1 StatusEarlyHints StatusCode = 103 // RFC 8297 StatusOK StatusCode = 200 // RFC 7231, 6.3.1 StatusCreated StatusCode = 201 // RFC 7231, 6.3.2 StatusAccepted StatusCode = 202 // RFC 7231, 6.3.3 StatusNonAuthoritativeInfo StatusCode = 203 // RFC 7231, 6.3.4 StatusNoContent StatusCode = 204 // RFC 7231, 6.3.5 StatusResetContent StatusCode = 205 // RFC 7231, 6.3.6 StatusPartialContent StatusCode = 206 // RFC 7233, 4.1 StatusMultiStatus StatusCode = 207 // RFC 4918, 11.1 StatusAlreadyReported StatusCode = 208 // RFC 5842, 7.1 StatusIMUsed StatusCode = 226 // RFC 3229, 10.4.1 StatusMultipleChoice StatusCode = 300 // RFC 7231, 6.4.1 StatusMovedPermanently StatusCode = 301 // RFC 7231, 6.4.2 StatusFound StatusCode = 302 // RFC 7231, 6.4.3 StatusSeeOther StatusCode = 303 // RFC 7231, 6.4.4 StatusNotModified StatusCode = 304 // RFC 7232, 4.1 StatusUseProxy StatusCode = 305 // RFC 7231, 6.4.5 StatusTemporaryRedirect StatusCode = 307 // RFC 7231, 6.4.7 StatusPermanentRedirect StatusCode = 308 // RFC 7538, 3 StatusBadRequest StatusCode = 400 // RFC 7231, 6.5.1 StatusPaymentRequired StatusCode = 402 // RFC 7231, 6.5.2 StatusForbidden StatusCode = 403 // RFC 7231, 6.5.3 StatusNotFound StatusCode = 404 // RFC 7231, 6.5.4 StatusMethodNotAllowed StatusCode = 405 // RFC 7231, 6.5.5 StatusNotAcceptable StatusCode = 406 // RFC 7231, 6.5.6 StatusProxyAuthRequired StatusCode = 407 // RFC 7235, 3.2 StatusRequestTimeout StatusCode = 408 // RFC 7231, 6.5.7 StatusConflict StatusCode = 409 // RFC 7231, 6.5.8 StatusGone StatusCode = 410 // RFC 7231, 6.5.9 StatusLengthRequired StatusCode = 411 // RFC 7231, 6.5.10 StatusPreconditionFailed StatusCode = 412 // RFC 7232, 4.2 StatusRequestEntityTooLarge StatusCode = 413 // RFC 7231, 6.5.11 StatusRequestURITooLong StatusCode = 414 // RFC 7231, 6.5.12 StatusUnsupportedMediaType StatusCode = 415 // RFC 7231, 6.5.13 StatusRequestedRangeNotSatisfiable StatusCode = 416 // RFC 7233, 4.4 StatusExpectationFailed StatusCode = 417 // RFC 7231, 6.5.14 StatusTeapot StatusCode = 418 // RFC 7168, 2.3.3 StatusMisdirectedRequest StatusCode = 421 // RFC 7540, 9.1.2 StatusUnprocessableEntity StatusCode = 422 // RFC 4918, 11.2 StatusLocked StatusCode = 423 // RFC 4918, 11.3 StatusFailedDependency StatusCode = 424 // RFC 4918, 11.4 StatusTooEarly StatusCode = 425 // RFC 8470, 5.2. StatusUpgradeRequired StatusCode = 426 // RFC 7231, 6.5.15 StatusPreconditionRequired StatusCode = 428 // RFC 6585, 3 StatusTooManyRequests StatusCode = 429 // RFC 6585, 4 StatusRequestHeaderFieldsTooLarg StatusCode = 431 // RFC 6585, 5 StatusInternalServerError StatusCode = 500 // RFC 7231, 6.6.1 StatusNotImplemented StatusCode = 501 // RFC 7231, 6.6.2 StatusBadGateway StatusCode = 502 // RFC 7231, 6.6.3 StatusGatewayTimeout StatusCode = 504 // RFC 7231, 6.6.5 StatusHTTPVersionNotSupported StatusCode = 505 // RFC 7231, 6.6.6 StatusVariantAlsoNegotiates StatusCode = 506 // RFC 2295, 8.1 StatusInsufficientStorage StatusCode = 507 // RFC 4918, 11.5 StatusLoopDetected StatusCode = 508 // RFC 5842, 7.2 StatusNotExtended StatusCode = 510 // RFC 2774, 7 StatusNetworkAuthenticationRequired StatusCode = 511 // RFC 6585, 6 )
The HTTP status codes registered with IANA.
func (StatusCode) String ¶
func (c StatusCode) String() string
type Template ¶
type Template interface { // Execute applies data to the template and then writes the result to // the io.Writer. // // Execute returns an error if applying the data object to the // Template fails or if an error occurs while writing the result to the // io.Writer. Execute(wr io.Writer, data interface{}) error // ExecuteTemplate applies the named associated template to the specified data // object and writes the output to the io.Writer. // // ExecuteTemplate returns an error if applying the data object to the // Template fails or if an error occurs while writing the result to the // io.Writer. ExecuteTemplate(wr io.Writer, name string, data interface{}) error }
Template implements a template.
type TemplateResponse ¶
type TemplateResponse struct { Template Template Name string Data interface{} FuncMap map[string]interface{} }
TemplateResponse bundles a Template with its data and names to function mappings to be passed together to the commit phase.
type URL ¶
type URL struct {
// contains filtered or unexported fields
}
URL represents a parsed URL (technically, a URI reference).
func ParseURL ¶
ParseURL parses a raw URL string into a URL structure.
The raw URl may be relative (a path, without a host) or absolute (starting with a scheme). Trying to parse a hostname and path without a scheme is invalid but may not necessarily return an error, due to parsing ambiguities.
func (URL) Hostname ¶
Hostname returns the host of the URL, stripping any valid port number if present.
If the result is enclosed in square brackets, as literal IPv6 addresses are, the square brackets are removed from the result.
func (URL) Path ¶
Path returns the path of the URL.
Note that the path is stored in decoded form: /%47%6f%2f becomes /Go/. A consequence is that it is impossible to tell which slashes in the path were slashes in the rawURL and which were %2f.
func (URL) Port ¶
Port returns the port part of the URL. If the host doesn't contain a valid port number, Port returns an empty string.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package defaults provides ready to use, safe, pre-configured instances of safehttp types.
|
Package defaults provides ready to use, safe, pre-configured instances of safehttp types. |
Package internal contains internal APIs.
|
Package internal contains internal APIs. |
plugins
|
|
collector
Package collector provides a function for creating violation report handlers.
|
Package collector provides a function for creating violation report handlers. |
coop
Package coop provides Cross-Origin-Opener-Policy protection.
|
Package coop provides Cross-Origin-Opener-Policy protection. |
cors
Package cors provides a safehttp.Interceptor that handles CORS requests.
|
Package cors provides a safehttp.Interceptor that handles CORS requests. |
csp
Package csp provides a safehttp.Interceptor which applies Content-Security Policies to responses.
|
Package csp provides a safehttp.Interceptor which applies Content-Security Policies to responses. |
csp/internalunsafecsp
Package internalunsafecsp is used internally to override CSP.
|
Package internalunsafecsp is used internally to override CSP. |
csp/internalunsafecsp/unsafecspfortests
Package unsafecspfortests can be used to disable CSP on specific handler registration in tests.
|
Package unsafecspfortests can be used to disable CSP on specific handler registration in tests. |
csp/internalunsafecsp/unsafestrictcsp
Package unsafestrictcsp can be used to disable Strict CSP protections on specific handler registration.
|
Package unsafestrictcsp can be used to disable Strict CSP protections on specific handler registration. |
csp/internalunsafecsp/unsafetrustedtypes
Package unsafetrustedtypes can be used to disable Trusted Types protections on specific handler registration.
|
Package unsafetrustedtypes can be used to disable Trusted Types protections on specific handler registration. |
fetchmetadata
Package fetchmetadata provides Fetch-Metadata based protections.
|
Package fetchmetadata provides Fetch-Metadata based protections. |
fetchmetadata/internalunsafefetchmetadata
Package internalunsafefetchmetadata is used internally to override FM policies.
|
Package internalunsafefetchmetadata is used internally to override FM policies. |
fetchmetadata/internalunsafefetchmetadata/unsafefetchmetadatafortests
Package unsafefetchmetadatafortests can be used to disable Fetch Metadata protections on specific handler registration in tests.
|
Package unsafefetchmetadatafortests can be used to disable Fetch Metadata protections on specific handler registration in tests. |
fetchmetadata/internalunsafefetchmetadata/unsaferesourcepolicy
Package unsaferesourcepolicy can be used to disable Fetch Metadata protections on specific handler registration.
|
Package unsaferesourcepolicy can be used to disable Fetch Metadata protections on specific handler registration. |
framing
Package framing provides utilities to install a comprehensive framing protection.
|
Package framing provides utilities to install a comprehensive framing protection. |
framing/internalunsafeframing
Package internalunsafeframing is used internally to override Framing protections.
|
Package internalunsafeframing is used internally to override Framing protections. |
framing/internalunsafeframing/unsafeframing
Package unsafeframing can be used to disable Framing protections on specific handler registration.
|
Package unsafeframing can be used to disable Framing protections on specific handler registration. |
framing/internalunsafeframing/unsafeframingfortests
Package unsafeframingfortests can be used to disable Framing protections on specific handler registration in tests.
|
Package unsafeframingfortests can be used to disable Framing protections on specific handler registration in tests. |
hostcheck
Package hostcheck provides a plugin that checks whether the request is intended to be sent to a given host.
|
Package hostcheck provides a plugin that checks whether the request is intended to be sent to a given host. |
hsts
Package hsts provides HTTP Strict Transport Security.
|
Package hsts provides HTTP Strict Transport Security. |
htmlinject
Package htmlinject provides utilities to pre-process HTML templates and inject additional parts into them before parsing.
|
Package htmlinject provides utilities to pre-process HTML templates and inject additional parts into them before parsing. |
reportingapi
Package reportingapi is an implementation of the Report-To header described in https://www.w3.org/TR/reporting/#header.
|
Package reportingapi is an implementation of the Report-To header described in https://www.w3.org/TR/reporting/#header. |
staticheaders
Package staticheaders provides a safehttp.Interceptor which sets security sensitive headers on every response.
|
Package staticheaders provides a safehttp.Interceptor which sets security sensitive headers on every response. |
xsrf
Package xsrf contains helper functions for the safehttp.Interceptor that provide protection against Cross-Site Request Forgery attacks.
|
Package xsrf contains helper functions for the safehttp.Interceptor that provide protection against Cross-Site Request Forgery attacks. |
xsrf/xsrfangular
Package xsrfangular provides a safehttp.Interceptor that ensures Cross-Site Request Forgery protection for Angular applications by verifying the incoming requests, rejecting those requests that are suspected to be part of an attack.
|
Package xsrfangular provides a safehttp.Interceptor that ensures Cross-Site Request Forgery protection for Angular applications by verifying the incoming requests, rejecting those requests that are suspected to be part of an attack. |
xsrf/xsrfhtml
Package xsrfhtml provides a safehttp.Interceptor that ensures Cross-Site Request Forgery by verifying the incoming requests for the presence of an XSRF token, rejecting those requests that are suspected to be part of an attack.
|
Package xsrfhtml provides a safehttp.Interceptor that ensures Cross-Site Request Forgery by verifying the incoming requests for the presence of an XSRF token, rejecting those requests that are suspected to be part of an attack. |
Package restricted contains restricted APIs.
|
Package restricted contains restricted APIs. |
Package safehttptest provides utilities for testing safehttp.Handler:s and safehttp.Interceptor:s.
|
Package safehttptest provides utilities for testing safehttp.Handler:s and safehttp.Interceptor:s. |