cheshire

package
v0.0.0-...-9c67cfd Latest Latest
Warning

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

Go to latest
Published: Oct 15, 2013 License: MIT Imports: 23 Imported by: 24

Documentation

Index

Constants

View Source
const (
	//The partition val (an integer from 0 to TotalPartitions)
	PARAM_SHARD_PARTITION = "_p"

	PARAM_SHARD_KEY = "_k"

	// The version of the router table
	PARAM_SHARD_REVISION = "_v"

	//The query type.
	// This defines how the request can be handled by the router.
	// Possible values:
	// single : return a single result (the first response received)
	// all : (default) return values for all servers, will make an effort to retry on failure, but will generally return error results.
	// all_q : return values for all servers (queue requests if needed, retry until response).  This would typically be for posting
	// none_q : returns success immediately, queues the request and make best effort to ensure it is delivered (TODO)
	PARAM_SHARD_QUERY_TYPE = "_qt"
)

Special Param Names

View Source
const StrestVersion = float32(2)

what Strest protocol version we are using.

Variables

View Source
var BIN = &BinProtocol{}
View Source
var BINCONST = contstantsinit()
View Source
var CONTENT_ENCODING = []string{
	"string",
	"bytes",
	"json",
	"msqpack",
}
View Source
var JSON = &JSONProtocol{}
View Source
var METHOD = []string{
	"GET",
	"POST",
	"PUT",
	"DELETE",
}
View Source
var PARAM_ENCODING = []string{
	"json",
	"msgpack",
}
View Source
var TXN_ACCEPT = []string{
	"single",
	"multi",
}
View Source
var TXN_STATUS = []string{
	"completed",
	"continue",
}

Functions

func BinaryListen

func BinaryListen(port int, config *ServerConfig) error

func CopyByteArray

func CopyByteArray(dest io.Writer, src io.Reader) error

copies a length prefixed byte array from the src to the dest.

func CopyByteArray32

func CopyByteArray32(dest io.Writer, src io.Reader) error

copies a byte array with a int32 length

func CopyN

func CopyN(dst io.Writer, src io.Reader, bytes int64) (err error)

Copies N bytes to the writer from the reader, hopefully faster then the fucked up way in the stdlib

func Flash

func Flash(txn *Txn, severity, message string)

func HandleRequest

func HandleRequest(request *Request, conn Writer, controller Controller, serverConfig *ServerConfig)

Implements the handle request, does the full filter stack.

func HttpListen

func HttpListen(port int, serverConfig *ServerConfig) error

func JSONEncodeString

func JSONEncodeString(s string) (string, error)

Json quotes and escapes a string. Modified and taken from the json encoding standard lib

func JsonListen

func JsonListen(port int, config *ServerConfig) error

func NewTxnId

func NewTxnId() string

create a new unique strest txn id

func ParseParams

func ParseParams(paramEncoding int8, params []byte) (*dynmap.DynMap, error)

func PingController

func PingController(txn *Txn)

A default ping controller

func RandString

func RandString(length int) string

func ReadByteArray

func ReadByteArray(reader io.Reader) ([]byte, error)

Reads a length prefixed byte array it assumes the first

func ReadByteArray32

func ReadByteArray32(reader io.Reader) ([]byte, error)

Reads a length prefixed byte array it assumes the first

func ReadHttpBody

func ReadHttpBody(req *http.Request) ([]byte, error)

reads the whole body of an http request

func ReadString

func ReadString(reader io.Reader) (string, error)

Reads a length prefixed utf8 string

func Redirect

func Redirect(txn *Txn, url string)

Issues a redirect (301) to the url

func Register

func Register(methods []string, controller Controller)

Registers a new controller

func RegisterApi

func RegisterApi(route string, method string, handler func(*Txn), filters ...ControllerFilter)

Registers a controller funtion for api calls

func RegisterHtml

func RegisterHtml(route string, method string, handler func(*Txn), filters ...ControllerFilter)

Registers a controller function for html pages

func Render

func Render(txn *Txn, path string, context map[string]interface{})

func RenderInLayout

func RenderInLayout(txn *Txn, path, layoutPath string, context map[string]interface{})

