pass

package module
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Feb 21, 2021 License: MIT Imports: 12 Imported by: 0

README

pass

Go Reference

Pass is a library for building reverse-proxies. It wraps httputil.ReverseProxy, and specifies routing via configuration files.

Configuration

Routing in Pass is configured via HCL. This enables proxy routing to be configured outside of your binary's code—such as Kubernetes ConfigMap definitions.

// Base prefix for all upstream routes. (optional)
prefix_path = "/api/v2"

// Annotations for this Manifest that can be used by other libraries once
// this Manifest is parsed. Similar to Kubernetes Annotations, they enable other
// libraries and tooling to apply meaning to the Manifest. These values are
// arbitrary to the pass library.
annotations = {
    "company/version": 2
}

// Define an upstream service called "widgets". The identifier here is just a
// human readable string to refer to this service. For instance, you could use
// this identifier when tagging metrics.
upstream "widgets" {
    // Annotations for this upstream destination.
    annotations = {
        "company/middleware": "jwt,tracing"
    }

    // Location in the form of "scheme://hostname" to send the traffic.
    destination = "http://widgets.local" 

    // Team identifier to help keep track of who's the point of contact for a
    // particular upstream service. (optional)
    owner = "Team A <team-a@company.com>"

    // Inform the reverse-proxy to flush the response body every second. If this
    // is omitted, no flushing will be peformed. A negative value will flush
    // immediately after each write to the client. (optional)
    flush_interval_ms = 1000

    // Add an additional prefix segment (added to the root level `prefix_path`)
    // that should be stripped from outgoing requests. (optional)
    prefix_path = "/private"

    // GET `/api/v2/private/widgets` -> GET `http://widgets.local/widgets`
    // POST `/api/v2/private/widgets` -> POST `http://widgets.local/widgets`
    route {
        methods = ["GET", "POST"]
        path = "/widgets"
    }

    // GET `/api/v2/private/widgets/123` -> GET `http://widgets.local/widgets/123`
    // PUT `/api/v2/private/widgets/123` -> PUT `http://widgets.local/widgets/123`
    // DELETE `/api/v2/private/widgets/123` -> DELETE `http://widgets.local/widgets/123`
    route {
        methods = ["GET", "PUT", "DELETE"]
        path = "/widgets/{[0-9]+}"
    }
}

upstream "gears" {
    destination = "http://gears.local" 
    owner = "Team B <team-b@company.com>"
    prefix_path = "/gears"

    // ANY METHOD /api/v2/gears/anything -> http://gears.local/api/v2/gears/anything
    route {
        methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
        path = "/*"
    }

    // ANY METHOD /api/v2/gears -> http://gears.local/api/v2/gears
    route {
        methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
        path = "/"
    }
}

Parsing the file and mounting it in your application:

m, err := pass.LoadManifest("./manifest.hcl", nil)
if err != nil {
	return err
}

// Register the manifest's routes with a router.
proxy, err := pass.New(m)
if err != nil {
	return err
}

You can pass an optional hcl.EvalContext to specify variables and functions as part of the HCL parsing.

ectx := &hcl.EvalContext{
	Variables: map[string]cty.Value{
		"namespace": cty.StringVal("example"),
	},
}

// The variable "namespace" will be available in this configuration file.
m, err := pass.LoadManifest("./manifest.hcl", ectx)
if err != nil {
	return err
}

Examples

Check out the example/ directory for usage examples in code.

Documentation

Overview

Package pass provides a small and configurable reverse-proxy.

Index

Constants

This section is empty.

Variables

View Source
var ErrDuplicateUpstreamIdentifier = fmt.Errorf("duplicate upstream identifier")

ErrDuplicateUpstreamIdentifier is returned when there more than one Upstream in a Manifest with the same identifier.

View Source
var ErrMissingUpstreamForMiddleware = fmt.Errorf("upstream missing for middleware stack")

ErrMissingUpstreamForMiddleware is returned when the Upstream referenced by a middleware stack doesn't exist in the Manifest.

Functions

This section is empty.

Types

type BufferPool

type BufferPool = httputil.BufferPool

BufferPool is an alias for httputil.BufferPool

type ErrorHandler

type ErrorHandler func(http.ResponseWriter, *http.Request, error)

ErrorHandler is a function that handles errors on behalf of the proxy. Errors returned from ResponseModifier functions will also be handled by this function.

type Manifest

type Manifest struct {
	Annotations map[string]string `hcl:"annotations,optional"` // Annotations to be used by other libraries
	Upstreams   []Upstream        `hcl:"upstream,block"`       // Upstream route configurations
	PrefixPath  string            `hcl:"prefix_path,optional"` // Prefix to add to all upstream routes. Stripped when proxying.
	// contains filtered or unexported fields
}

Manifest is a list of upstream services in which to proxy.

func LoadManifest

func LoadManifest(filename string, ectx *hcl.EvalContext) (*Manifest, error)

