layers

package
v2.0.5 Latest Latest
Warning

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

Go to latest
Published: Jun 22, 2021 License: MIT Imports: 14 Imported by: 3

Documentation

Overview

Context and layers.

A layer is a keystone of extensibility of httransform. You can think about them as stacks of callbacks.

One diagram worth 1000 words:

       HTTP interface            Layer 1             Layer 2
     +----------------+      **************      **************
     |                |      *            *      *            *       ==============
---> |  HTTP request  | ===> *  OnRequest * ===> *  OnRequest * ===>  =            =
     |                |      *            *      *            *       =            =
     +----------------+      **************      **************       =  Executor  =
     |                |      *            *      *            *       =            =
<--- |  HTTP response | <=== * OnResponse * <=== * OnResponse * <===  =            =
     |                |      *            *      *            *       ==============
     +----------------+      **************      **************

As you see, the request goes through the all layers forward and backward. This is a contract of this package. So, if you have a layers A and B, a request path is A(onRequest) -> B(onRequest) -> Executor -> B(onResponse) -> A(onResponse) -> client. So, that's why it worth to think about layers as about 'stacks'.

Let's check what happens if some layer returns an error:

       HTTP interface            Layer 1                 Layer 2
     +----------------+      **************           **************
     |                |      *            *           *            *       ==============
---> |  HTTP request  | ===> *  OnRequest * ===> X    *  OnRequest *       =            =
     |                |      *            *      |    *            *       =            =
     +----------------+      **************      |    **************       =  Executor  =
     |                |      *            *      |    *            *       =            =
<--- |  HTTP response | <=== * OnResponse * <=== +    * OnResponse *       =            =
     |                |      *            *           *            *       ==============
     +----------------+      **************           **************

So, we guarantee that error will pass through the same layers which were already processed a request.

Executor can also return an error. But it is its responsibility to put this error into a response.

Index

Constants

View Source
const TimeoutLayerKeyCancel = "timeout_layer__cancel"

TimeoutLayerKeyCancel defines a key which is used in context to store some internal data.

Variables

This section is empty.

Functions

func ReleaseContext

func ReleaseContext(ctx *Context)

ReleaseContext returns a context back to the pool.

Types

type Context

type Context struct {
	// ConnectTo contains an endpoint we have to connect to as a next
	// hop. For example, if you have TLS tunnel, you have 2 addresses:
	// one from CONNECT method, another one - from a tunneled request.
	ConnectTo string

	// RequestID is some unique identifier of the request.
	RequestID string

	// User is a username of a client which is doing a request. It
	// is returned from auth.Interface. If you do not have setup
	// authentication, it is an empty string.
	User string

	// EventStream is an instance of event stream to use.
	EventStream events.Stream

	// RequestType is a bitset related to different characteristics of the
	// request.
	RequestType events.RequestType

	// RequestHeaders is a headers of the request.
	//
	// If you need to do something with headers, please work with this
	// field. Underlying request is case sensitive so it would be really
	// awkward to do anything with it.
	//
	// Underlying fasthttp.Request headers are going to be dropped
	// before sending a request and repopulated from this one.
	//
	// If you implement a middleware, you should update this set only on
	// OnRequest chain flow. Please do not update them in any OnResponse
	// handler.
	RequestHeaders headers.Headers

	// ResponseHeaders is a headers of the response.
	//
	// If you need to do something with headers, please work with this
	// field. Underlying request is case sensitive so it would be really
	// awkward to do anything with it.
	//
	// Underlying fasthttp.Response headers are going to be dropped before
	// sending a response and repopulated from this one.
	//
	// If you implement a middleware, you should update this set only on
	// OnResponse chain flow. Please do not update them in any OnRequest
	// handler.
	ResponseHeaders headers.Headers
	// contains filtered or unexported fields
}

Context is a data structure which we pass along the request. It contains requests, responses, different metadata. You can attach some free-form data there.

func AcquireContext

func AcquireContext() *Context

AcquireContext returns a new context from the pool.

func (*Context) Cancel

func (c *Context) Cancel()

Cancel cancels a given context.

func (*Context) Deadline

func (c *Context) Deadline() (time.Time, bool)

Deadline conforms a context.Context interface.

func (*Context) Delete

func (c *Context) Delete(key string)

Delete deletes a key from the internal storage.

func (*Context) Done

func (c *Context) Done() <-chan struct{}

Done conforms a context.Context interface.

func (*Context) Err

func (c *Context) Err() error

Err conforms a context.Context interface.

func (*Context) Error

func (c *Context) Error(err error)

Error is a shortcut for the fast response about given error.

func (*Context) Get

func (c *Context) Get(key string) interface{}

Get gets a value from internal storage.

func (*Context) Hijack

func (c *Context) Hijack(netlocConn net.Conn, hijacker RequestHijacker)

Hijack setups a hijacker for the request if necessary. Usually you need it if you want to process upgraded connections such as websockets.

netlocConn is a connection to a target website. It is closed when you exit a hijacker function.

func (*Context) Hijacked

func (c *Context) Hijacked() bool

Hijacked checks if given context was hijacked or not.

func (*Context) Init

func (c *Context) Init(fasthttpCtx *fasthttp.RequestCtx,
	connectTo string,
	eventStream events.Stream,
	user string,
	requestType events.RequestType) error

Init initializes a Context based on given parameters.

fasthttpCtx is a parent context which produced this one, connectTo is a host:port of the remote endpoint we need to connect to on a first-hop (think about CONNECT method). The rest of parameters are trivial.

