fsthttp

package
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Jan 30, 2023 License: Apache-2.0, BSD-3-Clause Imports: 14 Imported by: 14

Documentation

Overview

Package fsthttp provides HTTP functionality for Fastly's Compute@Edge environment.

A Compute@Edge program can be thought of as an HTTP request handler. Each execution is triggered by an incoming request from a client, and is expected to respond to that request before terminating. The Serve function provides a Handler-style interface to that Request and its ResponseWriter.

The types in this package are similar to, but not the same as, corresponding types in the standard library's package net/http. Refer to the documentation for important caveats about usage.

Index

Constants

View Source
const (
	MethodGet     = "GET"
	MethodHead    = "HEAD"
	MethodPost    = "POST"
	MethodPut     = "PUT"
	MethodPatch   = "PATCH" // RFC 5789
	MethodDelete  = "DELETE"
	MethodConnect = "CONNECT"
	MethodOptions = "OPTIONS"
	MethodTrace   = "TRACE"
)

Common HTTP methods.

Unless otherwise noted, these are defined in RFC 7231 section 4.3.

View Source
const (
	StatusContinue           = 100 // RFC 7231, 6.2.1
	StatusSwitchingProtocols = 101 // RFC 7231, 6.2.2
	StatusProcessing         = 102 // RFC 2518, 10.1
	StatusEarlyHints         = 103 // RFC 8297

	StatusOK                   = 200 // RFC 7231, 6.3.1
	StatusCreated              = 201 // RFC 7231, 6.3.2
	StatusAccepted             = 202 // RFC 7231, 6.3.3
	StatusNonAuthoritativeInfo = 203 // RFC 7231, 6.3.4
	StatusNoContent            = 204 // RFC 7231, 6.3.5
	StatusResetContent         = 205 // RFC 7231, 6.3.6
	StatusPartialContent       = 206 // RFC 7233, 4.1
	StatusMultiStatus          = 207 // RFC 4918, 11.1
	StatusAlreadyReported      = 208 // RFC 5842, 7.1
	StatusIMUsed               = 226 // RFC 3229, 10.4.1

	StatusMultipleChoices  = 300 // RFC 7231, 6.4.1
	StatusMovedPermanently = 301 // RFC 7231, 6.4.2
	StatusFound            = 302 // RFC 7231, 6.4.3
	StatusSeeOther         = 303 // RFC 7231, 6.4.4
	StatusNotModified      = 304 // RFC 7232, 4.1
	StatusUseProxy         = 305 // RFC 7231, 6.4.5

	StatusTemporaryRedirect = 307 // RFC 7231, 6.4.7
	StatusPermanentRedirect = 308 // RFC 7538, 3

	StatusBadRequest                   = 400 // RFC 7231, 6.5.1
	StatusUnauthorized                 = 401 // RFC 7235, 3.1
	StatusPaymentRequired              = 402 // RFC 7231, 6.5.2
	StatusForbidden                    = 403 // RFC 7231, 6.5.3
	StatusNotFound                     = 404 // RFC 7231, 6.5.4
	StatusMethodNotAllowed             = 405 // RFC 7231, 6.5.5
	StatusNotAcceptable                = 406 // RFC 7231, 6.5.6
	StatusProxyAuthRequired            = 407 // RFC 7235, 3.2
	StatusRequestTimeout               = 408 // RFC 7231, 6.5.7
	StatusConflict                     = 409 // RFC 7231, 6.5.8
	StatusGone                         = 410 // RFC 7231, 6.5.9
	StatusLengthRequired               = 411 // RFC 7231, 6.5.10
	StatusPreconditionFailed           = 412 // RFC 7232, 4.2
	StatusRequestEntityTooLarge        = 413 // RFC 7231, 6.5.11
	StatusRequestURITooLong            = 414 // RFC 7231, 6.5.12
	StatusUnsupportedMediaType         = 415 // RFC 7231, 6.5.13
	StatusRequestedRangeNotSatisfiable = 416 // RFC 7233, 4.4
	StatusExpectationFailed            = 417 // RFC 7231, 6.5.14
	StatusTeapot                       = 418 // RFC 7168, 2.3.3
	StatusMisdirectedRequest           = 421 // RFC 7540, 9.1.2
	StatusUnprocessableEntity          = 422 // RFC 4918, 11.2
	StatusLocked                       = 423 // RFC 4918, 11.3
	StatusFailedDependency             = 424 // RFC 4918, 11.4
	StatusTooEarly                     = 425 // RFC 8470, 5.2.
	StatusUpgradeRequired              = 426 // RFC 7231, 6.5.15
	StatusPreconditionRequired         = 428 // RFC 6585, 3
	StatusTooManyRequests              = 429 // RFC 6585, 4
	StatusRequestHeaderFieldsTooLarge  = 431 // RFC 6585, 5
	StatusUnavailableForLegalReasons   = 451 // RFC 7725, 3

	StatusInternalServerError           = 500 // RFC 7231, 6.6.1
	StatusNotImplemented                = 501 // RFC 7231, 6.6.2
	StatusBadGateway                    = 502 // RFC 7231, 6.6.3
	StatusServiceUnavailable            = 503 // RFC 7231, 6.6.4
	StatusGatewayTimeout                = 504 // RFC 7231, 6.6.5
	StatusHTTPVersionNotSupported       = 505 // RFC 7231, 6.6.6
	StatusVariantAlsoNegotiates         = 506 // RFC 2295, 8.1
	StatusInsufficientStorage           = 507 // RFC 4918, 11.5
	StatusLoopDetected                  = 508 // RFC 5842, 7.2
	StatusNotExtended                   = 510 // RFC 2774, 7
	StatusNetworkAuthenticationRequired = 511 // RFC 6585, 6
)