Renders with a layout template.

Layout should have {{content}} variable

func SendError

func SendError(txn *Txn, code int, message string) (int, error)

Sends an error response to the channel

func SendSuccess

func SendSuccess(txn *Txn)

sends a standard 200 success response. will close the current transaction

func SessionId

func SessionId() string

returns a unique session id

func WriteByteArray

func WriteByteArray(writer io.Writer, bytes []byte) (int, error)

writes a length prefixed byte array

func WriteByteArray32

func WriteByteArray32(writer io.Writer, bytes []byte) (int, error)

writes a length int32 prefixed byte array

func WriteString

func WriteString(writer io.Writer, str string) (int, error)

writes a length prefixed utf8 string

Types

type BinConstants

type BinConstants struct {
	TxnAccept       map[string]int8
	TxnStatus       map[string]int8
	Method          map[string]int8
	ParamEncoding   map[string]int8
	ContentEncoding map[string]int8
}

type BinDecoder

type BinDecoder struct {

	//The fields decoded from the hello
	Hello *dynmap.DynMap
	// contains filtered or unexported fields
}

func (*BinDecoder) DecodeHello

func (this *BinDecoder) DecodeHello() (*dynmap.DynMap, error)

func (*BinDecoder) DecodeRequest

func (this *BinDecoder) DecodeRequest() (*Request, error)

decode the next request from the reader

func (*BinDecoder) DecodeResponse

func (this *BinDecoder) DecodeResponse() (*Response, error)

Decode the next response from the reader

func (*BinDecoder) DecodeShardRequest

func (this *BinDecoder) DecodeShardRequest() (*ShardRequest, error)

read a shard request from the socket.

type BinProtocol

type BinProtocol struct {
}

Implementation of the binary protocol

func (*BinProtocol) NewDecoder

func (this *BinProtocol) NewDecoder(reader io.Reader) Decoder

func (*BinProtocol) Type

func (this *BinProtocol) Type() string

func (*BinProtocol) WriteHello

func (this *BinProtocol) WriteHello(writer io.Writer, hello *dynmap.DynMap) error

Say hello

func (*BinProtocol) WriteRequest

func (this *BinProtocol) WriteRequest(request *Request, writer io.Writer) (int, error)

func (*BinProtocol) WriteResponse

func (this *BinProtocol) WriteResponse(response *Response, writer io.Writer) (int, error)

func (*BinProtocol) WriteShardRequest

func (this *BinProtocol) WriteShardRequest(s *ShardRequest, writer io.Writer) error

write out the shard request.

type BinaryWriter

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

func (*BinaryWriter) Type

func (this *BinaryWriter) Type() string

func (*BinaryWriter) Write

func (this *BinaryWriter) Write(response *Response) (int, error)

type Bootstrap

type Bootstrap struct {
	Conf *ServerConfig
}

func NewBootstrap

func NewBootstrap(config *ServerConfig) *Bootstrap

func NewBootstrapFile

func NewBootstrapFile(configPath string) *Bootstrap

func NewExtendedBootstrap

func NewExtendedBootstrap(configPath string, extentions []func(conf *ServerConfig)) *Bootstrap

func (*Bootstrap) AddFilters

func (this *Bootstrap) AddFilters(filters ...ControllerFilter)

func (*Bootstrap) InitControllers

func (this *Bootstrap) InitControllers()

func (*Bootstrap) InitProcs

func (this *Bootstrap) InitProcs()

func (*Bootstrap) InitStaticFiles

func (this *Bootstrap) InitStaticFiles()

this needs to be setup correctly to key off of the config yaml

func (*Bootstrap) InitWebSockets

func (this *Bootstrap) InitWebSockets()

func (*Bootstrap) RunInitMethods

func (this *Bootstrap) RunInitMethods(target interface{})

Runs All methods that have prefix of Init

func (*Bootstrap) Start

func (this *Bootstrap) Start()

starts listening in all the configured listeners this method does not return until all listeners exit (i.e. never).

type Cache