LoadManifest parses an HCL file containing the manifest.

type MountOption

type MountOption func(*mountConfig)

MountOption is a functional option used when mounting a manifest to a router.

func WithBufferPool

func WithBufferPool(p BufferPool) MountOption

WithBufferPool specifies a BufferPool to obtain byte slices for io.CopyBuffer operations when copying responses.

func WithErrorHandler

func WithErrorHandler(fn ErrorHandler) MountOption

WithErrorHandler specifies an ErrorHandler to call in the face on any errors communicating with the upstream service.

func WithErrorLog

func WithErrorLog(l *log.Logger) MountOption

WithErrorLog specifies an error logger to use when reporting upstream communication errors instead of the log package's default logger.

func WithNotFound added in v0.0.2

func WithNotFound(h http.HandlerFunc) MountOption

WithNotFound specifies an http.HandlerFunc to use if no routes in the manifest match. Use this for fall-through behavior to delegate to existing (in-process) routes.

func WithObserveFunction

func WithObserveFunction(fn ObserveFunction) MountOption

WithObserveFunction sets an ObserveFunction to use for all requests being proxied upstream.

func WithRequestModifier

func WithRequestModifier(fn RequestModifier) MountOption

WithRequestModifier specifies a RequestModifer to apply to all outgoing requests.

func WithResponseModifier

func WithResponseModifier(fn ResponseModifier) MountOption

WithResponseModifier specifies a ResponseModifier function to apply to responses coming from upstream service. If the upstream is unreachable, this function will not be called.

func WithRoot

func WithRoot(prefix string) MountOption

WithRoot informs the proxy of the root mount point. This root prefix will be stripped away from all requests sent upstream.

func WithTrailingSlashes added in v0.0.3

func WithTrailingSlashes() MountOption

WithTrailingSlashes forces trailing slashes to be unhandled. By default, the Proxy will strip trailing slashes where appropriate.

func WithTransport

func WithTransport(t http.RoundTripper) MountOption

WithTransport specifies an http.RoundTripper to use instead of http.DefaultTransport.

func WithUpstreamMiddleware added in v0.0.2

func WithUpstreamMiddleware(upstream string, m ...func(http.Handler) http.Handler) MountOption

WithUpstreamMiddleware registers a middleware stack for an upstream identifier (from the Manifest). When the Upstream's routes are registered these middleware will be applied along with them. Middlewares are applied in-order.

type ObserveFunction

type ObserveFunction func(*http.Request, *RouteInfo)

ObserveFunction is a function called just before a request is proxied to an upstream host. It provides an opportunity to perform logging and update metrics with information about the route.

type Proxy added in v0.0.2

type Proxy struct {
	// contains filtered or unexported fields
}

Proxy is a reverse-proxy.

func New added in v0.0.2

func New(m *Manifest, opts ...MountOption) (*Proxy, error)

New creates a new Proxy with the Manifest's routes mounted to it.

func (*Proxy) Root added in v0.0.2

func (p *Proxy) Root() string

Root returns the root specified at Proxy creation + the "prefix_path" specified in the Manifest.

func (*Proxy) ServeHTTP added in v0.0.2

func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements net/http.Handler

func (*Proxy) Upstreams added in v0.0.2

func (p *Proxy) Upstreams() []Upstream

Upstreams returns the Upstream services registered with this Proxy.

type RequestModifier

type RequestModifier func(*http.Request)

RequestModifier is a function that modifies a request

type ResponseModifier

type ResponseModifier func(*http.Response) error

ResponseModifier is a function that modifies upstream responses before as they are returned to the client.

type Route

type Route struct {
	Methods []string `hcl:"methods"` // HTTP Methods
	Path    string   `hcl:"path"`    // HTTP Path
}

Route is an individual HTTP method/path combination in which to proxy.

type RouteInfo

type RouteInfo struct {
	RouteMethod        string
	RoutePath          string
	RoutePrefix        string
	UpstreamHost       string
	UpstreamIdentifier string
	UpstreamOwner      string
}

RouteInfo is a structure that communicates route information to an ObserveFunction.

type Upstream

type Upstream struct {
	Identifier      string            `hcl:",label"`                     // Human identifier for the upstream
	Annotations     map[string]string `hcl:"annotations,optional"`       // Annotations to be used by other libraries
	Destination     string            `hcl:"destination"`                // Scheme and Hostname of the upstream component
	Routes          []Route           `hcl:"route,block"`                // Routes to accept
	FlushIntervalMS int               `hcl:"flush_interval_ms,optional"` // httputil.ReverseProxy.FlushInterval value in milliseconds
	Owner           string            `hcl:"owner,optional"`             // Team that owns the upstream component
	PrefixPath      string            `hcl:"prefix_path,optional"`       // Prefix to add to all routes. Stripped when proxying.
}

Upstream is an upstream service in which to proxy.

Directories

Path Synopsis
example

Jump to

Keyboard shortcuts

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