func (*Context) LocalAddr

func (c *Context) LocalAddr() net.Addr

LocalAddr returns an instance of local address of the client.

func (*Context) RemoteAddr

func (c *Context) RemoteAddr() net.Addr

RemoteAddr returns an instance of remote address of the client.

func (*Context) Request

func (c *Context) Request() *fasthttp.Request

Request returns a pointer to the original fasthttp.Request.

func (*Context) Reset

func (c *Context) Reset()

Reset resets a state of the given context. It also cancels it if necessary.

func (*Context) Respond

func (c *Context) Respond(msg string, statusCode int)

Respond is just a shortcut for the fast response. This response is just a plain text with a status code.

func (*Context) Response

func (c *Context) Response() *fasthttp.Response

Response returns a pointer to the original fasthttp.Response.

func (*Context) Set

func (c *Context) Set(key string, value interface{})

Set sets a value to internal storage.

func (*Context) Value

func (c *Context) Value(key interface{}) interface{}

Value conforms a context.Context interface.

type HeadersLayer

type HeadersLayer struct {
	// These headers are set via ctx.RequestHeaders.Set method.
	RequestSet []headers.Header

	// These headers are set via ctx.RequestHeaders.SetExact method.
	RequestSetExact []headers.Header

	// These headers are removed via ctx.RequestHeaders.Remove method.
	RequestRemove []string

	// These headers are removed via ctx.RequestHeaders.RemoveExact method.
	RequestRemoveExact []string

	// These headers are set via ctx.ResponseHeaders.Set method if we see
	// no failures.
	ResponseOkSet []headers.Header

	// These headers are set via ctx.ResponseHeaders.SetExact method if we
	// see no failures.
	ResponseOkSetExact []headers.Header

	// These headers are removed via ctx.ResponseHeaders.Remove method if we
	// see no failures.
	ResponseOkRemove []string

	// These headers are removed via ctx.ResponseHeaders.RemoveExact method
	// if we see no failures.
	ResponseOkRemoveExact []string

	// These headers are set via ctx.ResponseHeaders.Set method if we see
	// failures.
	ResponseErrSet []headers.Header

	// These headers are set via ctx.ResponseHeaders.SetExact method if we
	// see failures.
	ResponseErrSetExact []headers.Header

	// These headers are removed via ctx.ResponseHeaders.Remove method if we
	// see failures.
	ResponseErrRemove []string

	// These headers are removed via ctx.ResponseHeaders.RemoveExact method
	// if we see failures.
	ResponseErrRemoveExact []string
}

HeadersLayer defines a general layer which adds / modifies and removes headers.

func (*HeadersLayer) OnRequest

func (h *HeadersLayer) OnRequest(ctx *Context) error

OnRequest is to conform Layer interface.

func (*HeadersLayer) OnResponse

func (h *HeadersLayer) OnResponse(ctx *Context, err error) error

OnResponse is to conform Layer interface.

type Layer

type Layer interface {
	// OnRequest is going to be executed when your request goes towards
	// an executor.
	//
	// If you return an error from this method, the whole chain is going
	// to be aborted and this error will go backwards via stack.
	OnRequest(*Context) error

	// OnResponse is going to be executed when your response goes from
	// executor or error has happened.
	//
	// If this middleware has generated that error, it will be a first
	// which OnResponse is going to be callled. You need to return an
	// error from this method. Usually you need to return a propagated
	// error but sometimes you can override it adding some context and
	// return a new one.
	OnResponse(*Context, error) error
}

Layer is a middleware which processes a request and a response.

You can think about layers as stacks: you go through the list forward and on response or error you go backwards. There is a guarantee that if you passed through OnRequest function call, your OnResponse is also be called.

func NewFilterSubnetsLayer

func NewFilterSubnetsLayer(subnets []net.IPNet) (Layer, error)

NewFilterSubnetsLayer filters out requests which should not be passed further. You can use it to protect an access to your private networks.

For example, you can block requests to 127.0.0.1/8, 10.0.0.0/8.

This layer does DNS queries and uses their results to understand if it worth to proceed or not.

type ProxyHeadersLayer

type ProxyHeadersLayer struct{}

ProxyHeadersLayer is simplified version of HeadersLayer with 0 configuration but created only to wipe out some proxy headers from requests and responses.

func (ProxyHeadersLayer) OnRequest

func (p ProxyHeadersLayer) OnRequest(ctx *Context) error

OnRequest is to conform Layer interface.

func (ProxyHeadersLayer) OnResponse

func (p ProxyHeadersLayer) OnResponse(ctx *Context, err error) error

OnResponse is to conform Layer interface.

type RequestHijacker

type RequestHijacker func(clientConn, netlocConn net.Conn)

RequestHijacker is a function signature you can use for internal hijacking. You function will have both ends: a client connection and a netloc connection.

type TimeoutLayer

type TimeoutLayer struct {
	// Timeout defines a hard time limit of the request.
	Timeout time.Duration
}

TimeoutLayer defines a layer which control a time of execution of the request. So, if you want to limit an execution time by 1 minute, this is a right place to do.

The only flaw is that IF we stopped to process a response and started to pump it back, this middleware does not control that.

func (TimeoutLayer) OnRequest

func (t TimeoutLayer) OnRequest(ctx *Context) error

OnRequest conforms Layer interface.

func (TimeoutLayer) OnResponse

func (t TimeoutLayer) OnResponse(ctx *Context, err error) error

OnResponse conforms Layer interface.

Jump to

Keyboard shortcuts

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