HTTP status codes as registered with IANA. See: https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml

View Source
const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"

TimeFormat is the time format to use when generating times in HTTP headers. It is like time.RFC1123 but hard-codes GMT as the time zone. The time being formatted must be in UTC for Format to generate the correct format.

For parsing this time format, see ParseTime.

Variables

View Source
var ErrNoCookie = errors.New("fsthttp: named cookie not present")

ErrNoCookie is returned by Request's Cookie method when a cookie is not found.

View Source
var Limits = limits{}

Limits handles HTTP limits

Functions

func CanonicalHeaderKey

func CanonicalHeaderKey(s string) string

CanonicalHeaderKey returns the canonical format of the header key s. The canonicalization converts the first letter and any letter following a hyphen to upper case; the rest are converted to lowercase. For example, the canonical key for "accept-encoding" is "Accept-Encoding". If s contains a space or invalid header field bytes, it is returned without modifications.

func Error added in v0.1.2

func Error(w ResponseWriter, error string, code int)

Error replies to the request with the specified error message and HTTP code. It does not otherwise end the request; the caller should ensure no further writes are done to w. The error message should be plain text.

func NotFound added in v0.1.2

func NotFound(w ResponseWriter, r *Request)

NotFound replies to the request with an HTTP 404 not found error.

func Serve

func Serve(h Handler)

Serve calls h, providing it with a context that will be canceled when Serve returns, a Request representing the incoming client request that initiated this execution, and a ResponseWriter that can be used to respond to that request. Serve will ensure the ResponseWriter has been closed before returning, and so should only be called once per execution.

func ServeFunc

func ServeFunc(f HandlerFunc)

ServeFunc is sugar for Serve(HandlerFunc(f)).

func SetCookie

func SetCookie(h Header, cookie *Cookie)

SetCookie adds a Set-Cookie header to the provided ResponseWriter's headers. The provided cookie must have a valid Name. Invalid cookies may be silently dropped.

func StatusText

func StatusText(code int) string

StatusText returns a text for the HTTP status code. It returns the empty string if the code is unknown.

Types

type CacheOptions

type CacheOptions struct {
	// Pass controls whether or not the request should be cached at all. By
	// default pass is false, which means the request will only reach the
	// backend if a cached response is not available. If pass is set to true,
	// the request will always be sent directly to the backend.
	//
	// Pass is mutually exclusive with all other cache options. Setting any
	// other option will force pass to false.
	Pass bool

	// PCI controls the PCI/HIPAA compliant, non-volatile caching of the
	// request. PCI is false by default, which means the request may not be
	// PCI/HIPAA compliant. If PCI is set to true, caching will be made
	// compliant, and pass will be forced to false.
	//
	// https://docs.fastly.com/products/pci-compliant-caching-and-delivery
	PCI bool

	// TTL represents a Time-to-Live for cached responses to the request, in
	// seconds. If greater than zero, it overrides any behavior specified in the
	// response headers, and forces pass to false.
	TTL uint32

	// StaleWhileRevalidate represents a stale-while-revalidate time for the
	// request, in seconds. If greater than zero, it overrides any behavior
	// specified in the response headers, and forces pass to false.
	StaleWhileRevalidate uint32

	// SurrogateKey represents an explicit surrogate key for the request, which
	// will be added to any `Surrogate-Key` response headers received from the
	// backend. If nonempty, it forces pass to false.
	//
	// https://docs.fastly.com/en/guides/purging-api-cache-with-surrogate-keys
	SurrogateKey string
}

