Documentation
¶
Overview ¶
Package pipeline in Gozerian allows clients to to define and create sequential processing pipes for http requests and their associated responses. There are a couple of key concepts to understand and use this effectively:
Pipe ¶
A Pipe represents an intermediary (proxy) during the round trip of a HTTP request from a client to a target and any functional activity or translations that may need to be made during processing of the request or response.
Unlike most proxies that have a single request handler pipeline (including the built-in handlers in Go), Gozerian takes a contrarian view that the request and response pipes should be separated in order to provide the greatest level of control and compatibility with external systems. (For example, a primary use case of Gozerian is to work as a plugin to the ngxin server.)
In addition to the request and response pipes, a pipe maintains a context and control system. This is accessible by type asserting the passed http.Writer to a pipeline.ControlHolder and calling its Control() function like so:
return func(w http.ResponseWriter, r *http.Request) {
control := pipeline.ControlFromContext(r.Context())
Once you have a pipeline.Control, your fitting now has a variety of options available to it including logging, error handling, flow variables, etc. See the pipeline.Control documentation for more information.
Fitting ¶
A Fitting is simply an interface that allows for custom behavior for a single step (either request or response or both) in a Pipe. The interface is:
RequestHandlerFunc() http.HandlerFunc ResponseHandlerFunc() ResponseHandlerFunc
Either of these methods may return nil. Note that the request handler is the standard Go handler (http.RequestHandlerFunc) while a response handler is defined as a pipeline.ResponseHandlerFunc as there is no preexisting standard function. It is defined as:
func(w http.ResponseWriter, r *http.Request, res *http.Response)
Die ¶
A Die is nothing more than a factory function to create a Fitting. A Die is registered with the system by name and is called during the initialization of a Pipe. The function signature is:
func(config interface{}) (Fitting, error)
To register a Die with the system, you need only ensure that the Die (and Fitting, of course) is compiled into the Go executable and call RegisterDie with a unique ID and the Die function like so:
pipeline.RegisterDie("dump", test_util.CreateDumpFitting)
Setup & Execution:
Configuration can easily done via a YAML file. Example:
port: 8080
target: http://httpbin.org
pipes: # pipe definitions
main: # pipe id (as registered)
request: # request pipeline
- dump: # name of plugin
dumpBody: true # plugin-specific configuration
response: # response pipeline
- dump: # name of plugin
dumpBody: true # plugin-specific configuration
proxies: # maps host & path -> pipe
- host: localhost # host
path: / # path
pipe: main # pipe to use
Then, your main file need only register your Dies, open the configuration file and execute the gateway:
pipeline.RegisterDie("dump", test_util.CreateDumpFitting)
yamlReader, err := os.Open("main.yaml")
if err != nil {
fmt.Print(err)
}
err = go_gateway.ListenAndServe(yamlReader)
if err != nil {
fmt.Print(err)
}
Index ¶
- Constants
- func DefaultErrorHanderFunc(writer http.ResponseWriter, err error) error
- func NewControlContext(ctx context.Context, ctl Control) context.Context
- func RegisterDie(id string, die Die)
- func RegisterDies(m map[string]Die)
- type Control
- type Definition
- type Die
- type ErrorHandlerFunc
- type Fitting
- type FittingDef
- type FittingWithID
- type FlowData
- type Logger
- type Pipe
- type PipeDef
- type ResponseHandlerFunc
Constants ¶
const ( ConfigTimeout = "timeout" ConfigLogLevel = "logLevel" )
Variables ¶
This section is empty.
Functions ¶
func DefaultErrorHanderFunc ¶
func DefaultErrorHanderFunc(writer http.ResponseWriter, err error) error
DefaultErrorHanderFunc for now just sends the error to the client
func RegisterDies ¶
RegisterDies associates multiple Dies with ids
Types ¶
type Control ¶
type Control interface {
RequestID() string
SetErrorHandler(eh ErrorHandlerFunc)
ErrorHandler() ErrorHandlerFunc
HandleError(w http.ResponseWriter, err interface{}) error
Error() error
Cancel()
Cancelled() bool
Log() Logger
Config() config
FlowData() FlowData
}
Control contains control and context for a Pipe instance
func ControlFromContext ¶
type Definition ¶
type Definition interface {
CreatePipe() Pipe
}
Definition of a pipe
func DefinePipe ¶
func DefinePipe(r io.Reader) (Definition, error)
DefinePipeFromReader returns a Pipe Definition as defined in the yaml Reader
func DefinePipeDirectly ¶
func DefinePipeDirectly(pipeConfig PipeDef) (Definition, error)
func NewDefinition ¶
func NewDefinition(reqFittings []FittingWithID, resFittings []FittingWithID) Definition
DefinePipe returns a Pipe Definition defined by the passed handlers
type ErrorHandlerFunc ¶
type ErrorHandlerFunc func(writer http.ResponseWriter, err error) error
ErrorHandlerFunc is a function called to handle an error in a Pipe
type Fitting ¶
type Fitting interface {
RequestHandlerFunc() http.HandlerFunc
ResponseHandlerFunc() ResponseHandlerFunc
}
Fitting is a function in a Pipe
type FittingDef ¶
type FittingDef map[string]interface{}
type FittingWithID ¶
func NewFitting ¶
func NewFitting(dieID string, config interface{}) (FittingWithID, error)
NewFitting creates a fitting from a registered Die
type FlowData ¶
type FlowData map[string]interface{}
ExtraData is just an open map for storing stuff
type Logger ¶
type Logger interface {
Debugf(format string, args ...interface{})
Infof(format string, args ...interface{})
Printf(format string, args ...interface{})
Warnf(format string, args ...interface{})
Warningf(format string, args ...interface{})
Errorf(format string, args ...interface{})
Fatalf(format string, args ...interface{})
Panicf(format string, args ...interface{})
Debug(args ...interface{})
Info(args ...interface{})
Print(args ...interface{})
Warn(args ...interface{})
Warning(args ...interface{})
Error(args ...interface{})
Fatal(args ...interface{})
Panic(args ...interface{})
Debugln(args ...interface{})
Infoln(args ...interface{})
Println(args ...interface{})
Warnln(args ...interface{})
Warningln(args ...interface{})
Errorln(args ...interface{})
Fatalln(args ...interface{})
Panicln(args ...interface{})
WithField(key string, value interface{}) *logrus.Entry
WithFields(fields logrus.Fields) *logrus.Entry
}
Logger represents the logging interface
type Pipe ¶
type Pipe interface {
PrepareRequest(reqID string, req *http.Request) *http.Request
// Be sure to call this with a prepared http.Request!
RequestHandlerFunc() http.HandlerFunc
// Be sure to call this with a prepared http.Request!
ResponseHandlerFunc() ResponseHandlerFunc
}
Pipe runs a series of request and response handlers
type PipeDef ¶
type PipeDef struct {
Request []FittingDef `yaml:"request"`
Response []FittingDef `yaml:"response"`
}
type ResponseHandlerFunc ¶
ResponseHandlerFunc is the part of the Pipe that handles responses