type Cache interface {
	Set(key string, value []byte, expireSeconds int)

	// Sets the value if and only if there is no value associated with this key
	SetIfAbsent(key string, value []byte, expireSeconds int) bool

	// Deletes the value at the requested key
	Delete(key string)

	// Gets the value at the requested key
	Get(key string) ([]byte, bool)

	// Increment the key by val (val is allowed to be negative)
	// in most implementation expireSeconds will be from the first increment, but users should not count on that.
	// if no value is a present it should be added.
	// If a value is present which is not a number an error should be returned.
	Inc(key string, val int64, expireSeconds int) (int64, error)
}

A generic cache.

type Controller

type Controller interface {
	Config() *ControllerConfig
	HandleRequest(*Txn)
}

a Controller object

type ControllerConfig

type ControllerConfig struct {
	Route   string
	Filters []ControllerFilter
}

Configuration for a specific controller.

func NewControllerConfig

func NewControllerConfig(route string) *ControllerConfig

type ControllerFilter

type ControllerFilter interface {
	//This is called before the Controller is called.
	//returning false will stop the execution
	Before(*Txn) bool
}

Hooks to hook into before and after the controller execution.

type Decoder

type Decoder interface {
	//decode the initial hello (bin only)
	DecodeHello() (*dynmap.DynMap, error)

	//Decode the next response from the reader
	DecodeResponse() (*Response, error)

	//decode the next request from the reader
	DecodeRequest() (*Request, error)
}

type DefaultController

type DefaultController struct {
	Handlers map[string]func(*Txn)
	Conf     *ControllerConfig
}

func NewController

func NewController(route string, methods []string, handler func(*Txn)) *DefaultController

creates a new controller for the specified route for a specific method types (GET, POST, PUT, ect)

func NewControllerAll

func NewControllerAll(route string, handler func(*Txn)) *DefaultController

creates a new controller that will process all method types

func (*DefaultController) Config

func (this *DefaultController) Config() *ControllerConfig

func (*DefaultController) HandleRequest

func (this *DefaultController) HandleRequest(txn *Txn)

type DefaultNotFoundHandler

type DefaultNotFoundHandler struct {
}

func (*DefaultNotFoundHandler) Config

func (*DefaultNotFoundHandler) HandleRequest

func (h *DefaultNotFoundHandler) HandleRequest(txn *Txn)

type FilterAdvanced

type FilterAdvanced interface {
	ControllerFilter

	//Called immediately before the response is written.
	BeforeWrite(*Response, *Txn)

	//This is called after the controller is called.
	//The response has already been sent
	AfterWrite(*Response, *Txn)
}

Additional hooks if you need more granularity into the lifecycle

type Flusher

type Flusher interface {
	Flush() error
}

type HtmlController

type HtmlController struct {
	Handlers map[string]func(*Txn)
	Conf     *ControllerConfig
}

func NewHtmlController

func NewHtmlController(route string, methods []string, handler func(*Txn)) *HtmlController

func (*HtmlController) Config

func (this *HtmlController) Config() *ControllerConfig

func (*HtmlController) HandleRequest

func (this *HtmlController) HandleRequest(txn *Txn)

func (*HtmlController) HttpHijack

func (this *HtmlController) HttpHijack(writer http.ResponseWriter, req *http.Request, serverConfig *ServerConfig)

We hijack the request so we can use the html writer instead of the regular http writer. mostly this is so the filters know this is of type="html"

type HtmlFilter

type HtmlFilter interface {
	ControllerFilter

	//Allows you to hook in before anything is writen.
	//makes it possible to
	//set headers cookies, ect.
	BeforeHtmlWrite(txn *Txn, writer http.ResponseWriter) bool
}

Special filter for html lifecycle

type HtmlWriter

type HtmlWriter struct {
	*HttpWriter
}

func (*HtmlWriter) Type

func (this *HtmlWriter) Type() string

type HttpHijacker

type HttpHijacker interface {
	HttpHijack(writer http.ResponseWriter, req *http.Request, serverConfig *ServerConfig)
}

Implement this interface for a controller to skip the normal cheshire life cycle This should be only used in special cases (static file serving, websockets, ect) controllers that implement this interface will skip the HandleRequest function alltogether