CacheOptions control caching behavior for outgoing requests.

type Cookie struct {
	Name  string
	Value string

	Path       string    // optional
	Domain     string    // optional
	Expires    time.Time // optional
	RawExpires string    // for reading cookies only

	// 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
	MaxAge int
	Secure bool
	//revive:disable:var-naming
	HttpOnly bool
	//revive:enable:var-naming
	SameSite SameSite
	Raw      string
	Unparsed []string // Raw text of unparsed attribute-value pairs
}

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 (*Cookie) String

func (c *Cookie) String() string

String returns the serialization of the cookie for use in a Cookie header (if only Name and Value are set) or a Set-Cookie response header (if other fields are set). If c is nil or c.Name is invalid, the empty string is returned.

func (*Cookie) Valid

func (c *Cookie) Valid() error

Valid reports whether the cookie is valid.

type DecompressResponseOptions

type DecompressResponseOptions struct {
	// Gzip controls whether a gzip-encoded response to the request will be
	// automatically decompressed.
	//
	// If the response to the request is gzip-encoded, it will be presented in
	// decompressed form, and the Content-Encoding and Content-Length headers
	// will be removed.
	Gzip bool
}

DecompressResponseOptions control the auto decompress response behaviour.

type Handler

type Handler interface {
	ServeHTTP(ctx context.Context, w ResponseWriter, r *Request)
}

Handler describes anything which can handle, or respond to, an HTTP request. It has the same semantics as net/http.Handler, but operates on the Request and ResponseWriter types defined in this package.

func Adapt added in v0.1.2

func Adapt(h http.Handler) Handler

Adapt allows an http.Handler to be used as an fsthttp.Handler.

Because the Request and ResponseWriter types are not exactly the same as ones in net/http, helper accessor functions exist to extract the fsthttp values from the request context.

type HandlerFunc

type HandlerFunc func(ctx context.Context, w ResponseWriter, r *Request)

HandlerFunc adapts a function to a Handler.

func (HandlerFunc) ServeHTTP

func (f HandlerFunc) ServeHTTP(ctx context.Context, w ResponseWriter, r *Request)

ServeHTTP implements Handler by calling f(ctx, w, r).

type Header map[string][]string

Header represents the key-value pairs in a set of HTTP headers. Unlike net/http, keys are canonicalized to their lowercase form.

func NewHeader

func NewHeader() Header

NewHeader returns an initialized and empty set of headers.

func (Header) Add

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

Add adds the key, value pair to the headers. It appends to any existing values associated with key. The key is case insensitive; it is canonicalized by CanonicalHeaderKey.

func (Header) Apply

func (h Header) Apply(hs Header)

Apply adds all of the headers in hs. In the case of key conflict, values from hs totally overwrite existing values in h.

func (Header) Clone

func (h Header) Clone() Header

Clone returns a copy of the headers.

func (Header) Del

func (h Header) Del(key string)

Del deletes the values associated with key. The key is case insensitive; it is canonicalized by CanonicalHeaderKey.

func (Header) Get

func (h Header) Get(key string) string

Get gets the first value associated with the given key. It is case insensitive; CanonicalHeaderKey is used to canonicalize the provided key. If there are no values associated with the key, Get returns "".

func (Header) Keys

func (h Header) Keys() []string

Keys returns all keys in the header collection.

func (Header) Reset

func (h Header) Reset(hs Header)

Reset deletes all existing headers, and adds all of the headers in hs.

func (Header) Set

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

Set sets the header entries associated with key to the single element value. It replaces any existing values associated with key. The key is case insensitive; it is canonicalized by CanonicalHeaderKey.

func (Header) Values

func (h Header) Values(key string) []string

Values returns all values associated with the given key. It is case insensitive; CanonicalHeaderKey is used to canonicalize the provided key. The returned slice is not a copy.

type Request

