falcore

package module
v0.0.0-...-6be9a51 Latest Latest
Warning

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

Go to latest
Published: Apr 30, 2012 License: MIT Imports: 23 Imported by: 0

README

Falcore

Falcore is a framework for constructing high performance, modular HTTP servers in Golang.

Read more on our blog »

GoPkgDoc hosts code documentation for this project.

Features

  • Modular and flexible design
  • Hot restart hooks for zero-downtime deploys
  • Builtin statistics framework
  • Builtin logging framework

Design

Falcore is a filter pipeline based HTTP server library. You can build arbitrarily complicated HTTP services by chaining just a few simple components:

  • RequestFilters are the core component. A request filter takes a request and returns a response or nil. Request filters an modify the request as it passes through.
  • ResponseFilters can modify a response on its way out the door. An example response filter, compression_filter, is included. It applies deflate or gzip compression to the response if the request supplies the proper headers.
  • Pipelines form one of the two logic components. A pipeline contains a list of RequestFilters and a list of ResponseFilters. A request is processed through the request filters, in order, until one returns a response. It then passes the response through each of the response filters, in order. A pipeline is a valid RequestFilter.
  • Routers allow you to conditionally follow different pipelines. A router chooses from a set of pipelines. A few basic routers are included, including routing by hostname or requested path. You can implement your own router by implementing falcore.Router. Routers are not RequestFilters, but they can be put into pipelines.

Building

Falcore is currently targeted at Go 1.0. If you're still using Go r.60.x, you can get the last working version of falcore for r.60 using the tag last_r60.

Check out the project into $GOROOT/src/pkg/github.com/ngmoco/falcore. Build using the go build command.

Usage

See the examples directory for usage examples.

HTTPS

To use falcore to serve HTTPS, simply call ListenAndServeTLS instead of ListenAndServe. If you want to host SSL and nonSSL out of the same process, simply create two instances of falcore.Server. You can give them the same pipeline or share pipeline components.

Maintainers

Contributors

Documentation

Overview

Package falcore is a framework for constructing high performance, modular HTTP servers. For more information, see README.md

Index

Constants

View Source
const (
	FINEST level = iota
	FINE
	DEBUG
	TRACE
	INFO
	WARNING
	ERROR
	CRITICAL
)

Variables

This section is empty.

Functions

func Critical

func Critical(arg0 interface{}, args ...interface{}) error

func Debug

func Debug(arg0 interface{}, args ...interface{})

func Error

func Error(arg0 interface{}, args ...interface{}) error

func Fine

func Fine(arg0 interface{}, args ...interface{})

func Finest

func Finest(arg0 interface{}, args ...interface{})

Global Logging

func Info

func Info(arg0 interface{}, args ...interface{})

func SetLogger

func SetLogger(newLogger Logger)

func SimpleResponse

func SimpleResponse(req *http.Request, status int, headers http.Header, body string) *http.Response

func TimeDiff

func TimeDiff(startTime time.Time, endTime time.Time) float32

Helper for calculating times

func Trace

func Trace(arg0 interface{}, args ...interface{})

func Warn

func Warn(arg0 interface{}, args ...interface{}) error

Types

type HostRouter

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

Route requsts based on hostname

func NewHostRouter

func NewHostRouter() *HostRouter

Generate a new HostRouter instance

func (*HostRouter) AddMatch

func (r *HostRouter) AddMatch(host string, pipe RequestFilter)

TODO: support for non-exact matches

func (*HostRouter) SelectPipeline

func (r *HostRouter) SelectPipeline(req *Request) (pipe RequestFilter)

type Logger

type Logger interface {
	// Matches the log4go interface
	Finest(arg0 interface{}, args ...interface{})
	Fine(arg0 interface{}, args ...interface{})
	Debug(arg0 interface{}, args ...interface{})
	Trace(arg0 interface{}, args ...interface{})
	Info(arg0 interface{}, args ...interface{})
	Warn(arg0 interface{}, args ...interface{}) error
	Error(arg0 interface{}, args ...interface{}) error
	Critical(arg0 interface{}, args ...interface{}) error
}