type HttpWriter

type HttpWriter struct {
	Writer       http.ResponseWriter
	HttpRequest  *http.Request
	Request      *Request
	ServerConfig *ServerConfig
	// contains filtered or unexported fields
}

func ToHttpWriter

func ToHttpWriter(txn *Txn) (*HttpWriter, error)

func (*HttpWriter) Type

func (this *HttpWriter) Type() string

func (*HttpWriter) Write

func (conn *HttpWriter) Write(response *Response) (int, error)

type JSONDecoder

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

func (*JSONDecoder) DecodeHello

func (this *JSONDecoder) DecodeHello() (*dynmap.DynMap, error)

func (*JSONDecoder) DecodeRequest

func (this *JSONDecoder) DecodeRequest() (*Request, error)

func (*JSONDecoder) DecodeResponse

func (this *JSONDecoder) DecodeResponse() (*Response, error)

type JSONProtocol

type JSONProtocol struct {
}

///////////////////// The JSON protocol implementation /////////////////////

func (*JSONProtocol) NewDecoder

func (this *JSONProtocol) NewDecoder(reader io.Reader) Decoder

func (*JSONProtocol) Type

func (this *JSONProtocol) Type() string

func (*JSONProtocol) WriteHello

func (this *JSONProtocol) WriteHello(writer io.Writer, hello *dynmap.DynMap) error

func (*JSONProtocol) WriteRequest

func (this *JSONProtocol) WriteRequest(request *Request, writer io.Writer) (int, error)

func (*JSONProtocol) WriteResponse

func (this *JSONProtocol) WriteResponse(response *Response, writer io.Writer) (int, error)

type JsonWriter

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

func (*JsonWriter) Type

func (this *JsonWriter) Type() string

func (*JsonWriter) Write

func (this *JsonWriter) Write(response *Response) (int, error)

type Protocol

type Protocol interface {
	NewDecoder(io.Reader) Decoder
	//Say hello on first connection (bin only)
	WriteHello(io.Writer, *dynmap.DynMap) error
	WriteResponse(*Response, io.Writer) (int, error)
	WriteRequest(*Request, io.Writer) (int, error)
	Type() string
}

type Request

type Request struct {
	Shard *ShardRequest
	// contains filtered or unexported fields
}

Standard STREST request. See protocol spec https://github.com/trendrr/strest-server/wiki/STREST-Protocol-Spec

func NewRequest

func NewRequest(uri, method string) *Request

Create a new request object. Values are all set to defaults

func NewRequestDynMap

func NewRequestDynMap(mp *dynmap.DynMap) *Request

creates a new request from a dynmap

func ToStrestRequest

func ToStrestRequest(req *http.Request) *Request

func (*Request) Content

func (this *Request) Content() ([]byte, bool)

func (*Request) ContentEncoding

func (this *Request) ContentEncoding() (string, bool)

returns the current content encoding,

func (*Request) ContentIsSet

func (this *Request) ContentIsSet() bool

func (*Request) MarshalJSON

func (this *Request) MarshalJSON() ([]byte, error)

func (*Request) Method

func (this *Request) Method() string

func (*Request) Params

func (this *Request) Params() *dynmap.DynMap

func (*Request) SetContent

func (this *Request) SetContent(contentEncoding string, content []byte)

func (*Request) SetMethod

func (this *Request) SetMethod(method string)

func (*Request) SetParams

func (this *Request) SetParams(params *dynmap.DynMap)

func (*Request) SetTxnAccept

func (this *Request) SetTxnAccept(accept string)

Set to either "single" or "multi"

func (*Request) SetTxnAcceptMulti

func (this *Request) SetTxnAcceptMulti()

This request will accept multiple responses

func (*Request) SetTxnAcceptSingle

func (this *Request) SetTxnAcceptSingle()

This request will only accept a single response

func (*Request) SetTxnId

func (this *Request) SetTxnId(id string)

func (*Request) SetUri

func (this *Request) SetUri(uri string)

func (*Request) StrestVersion

func (this *Request) StrestVersion() float32

func (*Request) ToDynMap

func (this *Request) ToDynMap() *dynmap.DynMap

