tsweb
packageThis package is not in the latest version of its module.
Details
Validgo.mod file
The Go module system was introduced in Go 1.11 and is the official dependency management solution for Go.
Redistributable license
Redistributable licenses place minimal restrictions on how software can be used, modified, and redistributed.
Tagged version
Modules with tagged versions give importers more predictable builds.
Stable version
When a project reaches major version v1 it is considered stable.
- Learn more about best practices
Repository
Links
Documentation¶
Overview¶
Package tsweb contains code used in various Tailscale webservers.
Index¶
- Constants
- Variables
- func AcceptsEncoding(r *http.Request, enc string) bool
- func AddBrowserHeaders(w http.ResponseWriter)
- func AllowDebugAccess(r *http.Request) bool
- func BrowserHeaderHandler(h http.Handler) http.Handler
- func BrowserHeaderHandlerFunc(h http.HandlerFunc) http.HandlerFunc
- func CleanRedirectURL(urlStr string, allowedHosts []string) (*url.URL, error)
- func DefaultCertDir(leafDir string) string
- func ErrorHandler(h ReturnHandler, opts ErrorOptions) http.Handler
- func IsProd443(addr string) bool
- func LogHandler(h http.Handler, opts LogOptions) http.Handler
- func NormalizedPath(p string) string
- func Protected(h http.Handler) http.Handler
- func SetRequestID(h http.Handler) http.Handler
- func StdHandler(h ReturnHandler, opts HandlerOptions) http.Handler
- func VarzHandler(w http.ResponseWriter, r *http.Request)
- func WriteHTTPError(w http.ResponseWriter, r *http.Request, e HTTPError)
- type AccessLogRecord
- type BucketedStatsOptions
- type DebugHandler
- func (d *DebugHandler) Handle(slug, desc string, handler http.Handler)
- func (d *DebugHandler) HandleFunc(slug, desc string, handler http.HandlerFunc)
- func (d *DebugHandler) HandleSilent(slug string, handler http.Handler)
- func (d *DebugHandler) HandleSilentFunc(slug string, handler http.HandlerFunc)
- func (d *DebugHandler) KV(k string, v any)
- func (d *DebugHandler) KVFunc(k string, v func() any)
- func (d *DebugHandler) Section(f func(w io.Writer, r *http.Request))
- func (d *DebugHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (d *DebugHandler) Title(title string)
- func (d *DebugHandler) URL(url, desc string)
- type ErrorHandlerFunc
- type ErrorOptions
- type HTTPError
- type HandlerOptions
- type LogOptions
- type Middleware
- type OnCompletionFunc
- type OnStartFunc
- type Port80Handler
- type RequestID
- type ReturnHandler
- type ReturnHandlerFunc
Examples¶
Constants¶
const RequestIDHeader = "X-Tailscale-Request-Id"RequestIDHeader is a custom HTTP header that the WithRequestID middlewareuses to determine whether to re-use a given request ID from the clientor generate a new one.
Variables¶
var DevModeboolDevMode controls whether extra output in shown, for when the binary is being run in dev mode.
var PrometheusHandlerfeature.Hook[func(*DebugHandler)]PrometheusHandler is an optional hook to enable native Prometheussupport in the debug handler. It is disabled by default. Import thetailscale.com/tsweb/promvarz package to enable this feature.
var RequestIDKeyctxkey.Key[RequestID]RequestIDKey stores and loadsRequestID values within acontext.Context.
Functions¶
funcAcceptsEncoding¶added inv1.22.0
AcceptsEncoding reports whether r accepts the named encoding("gzip", "br", etc).
funcAddBrowserHeaders¶added inv1.46.0
func AddBrowserHeaders(whttp.ResponseWriter)
AddBrowserHeaders sets various HTTP security headers for browser-facing endpoints.
The specific headers:
- require HTTPS access (HSTS)
- disallow iframe embedding
- mitigate MIME confusion attacks
These headers are based onhttps://infosec.mozilla.org/guidelines/web_security
funcAllowDebugAccess¶
AllowDebugAccess reports whether r should be permitted to accessvarious debug endpoints.
funcBrowserHeaderHandler¶added inv1.46.0
BrowserHeaderHandler wraps the provided http.Handler with a call toAddBrowserHeaders.
funcBrowserHeaderHandlerFunc¶added inv1.46.0
func BrowserHeaderHandlerFunc(hhttp.HandlerFunc)http.HandlerFunc
BrowserHeaderHandlerFunc wraps the provided http.HandlerFunc with a call toAddBrowserHeaders.
funcCleanRedirectURL¶added inv1.60.0
CleanRedirectURL ensures that urlStr is a valid redirect URL to thecurrent server, or one of allowedHosts. Returns the cleaned URL ora validation error.
funcDefaultCertDir¶
funcErrorHandler¶added inv1.70.0
func ErrorHandler(hReturnHandler, optsErrorOptions)http.Handler
ErrorHandler converts aReturnHandler into a standardhttp.Handler.Errors are handled as specified by the [ReturnHandler.ServeHTTPReturn] method.When wrapped in aLogHandler, panics are added to theAccessLogRecord;otherwise, panics continue up the stack.
funcLogHandler¶added inv1.70.0
func LogHandler(hhttp.Handler, optsLogOptions)http.Handler
LogHandler returns an http.Handler that logs to opts.Logf.It logs both successful and failing requests.The log line includes the first error returned toErrorHandler within.The outer-most LogHandler(LogHandler(...)) does all of the logging.Inner LogHandler instance do nothing.Panics are swallowed and their stack traces are put in the error.
funcNormalizedPath¶added inv1.60.0
NormalizedPath returns the given path with the following modifications:
- any query parameters are removed
- any path component with a hex string of 9 or more characters isreplaced by an ellipsis
- any path component containing a period with at least two charactersafter the period (i.e. an email or domain)
- any path component consisting of a common Tailscale Stable ID
- any path segment *@passkey.
funcProtected¶
Protected wraps a provided debug handler, h, returning a Handlerthat enforces AllowDebugAccess and returns forbidden replies forunauthorized requests.
funcSetRequestID¶added inv1.56.0
SetRequestID is an HTTP middleware that injects a RequestID in the*http.Request Context. The value of that request id is either retrieved fromthe RequestIDHeader or a randomly generated one if not exists. Innerhandlers can retrieve this ID from the RequestIDFromContext function.
funcStdHandler¶added inv0.98.0
func StdHandler(hReturnHandler, optsHandlerOptions)http.Handler
StdHandler converts a ReturnHandler into a standard http.Handler.Handled requests are logged using opts.Logf, as are any errors.Errors are handled as specified by the ReturnHandler interface.Short-hand for LogHandler(ErrorHandler()).
funcVarzHandler¶added inv1.4.0
func VarzHandler(whttp.ResponseWriter, r *http.Request)
VarzHandler writes expvar values as Prometheus metrics.TODO: migrate all users to varz.Handler or promvarz.Handler and remove this.
funcWriteHTTPError¶added inv1.72.0
func WriteHTTPError(whttp.ResponseWriter, r *http.Request, eHTTPError)
WriteHTTPError is the default error response formatter.
Types¶
typeAccessLogRecord¶added inv0.98.0
type AccessLogRecord struct {// Timestamp at which request processing started.Timetime.Time `json:"time"`// Time it took to finish processing the request. It does not// include the entire lifetime of the underlying connection in// cases like connection hijacking, only the lifetime of the HTTP// request handler.Secondsfloat64 `json:"duration,omitempty"`// The client's ip:port.RemoteAddrstring `json:"remote_addr,omitempty"`// The HTTP protocol version, usually "HTTP/1.1 or HTTP/2".Protostring `json:"proto,omitempty"`// Whether the request was received over TLS.TLSbool `json:"tls,omitempty"`// The target hostname in the request.Hoststring `json:"host,omitempty"`// The HTTP method invoked.Methodstring `json:"method,omitempty"`// The unescaped request URI, including query parameters.RequestURIstring `json:"request_uri,omitempty"`// The client's user-agentUserAgentstring `json:"user_agent,omitempty"`// Where the client was before making this request.Refererstring `json:"referer,omitempty"`// The HTTP response code sent to the client.Codeint `json:"code,omitempty"`// Number of bytes sent in response body to client. If the request// was hijacked, only includes bytes sent up to the point of// hijacking.Bytesint `json:"bytes,omitempty"`// Error encountered during request processing.Errstring `json:"err,omitempty"`// RequestID is a unique ID for this request. If the *http.Request context// carries this value via SetRequestID, then it will be displayed to the// client immediately after the error text, as well as logged here. This// makes it easier to correlate support requests with server logs. If a// RequestID generator is not configured, RequestID will be empty.RequestIDRequestID `json:"request_id,omitempty"`}AccessLogRecord is a record of one HTTP request served.
func (AccessLogRecord)String¶added inv0.98.0
func (mAccessLogRecord) String()string
String returns m as a JSON string.
typeBucketedStatsOptions¶added inv1.60.0
type BucketedStatsOptions struct {// Bucket returns which bucket the given request is in.// If nil, [NormalizedPath] is used to compute the bucket.Bucket func(req *http.Request)string// If non-nil, Started maintains a counter of all requests which// have begun processing.Started *metrics.LabelMap// If non-nil, Finished maintains a counter of all requests which// have finished processing with success (that is, the HTTP handler has// returned).Finished *metrics.LabelMap}BucketedStatsOptions describes tsweb handler options surroundingthe generation of metrics, grouped into buckets.
typeDebugHandler¶added inv1.10.0
type DebugHandler struct {// contains filtered or unexported fields}DebugHandler is an http.Handler that serves a debugging "homepage",and provides helpers to register more debug endpoints and reports.
The rendered page consists of three sections: informationalkey/value pairs, links to other pages, and additionalprogram-specific HTML. Callers can add to these sections using theKV, URL and Section helpers respectively.
Additionally, the Handle method offers a shorthand for correctlyregistering debug handlers and cross-linking them from /debug/.
funcDebugger¶added inv1.10.0
func Debugger(mux *http.ServeMux) *DebugHandler
Debugger returns the DebugHandler registered on mux at /debug/,creating it if necessary.
func (*DebugHandler)Handle¶added inv1.10.0
func (d *DebugHandler) Handle(slug, descstring, handlerhttp.Handler)
Handle registers handler at /debug/<slug> and adds a link to iton /debug/ with the provided description.
Example¶
mux := http.NewServeMux()dbg := Debugger(mux)// Registers /debug/flushcache with the given handler, and adds a// link to /debug/ with the description "Flush caches".dbg.Handle("flushcache", "Flush caches", http.HandlerFunc(http.NotFound))func (*DebugHandler)HandleFunc¶added inv1.82.0
func (d *DebugHandler) HandleFunc(slug, descstring, handlerhttp.HandlerFunc)
Handle registers handler at /debug/<slug> and adds a link to iton /debug/ with the provided description.
func (*DebugHandler)HandleSilent¶added inv1.50.0
func (d *DebugHandler) HandleSilent(slugstring, handlerhttp.Handler)
HandleSilent registers handler at /debug/<slug>. It does not adda descriptive entry in /debug/ for it. This should be usedsparingly, for things that need to be registered but would pollutethe list of debug links.
func (*DebugHandler)HandleSilentFunc¶added inv1.82.0
func (d *DebugHandler) HandleSilentFunc(slugstring, handlerhttp.HandlerFunc)
HandleSilent registers handler at /debug/<slug>. It does not adda descriptive entry in /debug/ for it. This should be usedsparingly, for things that need to be registered but would pollutethe list of debug links.
func (*DebugHandler)KV¶added inv1.10.0
func (d *DebugHandler) KV(kstring, vany)
KV adds a key/value list item to /debug/.
Example¶
mux := http.NewServeMux()dbg := Debugger(mux)// Adds two list items to /debug/, showing that the condition is// red and there are 42 donuts.dbg.KV("Condition", "red")dbg.KV("Donuts", 42)func (*DebugHandler)KVFunc¶added inv1.10.0
func (d *DebugHandler) KVFunc(kstring, v func()any)
KVFunc adds a key/value list item to /debug/. v is called on everyrender of /debug/.
Example¶
mux := http.NewServeMux()dbg := Debugger(mux)// Adds an count of page renders to /debug/. Note this example// isn't concurrency-safe.views := 0dbg.KVFunc("Debug pageviews", func() any {views = views + 1return views})dbg.KV("Donuts", 42)func (*DebugHandler)Section¶added inv1.10.0
func (d *DebugHandler) Section(f func(wio.Writer, r *http.Request))
Section invokes f on every render of /debug/ to add supplementalHTML to the page body.
Example¶
mux := http.NewServeMux()dbg := Debugger(mux)// Adds a section to /debug/ that dumps the HTTP request of the// visitor.dbg.Section(func(w io.Writer, r *http.Request) {io.WriteString(w, "<h3>Dump of your HTTP request</h3>")fmt.Fprintf(w, "<code>%#v</code>", r)})func (*DebugHandler)ServeHTTP¶added inv1.10.0
func (d *DebugHandler) ServeHTTP(whttp.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler.
func (*DebugHandler)Title¶added inv1.82.0
func (d *DebugHandler) Title(titlestring)
Title sets the title at the top of the debug page.
func (*DebugHandler)URL¶added inv1.10.0
func (d *DebugHandler) URL(url, descstring)
URL adds a URL and description list item to /debug/.
Example¶
mux := http.NewServeMux()dbg := Debugger(mux)// Links to the Tailscale website from /debug/.dbg.URL("https://www.tailscale.com", "Homepage")typeErrorHandlerFunc¶added inv1.28.0
type ErrorHandlerFunc func(http.ResponseWriter, *http.Request,HTTPError)
ErrorHandlerFunc is called to present a error response.
typeErrorOptions¶added inv1.70.0
type ErrorOptions struct {// Logf is used to record unexpected behaviours when returning HTTPError but// different error codes have already been written to the client.Logflogger.Logf// OnError is called if the handler returned a HTTPError. This// is intended to be used to present pretty error pages if// the user agent is determined to be a browser.OnErrorErrorHandlerFunc}ErrorOptions are options used byErrorHandler.
typeHTTPError¶added inv0.98.0
type HTTPError struct {Codeint// HTTP response code to send to client; 0 means 500Msgstring// Response body to send to clientErrerror// Detailed error to log on the serverHeaderhttp.Header// Optional set of HTTP headers to set in the response}HTTPError is an error with embedded HTTP response information.
It is the error type to be (optionally) used by Handler.ServeHTTPReturn.
typeHandlerOptions¶added inv1.2.1
type HandlerOptions struct {QuietLoggingIfSuccessfulbool// if set, do not log successfully handled HTTP requests (200 and 304 status codes)Logflogger.LogfNow func()time.Time// if nil, defaults to time.Now// If non-nil, StatusCodeCounters maintains counters// of status codes for handled responses.// The keys are "1xx", "2xx", "3xx", "4xx", and "5xx".StatusCodeCounters *expvar.Map// If non-nil, StatusCodeCountersFull maintains counters of status// codes for handled responses.// The keys are HTTP numeric response codes e.g. 200, 404, ...StatusCodeCountersFull *expvar.Map// If non-nil, BucketedStats computes and exposes statistics// for each bucket based on the contained parameters.BucketedStats *BucketedStatsOptions// OnStart is called inline before ServeHTTP is called. Optional.OnStartOnStartFunc// OnError is called if the handler returned a HTTPError. This// is intended to be used to present pretty error pages if// the user agent is determined to be a browser.OnErrorErrorHandlerFunc// OnCompletion is called inline when ServeHTTP is finished and gets// useful data that the implementor can use for metrics. Optional.OnCompletionOnCompletionFunc}HandlerOptions are options used byStdHandler, containing bothLogOptionsused byLogHandler andErrorOptions used byErrorHandler.
typeLogOptions¶added inv1.70.0
type LogOptions struct {// Logf is used to log HTTP requests and responses.Logflogger.Logf// Now is a function giving the current time. Defaults to [time.Now].Now func()time.Time// QuietLogging suppresses all logging of handled HTTP requests, even if// there are errors or status codes considered unsuccessful. Use this option// to add your own logging in OnCompletion.QuietLoggingbool// QuietLoggingIfSuccessful suppresses logging of handled HTTP requests// where the request's response status code is 200 or 304.QuietLoggingIfSuccessfulbool// StatusCodeCounters maintains counters of status code classes.// The keys are "1xx", "2xx", "3xx", "4xx", and "5xx".// If nil, no counting is done.StatusCodeCounters *expvar.Map// StatusCodeCountersFull maintains counters of status codes.// The keys are HTTP numeric response codes e.g. 200, 404, ...// If nil, no counting is done.StatusCodeCountersFull *expvar.Map// BucketedStats computes and exposes statistics for each bucket based on// the contained parameters. If nil, no counting is done.BucketedStats *BucketedStatsOptions// OnStart is called inline before ServeHTTP is called. Optional.OnStartOnStartFunc// OnCompletion is called inline when ServeHTTP is finished and gets// useful data that the implementor can use for metrics. Optional.OnCompletionOnCompletionFunc}LogOptions are the options used byLogHandler.These options are a subset ofHandlerOptions.
typeMiddleware¶added inv1.56.0
A Middleware is a function that wraps an http.Handler to extend or modifyits behaviour.
The implementation of the wrapper is responsible for delegating its inputrequest to the underlying handler, if appropriate.
funcMiddlewareStack¶added inv1.72.0
func MiddlewareStack(mw ...Middleware)Middleware
MiddlewareStack combines multiple middleware into a single middleware fordecorating ahttp.Handler. The first middleware argument will be the firstto process an incoming request, before passing the request onto subsequentmiddleware and eventually the wrapped handler.
For example:
MiddlewareStack(A, B)(h).ServeHTTP(w, r)
calls in sequence:
a.ServeHTTP(w, r)-> b.ServeHTTP(w, r)-> h.ServeHTTP(w, r)
(where the lowercase handlers were generated by the uppercase middleware).
Example¶
// setHeader returns a middleware that sets header k = vs.setHeader := func(k string, vs ...string) Middleware {k = textproto.CanonicalMIMEHeaderKey(k)return func(h http.Handler) http.Handler {return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {w.Header()[k] = vsh.ServeHTTP(w, r)})}}// h is a http.Handler which prints the A, B & C response headers, wrapped// in a few middleware which set those headers.var h http.Handler = MiddlewareStack(setHeader("A", "mw1"),MiddlewareStack(setHeader("A", "mw2.1"),setHeader("B", "mw2.2"),setHeader("C", "mw2.3"),setHeader("C", "mw2.4"),),setHeader("B", "mw3"),)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {fmt.Println("A", w.Header().Get("A"))fmt.Println("B", w.Header().Get("B"))fmt.Println("C", w.Header().Get("C"))}))// Invoke the handler.h.ServeHTTP(httptest.NewRecorder(), httptest.NewRequest("", "/", nil))Output:A mw2.1B mw3C mw2.4
typeOnCompletionFunc¶added inv1.68.0
type OnCompletionFunc func(*http.Request,AccessLogRecord)
OnCompletionFunc is called when ServeHTTP is finished and getsuseful data that the implementor can use for metrics.
typeOnStartFunc¶added inv1.70.0
type OnStartFunc func(*http.Request,AccessLogRecord)
OnStartFunc is called before ServeHTTP is called.
typePort80Handler¶
type Port80Handler struct {Mainhttp.Handler// FQDN is used to redirect incoming requests to https://<FQDN>.// If it is not set, the hostname is calculated from the incoming// request.FQDNstring}Port80Handler is the handler to be given toautocert.Manager.HTTPHandler. The inner handler is the muxreturned by NewMux containing registered /debug handlers.
func (Port80Handler)ServeHTTP¶
func (hPort80Handler) ServeHTTP(whttp.ResponseWriter, r *http.Request)
typeRequestID¶added inv1.50.0
type RequestIDstring
RequestID is an opaque identifier for a HTTP request, used to correlateuser-visible errors with backend server logs. The RequestID is typicallythreaded through an HTTP Middleware (WithRequestID) and then can be extractedby HTTP Handlers to include in their logs.
RequestID is an opaque identifier for a HTTP request, used to correlateuser-visible errors with backend server logs. If present in the context, theRequestID will be printed alongside the message text and logged in theAccessLogRecord.
A RequestID has the format "REQ-1{ID}", and the ID should be treated as anopaque string. The current implementation uses a UUID.
funcGenerateRequestID¶added inv1.62.0
func GenerateRequestID()RequestID
GenerateRequestID generates a new request ID with the current format.
funcRequestIDFromContextdeprecatedadded inv1.56.0
func (RequestID)String¶added inv1.62.0
String returns the string format of the request ID, for use in e.g. settingahttp.Header.
typeReturnHandler¶added inv0.98.0
type ReturnHandler interface {// ServeHTTPReturn is like http.Handler.ServeHTTP, except that// it can choose to return an error instead of writing to its// http.ResponseWriter.//// If ServeHTTPReturn returns an error, it caller should handle// an error by serving an HTTP 500 response to the user. The// error details should not be sent to the client, as they may// contain sensitive information. If the error is an// HTTPError, though, callers should use the HTTP response// code and message as the response to the client.ServeHTTPReturn(http.ResponseWriter, *http.Request)error}ReturnHandler is like net/http.Handler, but the handler can return anerror instead of writing to its ResponseWriter.
typeReturnHandlerFunc¶added inv0.98.1
type ReturnHandlerFunc func(http.ResponseWriter, *http.Request)error
ReturnHandlerFunc is an adapter to allow the use of ordinaryfunctions as ReturnHandlers. If f is a function with theappropriate signature, ReturnHandlerFunc(f) is a ReturnHandler thatcalls f.
func (ReturnHandlerFunc)ServeHTTPReturn¶added inv0.98.1
func (fReturnHandlerFunc) ServeHTTPReturn(whttp.ResponseWriter, r *http.Request)error
ServeHTTPReturn calls f(w, r).
Directories¶
| Path | Synopsis |
|---|---|
Package promvarz combines Prometheus metrics exported by our expvar converter (tsweb/varz) with metrics exported by the official Prometheus client. | Package promvarz combines Prometheus metrics exported by our expvar converter (tsweb/varz) with metrics exported by the official Prometheus client. |
Package varz contains code to export metrics in Prometheus format. | Package varz contains code to export metrics in Prometheus format. |