I really want to use log4go... but i need to support falling back to standard (shitty) logger :( I suggest using go-timber for the real logger

func NewStdLibLogger

func NewStdLibLogger() Logger

type MatchAnyRoute

type MatchAnyRoute struct {
	Filter RequestFilter
}

Will match any request. Useful for fallthrough filters.

func (*MatchAnyRoute) MatchString

func (r *MatchAnyRoute) MatchString(str string) RequestFilter

type PathRouter

type PathRouter struct {
	Routes *list.List
}

Route requests based on path

func NewPathRouter

func NewPathRouter() *PathRouter

Generate a new instance of PathRouter

func (*PathRouter) AddMatch

func (r *PathRouter) AddMatch(match string, filter RequestFilter) (err error)

convenience method for adding RegexpRoutes

func (*PathRouter) AddRoute

func (r *PathRouter) AddRoute(route Route)

func (*PathRouter) SelectPipeline

func (r *PathRouter) SelectPipeline(req *Request) (pipe RequestFilter)

Will panic if r.Routes contains an object that isn't a Route

type Pipeline

type Pipeline struct {
	Upstream            *list.List
	Downstream          *list.List
	RequestDoneCallback RequestFilter
}

Pipelines have an upstream and downstream list of filters. A request is passed through the upstream items in order UNTIL a Response is returned. Once a request is returned, it is passed through ALL ResponseFilters in the Downstream list, in order.

If no response is generated by any Filters a default 404 response is returned.

The RequestDoneCallback (if set) will be called after the request has completed. The finished request object will be passed to the FilterRequest method for inspection. Changes to the request will have no effect and the return value is ignored.

func NewPipeline

func NewPipeline() (l *Pipeline)

func (*Pipeline) FilterRequest

func (p *Pipeline) FilterRequest(req *Request) *http.Response

Pipelines are also RequestFilters... wacky eh? Be careful though because a Pipeline will always returns a response so no Filters after a Pipeline filter will be run.

type PipelineStageStat

type PipelineStageStat struct {
	Name      string
	Status    byte
	StartTime time.Time
	EndTime   time.Time
}

Container for keeping stats per pipeline stage Name for filter stages is reflect.TypeOf(filter).String()[1:] and the Status is 0 unless it is changed explicitly in the Filter or Router.

For the Status, the falcore library will not apply any specific meaning to the status codes but the following are suggested conventional usages that we have found useful

  type PipelineStatus byte
  const (
	    Success PipelineStatus = iota	// General Run successfully
	    Skip								// Skipped (all or most of the work of this stage)
	    Fail								// General Fail
	    // All others may be used as custom status codes
  )

func NewPiplineStage

func NewPiplineStage(name string) *PipelineStageStat

type RegexpRoute

type RegexpRoute struct {
	Match  *regexp.Regexp
	Filter RequestFilter
}

Will match based on a regular expression

func (*RegexpRoute) MatchString

func (r *RegexpRoute) MatchString(str string) RequestFilter

type Request

type Request struct {
	ID                 string
	StartTime          time.Time
	EndTime            time.Time
	HttpRequest        *http.Request
	Connection         net.Conn
	RemoteAddr         *net.TCPAddr
	PipelineStageStats *list.List
	CurrentStage       *PipelineStageStat

	Overhead time.Duration
	// contains filtered or unexported fields
}

Request wrapper

The request is wrapped so that useful information can be kept with the request as it moves through the pipeline.

A pointer is kept to the originating Connection.

There is a unique ID assigned to each request. This ID is not globally unique to keep it shorter for logging purposes. It is possible to have duplicates though very unlikely over the period of a day or so. It is a good idea to log the ID in any custom log statements so that individual requests can easily be grepped from busy log files.

Falcore collects performance statistics on every stage of the pipeline. The stats for the request are kept in PipelineStageStats. This structure will only be complete in the Request passed to the pipeline RequestDoneCallback. Overhead will only be available in the RequestDoneCallback and it's the difference between the total request time and the sums of the stage times. It will include things like pipeline iteration and the stat collection itself.

See falcore.PipelineStageStat docs for more info.

The Signature is also a cool feature. See the

func (*Request) Signature

func (fReq *Request) Signature() string

The Signature will only be complete in the RequestDoneCallback. At any given time, the Signature is a crc32 sum of all the finished pipeline stages combining PipelineStageStat.Name and PipelineStageStat.Status. This gives a unique signature for each unique path through the pipeline. To modify the signature for your own use, just set the request.CurrentStage.Status in your RequestFilter or ResponseFilter.

func (*Request) Trace

func (fReq *Request) Trace()

Call from RequestDoneCallback. Logs a bunch of information about the request to the falcore logger. This is a pretty big hit to performance so it should only be used for debugging or development. The source is a good example of how to get useful information out of the Request.

type RequestFilter

type RequestFilter interface {
	FilterRequest(req *Request) *http.Response
}

Filter incomming requests and optionally return a response or nil. Filters are chained together into a flow (the Pipeline) which will terminate if the Filter returns a response.

func NewRequestFilter

func NewRequestFilter(f func(req *Request) *http.Response) RequestFilter

Helper to create a Filter by just passing in a func

   filter = NewRequestFilter(func(req *Request) *http.Response {
			req.Headers.Add("X-Falcore", "is_cool")
			return
		})

type ResponseFilter

type ResponseFilter interface {
	FilterResponse(req *Request, res *http.Response)
}

Filter outgoing responses. This can be used to modify the response before it is sent. Modifying the request at this point will have no effect.

func NewResponseFilter

func NewResponseFilter(f func(req *Request, res *http.Response)) ResponseFilter

Helper to create a Filter by just passing in a func

   filter = NewResponseFilter(func(req *Request, res *http.Response) {
			// some crazy response magic
			return
		})

type Route

type Route interface {
	// Returns the route's filter if there's a match.  nil if there isn't
	MatchString(str string) RequestFilter
}

Interface for defining individual routes

type Router

type Router interface {
	// Returns a Pipeline or nil if one can't be found
	SelectPipeline(req *Request) (pipe RequestFilter)
}

Interface for defining routers

func NewRouter

func NewRouter(f genericRouter) Router

Generate a new Router instance using f for SelectPipeline

type Server

type Server struct {
	Addr     string
	Pipeline *Pipeline

	AcceptReady chan int
	// contains filtered or unexported fields
}

func NewServer

func NewServer(port int, pipeline *Pipeline) *Server

func (*Server) FdListen

func (srv *Server) FdListen(fd int) error

func (*Server) ListenAndServe

func (srv *Server) ListenAndServe() error

func (*Server) ListenAndServeTLS

func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error

func (*Server) Port

func (srv *Server) Port() int

func (*Server) SocketFd

func (srv *Server) SocketFd() int

func (*Server) StopAccepting

func (srv *Server) StopAccepting()

type StdLibLogger

type StdLibLogger struct{}

This is a simple Logger implementation that uses the go log package for output. It's not really meant for production use since it isn't very configurable. It is a sane default alternative that allows us to not have any external dependencies. Use timber or log4go as a real alternative.

func (StdLibLogger) Critical

func (fl StdLibLogger) Critical(arg0 interface{}, args ...interface{}) error

func (StdLibLogger) Debug

func (fl StdLibLogger) Debug(arg0 interface{}, args ...interface{})

func (StdLibLogger) Error

func (fl StdLibLogger) Error(arg0 interface{}, args ...interface{}) error

func (StdLibLogger) Fine

func (fl StdLibLogger) Fine(arg0 interface{}, args ...interface{})

func (StdLibLogger) Finest

func (fl StdLibLogger) Finest(arg0 interface{}, args ...interface{})

func (StdLibLogger) Info

func (fl StdLibLogger) Info(arg0 interface{}, args ...interface{})

func (StdLibLogger) Log

func (fl StdLibLogger) Log(lvl level, arg0 interface{}, args ...interface{}) (e error)

func (StdLibLogger) Trace

func (fl StdLibLogger) Trace(arg0 interface{}, args ...interface{})

func (StdLibLogger) Warn

func (fl StdLibLogger) Warn(arg0 interface{}, args ...interface{}) error

type StringBody

type StringBody struct {
	BodyString string
	BodyBuffer *strings.Reader
}

func ReadRequestBody

func ReadRequestBody(r *http.Request) (sb *StringBody, err error)

reads the request body and replaces the buffer with self returns nil if the body is multipart and not replaced

func (*StringBody) Close

func (sb *StringBody) Close() error

func (*StringBody) Read

func (sb *StringBody) Read(b []byte) (n int, err error)

type StringBodyFilter

type StringBodyFilter struct{}

func (*StringBodyFilter) FilterRequest

func (sbf *StringBodyFilter) FilterRequest(request *Request) *http.Response

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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