Creates a new dynmap with all the appropriate fields This is here for compatibility, but is rather inefficient

func (*Request) TxnAccept

func (this *Request) TxnAccept() string

func (*Request) TxnId

func (this *Request) TxnId() string

return the txnid.

func (*Request) Uri

func (this *Request) Uri() string

func (*Request) UserAgent

func (this *Request) UserAgent() string

type RequestTxnId

type RequestTxnId interface {
	TxnId() string
}

Makes it simple to create a new response from anything implementing this interface

type Response

type Response struct {
	dynmap.DynMap
	// contains filtered or unexported fields
}

Standard STREST response See protocol spec https://github.com/trendrr/strest-server/wiki/STREST-Protocol-Spec

func NewError

func NewError(txn RequestTxnId, code int, message string) *Response

func NewResponse

func NewResponse(txn RequestTxnId) *Response

Creates a new response based on this request txn. auto fills the txn id

func NewResponseDynMap

func NewResponseDynMap(mp *dynmap.DynMap) *Response

creates a new response from a dynmap

func (*Response) Content

func (this *Response) Content() ([]byte, bool)

func (*Response) ContentEncoding

func (this *Response) ContentEncoding() (string, bool)

returns the current content encoding,

func (*Response) ContentIsSet

func (this *Response) ContentIsSet() bool

func (*Response) MarshalJSON

func (this *Response) MarshalJSON() ([]byte, error)

func (*Response) SetContent

func (this *Response) SetContent(contentEncoding string, content []byte)

func (*Response) SetStatus

func (this *Response) SetStatus(code int, message string)

func (*Response) SetStatusCode

func (this *Response) SetStatusCode(code int)

func (*Response) SetStatusMessage

func (this *Response) SetStatusMessage(message string)

func (*Response) SetTxnComplete

func (this *Response) SetTxnComplete()

func (*Response) SetTxnContinue

func (this *Response) SetTxnContinue()

func (*Response) SetTxnId

func (this *Response) SetTxnId(id string)

func (*Response) SetTxnStatus

func (this *Response) SetTxnStatus(status string)

completed or continue

func (*Response) StatusCode

func (this *Response) StatusCode() int

func (*Response) StatusMessage

func (this *Response) StatusMessage() string

func (*Response) StrestVersion

func (this *Response) StrestVersion() float32

func (*Response) ToDynMap

func (this *Response) ToDynMap() *dynmap.DynMap

func (*Response) TxnComplete

func (this *Response) TxnComplete() bool

func (*Response) TxnContinue

func (this *Response) TxnContinue() bool

func (*Response) TxnId

func (this *Response) TxnId() string

func (*Response) TxnStatus

func (this *Response) TxnStatus() string

type RouteMatcher

type RouteMatcher interface {
	// A controller matches the given method, path
	Match(string, string) Controller
	// Registers a controller for the specified methods
	Register([]string, Controller)
}

The Cheshire Router, translates between a uri + method to a controller

type Router

type Router struct {
	NotFoundHandler Controller
	// contains filtered or unexported fields
}

This is a default implementation of a cheshire Router. it is based on the HTTP request multiplexer from golang sources: http://golang.org/src/pkg/net/http/server.go?s=25470:25535#L841

Patterns name fixed, rooted paths, like "/favicon.ico", or rooted subtrees, like "/images/" (note the trailing slash). Longer patterns take precedence over shorter ones, so that if there are handlers registered for both "/images/" and "/images/thumbnails/", the latter handler will be called for paths beginning "/images/thumbnails/" and the former will receive requests for any other paths in the "/images/" subtree.

Should also takes care of sanitizing the URL request path, redirecting any request containing . or .. elements to an equivalent .- and ..-free URL.

func NewDefaultRouter

func NewDefaultRouter() *Router

NewServeMux allocates and returns a new CheshireMux.

func (*Router) Match

func (mux *Router) Match(method string, path string) (h Controller)

Match returns the registered Controller that matches the request or, if no match the registered not found handler is returned

func (*Router) Register

func (this *Router) Register(methods []string, handler Controller)

