Documentation
ΒΆ
Overview ΒΆ
Package typhon wraps net/http to provide a simple yet powerful programming model for RPC servers and clients. At Monzo, it is used to implement the majority of our Go microservices.
Index ΒΆ
- Variables
- func AppendMetadataToContext(ctx context.Context, md Metadata) context.Context
- func ErrorStatusCode(err error) int
- func HttpHandler(svc Service) http.Handler
- func RequestMethodFromContext(ctx context.Context) (string, bool)
- func RequestPatternFromContext(ctx context.Context) (string, bool)
- func WithH2C(ctx context.Context) context.Context
- type Filter
- type Metadata
- type Request
- func (r *Request) BodyBytes(consume bool) ([]byte, error)
- func (r Request) Decode(v interface{}) error
- func (r *Request) Encode(v interface{})
- func (r *Request) EncodeAsJSON(v interface{})
- func (r *Request) EncodeAsProtobuf(m proto.Message)
- func (r Request) RequestMethod() string
- func (r Request) RequestPathPattern() string
- func (r Request) Response(body interface{}) Response
- func (r Request) ResponseWithCode(body interface{}, statusCode int) Response
- func (r Request) Send() *ResponseFuture
- func (r Request) SendVia(svc Service) *ResponseFuture
- func (r Request) String() string
- func (r *Request) Write(b []byte) (n int, err error)
- type Response
- func (r *Response) BodyBytes(consume bool) ([]byte, error)
- func (r *Response) Decode(v interface{}) error
- func (r *Response) Encode(v interface{})
- func (r *Response) EncodeAsJSON(v interface{})
- func (r *Response) EncodeAsLegacyProtobuf(m legacyproto.Message)
- func (r *Response) EncodeAsProtobuf(m proto.Message)
- func (r *Response) EncodeAsProtobufJSON(m proto.Message)
- func (r Response) String() string
- func (r *Response) Write(b []byte) (n int, err error)
- func (r *Response) Writer() ResponseWriter
- type ResponseFuture
- type ResponseWriter
- type Router
- func (r *Router) CONNECT(pattern string, svc Service)
- func (r *Router) DELETE(pattern string, svc Service)
- func (r *Router) GET(pattern string, svc Service)
- func (r *Router) HEAD(pattern string, svc Service)
- func (r Router) Lookup(method, path string) (Service, string, map[string]string, bool)
- func (r *Router) OPTIONS(pattern string, svc Service)
- func (r *Router) PATCH(pattern string, svc Service)
- func (r *Router) POST(pattern string, svc Service)
- func (r *Router) PUT(pattern string, svc Service)
- func (r Router) Params(req Request) map[string]string
- func (r Router) Pattern(req Request) string
- func (r *Router) Register(method, pattern string, svc Service)
- func (r Router) Serve() Service
- func (r *Router) TRACE(pattern string, svc Service)
- type Server
- type ServerOption
- type Service
- type StreamerWriter
- type TimeoutOptions
- type WrapDownstreamErrors
Constants ΒΆ
This section is empty.
Variables ΒΆ
var ( // Client is used to send all requests by default. It can be overridden globally but MUST only be done before use // takes place; access is not synchronised. Client Service = BareClient // RoundTripper chooses HTTP1, or H2C based on a context flag (see WithH2C) RoundTripper http.RoundTripper = dynamicRoundTripper{} // HTTPRoundTripper is a HTTP1 and TLS HTTP2 client HTTPRoundTripper http.RoundTripper = &http.Transport{ Proxy: http.ProxyFromEnvironment, DisableKeepAlives: false, DisableCompression: false, IdleConnTimeout: 10 * time.Minute, MaxIdleConnsPerHost: 10, } // H2cRoundTripper is a prior-knowledge H2c client. It does not support ProxyFromEnvironment. H2cRoundTripper http.RoundTripper = &http2.Transport{ AllowHTTP: true, DialTLSContext: func(ctx context.Context, network, addr string, _ *tls.Config) (net.Conn, error) { var d net.Dialer return d.DialContext(ctx, network, addr) }, } )
Functions ΒΆ
func AppendMetadataToContext ΒΆ
AppendMetadataToContext sets the metadata on the context.
func ErrorStatusCode ΒΆ
ErrorStatusCode returns a HTTP status code for the given error.
If the error is not a terror, this will always be 500 (Internal Server Error).
func HttpHandler ΒΆ
HttpHandler transforms the given Service into a standard library HTTP handler. It is one of the main "bridges" between Typhon and net/http.
func RequestMethodFromContext ΒΆ added in v1.1.10
RequestMethodFromContext returns the method of the request, if available.
func RequestPatternFromContext ΒΆ added in v1.1.10
RequestPatternFromContext returns the pattern that was matched for the request, if available.
Types ΒΆ
type Filter ΒΆ
Filter functions compose with Services to modify their behaviour. They might change a service's input or output, or elect not to call the underlying service at all.
These are typically useful to encapsulate common logic that is shared among multiple Services. Authentication, authorisation, rate limiting, and tracing are good examples.
type Metadata ΒΆ
Metadata provides a transport agnostic way to pass metadata with Typhon. It aligns to the interface of Go's default HTTP header type for convenience.
func MetadataFromContext ΒΆ
MetadataFromContext retrieves the metadata from the context.
func NewMetadata ΒΆ
NewMetadata creates a metadata struct from a map of strings.
type Request ΒΆ
A Request is Typhon's wrapper around http.Request, used by both clients and servers.
Note that Typhon makes no guarantees that a Request is safe to access or mutate concurrently. If a single Request object is to be used by multiple goroutines concurrently, callers must make sure to properly synchronise accesses.
func NewRequest ΒΆ
NewRequest constructs a new Request with the given parameters, and if non-nil, encodes the given body into it.
func (*Request) BodyBytes ΒΆ
BodyBytes fully reads the request body and returns the bytes read.
If consume is true, this is equivalent to ioutil.ReadAll; if false, the caller will observe the body to be in the same state that it was before (ie. any remaining unread body can be read again).
Warning: if consume is false, you must ensure this is called on a pointer receiver (*Request) and not a Request value. This is because the Response.Body referenced by the caller needs to be mutated.
func (*Request) EncodeAsJSON ΒΆ
func (r *Request) EncodeAsJSON(v interface{})
EncodeAsJSON serialises the passed object as JSON into the body (and sets appropriate headers).
func (*Request) EncodeAsProtobuf ΒΆ
EncodeAsProtobuf serialises the passed object as protobuf into the body (and sets appropriate headers).
func (Request) RequestMethod ΒΆ added in v1.1.9
RequestMethod returns the HTTP method of the request
func (Request) RequestPathPattern ΒΆ added in v1.1.9
RequestPathPattern finds the router entry pattern that matches the request
func (Request) Response ΒΆ
Response constructs a new Response to the request, and if non-nil, encodes the given body into it.
func (Request) ResponseWithCode ΒΆ
ResponseWithCode constructs a new Response with the given status code to the request, and if non-nil, encodes the given body into it.
func (Request) Send ΒΆ
func (r Request) Send() *ResponseFuture
Send round-trips the request via the default Client. It does not block, instead returning a ResponseFuture representing the asynchronous operation to produce the response. It is equivalent to:
r.SendVia(Client)
func (Request) SendVia ΒΆ
func (r Request) SendVia(svc Service) *ResponseFuture
SendVia round-trips the request via the passed Service. It does not block, instead returning a ResponseFuture representing the asynchronous operation to produce the response.
type Response ΒΆ
type Response struct { *http.Response Error error Request *Request // The Request that we are responding to // contains filtered or unexported fields }
A Response is Typhon's wrapper around http.Response, used by both clients and servers.
Note that Typhon makes no guarantees that a Response is safe to access or mutate concurrently. If a single Response object is to be used by multiple goroutines concurrently, callers must make sure to properly synchronise accesses.
func BareClient ΒΆ
BareClient is the most basic way to send a request, using the default http RoundTripper
func ErrorFilter ΒΆ
ErrorFilter serialises and deserialises response errors. Without this filter, errors may not be passed across the network properly so it is recommended to use this in most/all cases. It tries to do everything it can to give you all the information that it can about why your request might have failed. Because of this, it has some weird behavior.
func ExpirationFilter ΒΆ
ExpirationFilter provides admission control; it rejects requests which are cancelled
func H2cFilter ΒΆ
H2cFilter adds HTTP/2 h2c upgrade support to the wrapped Service (as defined in RFC 7540 Β§3.2, Β§3.4).
func NewResponse ΒΆ
NewResponse constructs a Response with status code 200.
func NewResponseWithCode ΒΆ
NewResponseWithCode constructs a Response with the given status code.
func (*Response) BodyBytes ΒΆ
BodyBytes fully reads the response body and returns the bytes read. If consume is false, the body is copied into a new buffer such that it may be read again.
Warning: if consume is false, you must ensure this is called on a pointer receiver (*Response) and not a Response value. This is because the Response.Body referenced by the caller needs to be mutated.
func (*Response) Encode ΒΆ
func (r *Response) Encode(v interface{})
Encode serialises the passed object into the body (and sets appropriate headers).
func (*Response) EncodeAsJSON ΒΆ
func (r *Response) EncodeAsJSON(v interface{})
EncodeAsJSON writes the response as JSON. This is the default encoding type when using Encode.
func (*Response) EncodeAsLegacyProtobuf ΒΆ
func (r *Response) EncodeAsLegacyProtobuf(m legacyproto.Message)
EncodeAsLegacyProtobuf is required as github.com/monzo/terrors still uses the old protobuf code path.
func (*Response) EncodeAsProtobuf ΒΆ
EncodeAsProtobuf writes the passed object as protobuf wire format into the body.
func (*Response) EncodeAsProtobufJSON ΒΆ
EncodeAsProtobufJSON writes well-formed protobuf JSON to the response. See https://developers.google.com/protocol-buffers/docs/proto3#json for more info.
func (*Response) Writer ΒΆ
func (r *Response) Writer() ResponseWriter
Writer returns a ResponseWriter which can be used to populate the response.
This is useful when you want to use another HTTP library that is used to wrapping net/http directly. For example, it allows a Typhon Service to use a http.Handler internally.
type ResponseFuture ΒΆ
type ResponseFuture struct {
// contains filtered or unexported fields
}
A ResponseFuture is a container for a Response which will materialise at some point.
func Send ΒΆ
func Send(req Request) *ResponseFuture
Send round-trips the request via the default Client. It does not block, instead returning a ResponseFuture representing the asynchronous operation to produce the response. It is equivalent to:
SendVia(req, Client)
func SendVia ΒΆ
func SendVia(req Request, svc Service) *ResponseFuture
SendVia round-trips the request via the passed Service. It does not block, instead returning a ResponseFuture representing the asynchronous operation to produce the response.
func (*ResponseFuture) Response ΒΆ
func (f *ResponseFuture) Response() Response
Response provides access to the response object, blocking until it is available
func (*ResponseFuture) WaitC ΒΆ
func (f *ResponseFuture) WaitC() <-chan struct{}
WaitC returns a channel which can be waited upon until the response is available
type ResponseWriter ΒΆ
type ResponseWriter interface { http.ResponseWriter // WriteJSON writes the given data as JSON to the Response. The passed value must (perhaps obviously) be // serialisable to JSON. WriteJSON(interface{}) // WriteError writes the given error to the Response. WriteError(err error) }
type Router ΒΆ
type Router struct {
// contains filtered or unexported fields
}
A Router multiplexes requests to a set of Services by pattern matching on method and path, and can also extract parameters from paths.
func RouterForRequest ΒΆ
RouterForRequest returns a pointer to the Router that successfully dispatched the request, or nil.
func (Router) Lookup ΒΆ
Lookup returns the Service, pattern, and extracted path parameters for the HTTP method and path.
func (Router) Params ΒΆ
Params returns extracted path parameters, assuming the request has been routed and has captured parameters.
func (*Router) Register ΒΆ
Register associates a Service with a method and path.
Method is a HTTP method name, or "*" to match any method.
Patterns are strings of the format: /foo/:name/baz/*residual As well as being literal paths, they can contain named parameters like :name whose value is dynamic and only known at runtime, or *residual components which match (potentially) multiple path components.
In the case that patterns are ambiguous, the last route to be registered will take precedence.
type Server ΒΆ
type Server struct {
// contains filtered or unexported fields
}
func Serve ΒΆ
Serve starts a HTTP server, binding the passed Service to the passed listener and applying the passed ServerOptions.
func (*Server) Done ΒΆ
func (s *Server) Done() <-chan struct{}
Done returns a channel that will be closed when the server begins to shutdown. The server may still be draining its connections at the time the channel is closed.
type ServerOption ΒΆ added in v1.1.3
type ServerOption func(*Server)
ServerOption allows customizing the underling http.Server
func WithMaxConnectionAge ΒΆ added in v1.1.8
func WithMaxConnectionAge(maxAge time.Duration) ServerOption
WithMaxConnectionAge returns a server option that will enforce a max connection age. When a connection has reached the max connection age then the next request that is processed on that connection will result in the connection being gracefully closed. This does mean that if a connection is not being used then it can outlive the maximum connection age.
func WithTimeout ΒΆ added in v1.1.3
func WithTimeout(opts TimeoutOptions) ServerOption
WithTimeout sets the server timeouts.
type Service ΒΆ
A Service is a function that takes a request and produces a response. Services are used symmetrically in both clients and servers.
func HttpService ΒΆ
func HttpService(rt http.RoundTripper) Service
HttpService returns a Service which sends requests via the given net/http RoundTripper. Only use this if you need to do something custom at the transport level.
type StreamerWriter ΒΆ
type StreamerWriter interface { io.ReadWriteCloser CloseWithError(error) error }
func Streamer ΒΆ
func Streamer() StreamerWriter
Streamer returns a reader/writer/closer that can be used to stream responses. A simple use of this is:
func streamingService(req typhon.Request) typhon.Response { body := typhon.Streamer() go func() { // do something to asynchronously produce output into body if err != nil { body.CloseWithError(err) return } body.Close() }() return req.Response(body) }
Note that a Streamer may not perform any internal buffering, so callers should take care not to depend on writes being non-blocking. If buffering is needed, Streamer can be wrapped in a bufio.Writer.
type TimeoutOptions ΒΆ added in v1.1.3
type TimeoutOptions struct { Read time.Duration ReadHeader time.Duration Write time.Duration Idle time.Duration }
TimeoutOptions specifies various server timeouts. See http.Server for details of what these do. There's a nice post explaining them here: https://ieftimov.com/posts/make-resilient-golang-net-http-servers-using-timeouts-deadlines-context-cancellation/#server-timeouts---first-principles WARNING: Due to a Go bug, connections using h2c do not respect these timeouts. See https://github.com/golang/go/issues/52868
type WrapDownstreamErrors ΒΆ
type WrapDownstreamErrors struct{}
WrapDownstreamErrors is a context key that can be used to enable wrapping of downstream response errors on a per-request basis.
This is implemented as a context key to allow us to migrate individual services from the old behaviour to the new behaviour without adding a dependency on config to Typhon.