type Request struct {
	// Method specifies the HTTP method: GET, POST, PUT, HEAD, etc.
	Method string

	// URL is the parsed and validated URL of the request.
	//
	// Outgoing requests are always sent to the preconfigured backend provided
	// to the send method. The URL is used for the request resource, Host
	// header, etc.
	URL *url.URL

	// Proto contains the HTTP protocol version used for incoming requests.
	//
	// These fields are ignored for outgoing requests.
	Proto      string // "HTTP/1.0"
	ProtoMajor int    // 1
	ProtoMinor int    // 0

	// Header contains the request header fields either received in the
	// incoming request, or to be sent with the outgoing request.
	Header Header

	// CacheOptions control caching behavior for outgoing requests.
	CacheOptions CacheOptions

	// Body is the request's body.
	//
	// For the incoming client request, the body will always be non-nil, but
	// reads may return immediately with EOF. For outgoing requests, the body is
	// optional. A body may only be read once.
	//
	// It is possible to assign the unread body of the incoming client request
	// to the body field of a different request. When that second request is
	// sent, the body will be efficiently streamed from the incoming request.
	//
	// It is also possible to assign the unread body of a received response to
	// the body field of a request, with the same results.
	Body io.ReadCloser

	// Host is the hostname parsed from the incoming request URL.
	Host string

	// RemoteAddr contains the IP address of the requesting client.
	//
	// This field is ignored for outgoing requests.
	RemoteAddr string

	// TLSInfo collects TLS metadata for incoming requests received over HTTPS.
	TLSInfo TLSInfo

	// SendPollInterval determines how often the Send method will check for
	// completed requests. While polling, the Go runtime is suspended, and all
	// user code stops execution. A shorter interval will make Send more
	// responsive, but provide less CPU time to user code. A longer poll
	// interval will make Send less responsive, but provide more CPU time to
	// user code.
	//
	// If SendPollInterval is zero, a default value of 1ms is used. The minimum
	// value is 1ms, and the maximum value is 1s.
	SendPollInterval time.Duration

	// DecompressResponseOptions control the auto decompress response behaviour.
	DecompressResponseOptions DecompressResponseOptions

	// ManualFramingMode controls how the framing headers
	// (Content-Length/Transfer-Encoding) are set for a request.
	//
	// If ManualFramingMode is true, the request uses the exact framing headers
	// set in the message.  If ManualFramingMode is false, or ManualFramingMode
	// is true and the framing is invalid, the framing headers are based on the
	// message body, and any framing headers already set in the message are
	// discarded.
	ManualFramingMode bool
	// contains filtered or unexported fields
}

Request represents an HTTP request received by this server from a requesting client, or to be sent from this server during this execution. Some fields only have meaning in one context or the other.

func NewRequest

func NewRequest(method string, uri string, body io.Reader) (*Request, error)

NewRequest constructs an outgoing request with the given HTTP method, URI, and body. The URI is parsed via url.Parse.

func RequestFromContext added in v0.1.2

func RequestFromContext(ctx context.Context) *Request

RequestFromContext returns the fsthttp.Request associated with the context, if any.

func (*Request) AddCookie

func (req *Request) AddCookie(c *Cookie)

AddCookie adds a cookie to the request. Per RFC 6265 section 5.4, AddCookie does not attach more than one Cookie header field. That means all cookies, if any, are written into the same line, separated by semicolon. AddCookie only sanitizes c's name and value, and does not sanitize a Cookie header already present in the request.

func (*Request) Clone

func (req *Request) Clone() *Request

Clone returns a copy of the request. The returned copy will have a nil Body field, and it's URL will have a nil User field.

func (*Request) Cookie

func (req *Request) Cookie(name string) (*Cookie, error)

Cookie returns the named cookie provided in the request or ErrNoCookie if not found. If multiple cookies match the given name, only one cookie will be returned.

func (*Request) Cookies

func (req *Request) Cookies() []*Cookie

Cookies parses and returns the HTTP cookies sent with the request.

func (*Request) Send

func (req *Request) Send(ctx context.Context, backend string) (*Response, error)

Send the request to the named backend. Requests may only be sent to backends that have been preconfigured in your service, regardless of their URL. Once sent, a request cannot be sent again.

type Response

type Response struct {
	// Request associated with the response.
	Request *Request

	// Backend that served the response.
	Backend string

	// StatusCode of the response.
	StatusCode int

	// Header received with the response.
	Header Header

	// Body of the response.
	Body io.ReadCloser
}

Response to an outgoing HTTP request made by this server.

func ResponseFromContext added in v0.1.2

func ResponseFromContext(ctx context.Context) *Response

ResponseFromContext returns the fsthttp.Response associated with the context, if any.

func (*Response) Cookies

func (resp *Response) Cookies() []*Cookie

Cookies parses and returns the cookies set in the Set-Cookie headers.

type ResponseWriter