Handle registers the handler for the given pattern. If a handler already exists for pattern, Handle panics.

type ServerConfig

type ServerConfig struct {
	*dynmap.DynMap
	Router  RouteMatcher
	Filters []ControllerFilter
}

func NewServerConfig

func NewServerConfig() *ServerConfig

Creates a new server config with a default routematcher

func NewServerConfigFile

func NewServerConfigFile(path string) *ServerConfig

Parses a server config from a YAML file

func (*ServerConfig) Register

func (this *ServerConfig) Register(methods []string, controller Controller)

Registers a controller with the RouteMatcher. shortcut to conf.Router.Register(controller)

type Session

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

func NewSession

func NewSession(cache Cache, sessionMaxSeconds int) *Session

func (*Session) Before

func (this *Session) Before(txn *Txn) bool

This is called before the Controller is called. returning false will stop the execution

func (*Session) BeforeHtmlWrite

func (this *Session) BeforeHtmlWrite(txn *Txn, writer http.ResponseWriter) bool

type ShardRequest

type ShardRequest struct {
	Partition int
	Key       string
	Revision  int64
}

type StaticFileController

type StaticFileController struct {
	Route   string
	Path    string
	Conf    *ControllerConfig
	Handler http.Handler
}

Allows us to use the fast static file handler built into golang standard lib Note that this skips the cheshire lifecycle so no middleware filters will be executed.

func NewStaticFileController

func NewStaticFileController(route string, path string) *StaticFileController

initial the handler via http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp")))

func (*StaticFileController) Config

func (this *StaticFileController) Config() *ControllerConfig

func (*StaticFileController) HandleRequest

func (this *StaticFileController) HandleRequest(txn *Txn)

func (*StaticFileController) HttpHijack

func (this *StaticFileController) HttpHijack(writer http.ResponseWriter, req *http.Request, serverConfig *ServerConfig)

type Txn

type Txn struct {
	Request *Request

	//writer should be threadsafe
	Writer Writer

	//Session is not currently threadsafe
	Session *dynmap.DynMap

	//The filters that will be run on this txn
	Filters []ControllerFilter

	//the immutable server config
	ServerConfig *ServerConfig
}

Represents a single transaction. This wraps the underlying Writer, and allows saving of session state ect.

func NewTxn

func NewTxn(request *Request, writer Writer, filters []ControllerFilter, serverConfig *ServerConfig) *Txn

func (*Txn) Params

func (this *Txn) Params() *dynmap.DynMap

func (*Txn) TxnId

func (this *Txn) TxnId() string

func (*Txn) Type

func (this *Txn) Type() string

Returns the connection type. currently will be one of http,html,json,websocket

func (*Txn) Write

func (this *Txn) Write(response *Response) (int, error)

Writes a response to the underlying writer.

type WebsocketController

type WebsocketController struct {
	Conf    *ControllerConfig
	Handler websocket.Handler
	// contains filtered or unexported fields
}

func NewWebsocketController

func NewWebsocketController(route string, config *ServerConfig) *WebsocketController

func (WebsocketController) Config

func (WebsocketController) HandleRequest

func (wc WebsocketController) HandleRequest(txn *Txn)

func (*WebsocketController) HandleWCConnection

func (this *WebsocketController) HandleWCConnection(ws *websocket.Conn)

func (*WebsocketController) HttpHijack

func (this *WebsocketController) HttpHijack(writer http.ResponseWriter, req *http.Request, serverConfig *ServerConfig)

implements the HttpHijacker interface so we can handle the request directly.

type WebsocketWriter

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

func (*WebsocketWriter) Type

func (this *WebsocketWriter) Type() string

func (*WebsocketWriter) Write

func (this *WebsocketWriter) Write(response *Response) (int, error)

type Writer

type Writer interface {
	//writes the response to the underlying channel
	// i.e. either to an http response writer or json socket.
	// implementers should make sure that this method is threadsafe as the
	// Writer may be shared across go routines.
	Write(*Response) (int, error)

	//What type of writer is this?
	//Examples: http,json,websocket
	Type() string
}

Directories

Path Synopsis
impl

Jump to

Keyboard shortcuts

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