type ResponseWriter interface {
	// Header returns the headers that will be sent by WriteHeader.
	// Changing the returned headers after a call to WriteHeader has no effect.
	Header() Header

	// WriteHeader initiates the response to the client by sending an HTTP
	// response preamble with the provided status code, and all of the response
	// headers collected by Header. If WriteHeader is not called explicitly,
	// the first call to Write or Close will trigger an implicit call to
	// WriteHeader with a code of 200. After the first call to WriteHeader,
	// subsequent calls have no effect.
	WriteHeader(code int)

	// Write the data to the connection as part of an HTTP reply.
	//
	// If WriteHeader has not yet been called, Write calls WriteHeader(200)
	// before writing the data. Unlike the ResponseWriter in net/http, Write
	// will not automatically add Content-Type or Content-Length headers.
	Write(p []byte) (int, error)

	// Close the response to the client. Close must be called to ensure the
	// response has been fully written to the client.
	//
	// If WriteHeader has not yet been called, Close calls WriteHeader(200)
	// before closing the response. Once closed, a ResponseWriter is
	// invalidated, and may no longer be accessed or used in any way.
	Close() error

	// SetManualFramingMode controls how the framing headers
	// (Content-Length/Transfer-Encoding) are set for a response.
	//
	// If set to true, the response uses the exact framing headers
	// set in the message.  If set to false, or set to true and
	// the framing is invalid, the framing headers are based on the
	// message body, and any framing headers already set in the message are
	// discarded.
	//
	// To have an effect on the response, this must be called before any call to Write() or WriteHeader().
	SetManualFramingMode(bool)
}

ResponseWriter is used to respond to client requests.

func ResponseWriterFromContext added in v0.1.2

func ResponseWriterFromContext(ctx context.Context) ResponseWriter

ResponseWriterFromContext returns the fsthttp.ResponseWriter associated with the context, if any.

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 (
	//revive:disable:exported
	SameSiteDefaultMode SameSite = iota + 1
	SameSiteLaxMode
	SameSiteStrictMode
	SameSiteNoneMode
)

type TLSInfo

type TLSInfo struct {
	// Protocol contains the TLS protocol version used to secure the client TLS
	// connection, if any.
	Protocol string

	// ClientHello contains raw bytes sent by the client in the TLS ClientHello
	// message. See RFC 5246 for details.
	ClientHello []byte

	// CipherOpenSSLName contains the cipher suite used to secure the client TLS
	// connection. The value returned will be consistent with the OpenSSL name
	// for the cipher suite.
	CipherOpenSSLName string
}

TLSInfo collects TLS-related metadata for incoming requests. All fields are ignored for outgoing requests.

type Transport added in v0.1.2

type Transport struct {

	// Request is an optional callback invoked before the request is
	// sent to the backend.  It allows callers to set
	// fsthttp.Request-specific fields, such as cache control options.
	Request func(req *Request) error
	// contains filtered or unexported fields
}

Transport is an http.RoundTripper implementation for backend requests on Compute@Edge.

Compute@Edge requests must be made to a pre-configured named backend. Transport provides a mechanism for mapping hostnames to backend names. A default catchall backend is set when the Transport is created, but additional host-to-backend mappings can be added with the AddHostBackend method.

Transport is provided primarily to adapt existing code which uses http.Client instances to work on Compute@Edge. Using an http.Client pulls in substantially more code, resulting in slower compile times and larger binaries. For this reason, we recommend new code use the fsthttp.Request type and its Send() method directly whenever possible.

func NewTransport added in v0.1.2

func NewTransport(backend string) *Transport

NewTransport creates a new Transport instance with the given default backend. Any request made to a host not explicitly mapped to a backend using the AddHostBackend method will be sent to the default backend.

func (*Transport) AddHostBackend added in v0.1.2

func (t *Transport) AddHostBackend(host, backend string)

AddHostBackend adds a new host-to-backend mapping. Multiple hosts may be mapped to the same backend.

func (*Transport) RoundTrip added in v0.1.2

func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error)

RoundTrip implements the http.RoundTripper interface.

The provided http.Request is adapted into an fsthttp.Request. If the Transport's Request callback field is set, it is invoked so that the fsthttp.Request can be modified before it is sent. The request is then sent to the backend matching the host in the URL. The resulting fsthttp.Response is adapted into an http.Response and returned.

The http.Response's Request field contains a context from which the original fsthttp.Request and fsthttp.Response can be extracted using fsthttp.RequestFromContext and fsthttp.ResponseFromContext.

Jump to

Keyboard shortcuts

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