gotham

package module
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Jun 10, 2022 License: MIT Imports: 24 Imported by: 2

README

gotham

Build Status Go Report Card codecov

A well-tested/high-performace tcp/protobuf router written in go, highly inspired by Gin, and the source of standard http library:net/http/server.go.

content

Installation

To install gotham package, you need to install Go and set your Go workspace first.

  1. The first need Go installed (version 1.11+ is required), then you can use the below Go command to install Gotham.
$ go get -u github.com/sleep2death/gotham
  1. Import it in your code:
import "github.com/sleep2death/gotham"

Quick start

All examples you can find are in /examples folder.

package main

import (
	"log"
	"net/http"

	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/ptypes"

	"github.com/sleep2death/gotham"
	"github.com/sleep2death/gotham/examples/pb"
)

func main() {
	// SERVER
	// Starts a new gotham instance without any middleware attached.
	router := gotham.New()

	// Define your handlers.
	router.Handle("/pb/EchoMessage", func(c *gotham.Context) {
		message := new(pb.EchoMessage)

		// If some error fires, you can abort the request.
		if err := proto.Unmarshal(c.Data(), message); err != nil {
			c.AbortWithStatus(http.StatusBadRequest)
			return
		}

		// log.Printf("Ping request received at %s", ptypes.TimestampString(message.Ts))
		message.Message = "Pong"
		message.Ts = ptypes.TimestampNow()
		c.Write(message)
	})

	// Run, gotham, Run...
	addr := ":9090"
	log.Fatal(router.Run(addr))
}

Documentation

Index

Constants

View Source
const (
	// DebugMode indicates gotham mode is debug.
	DebugMode = "debug"
	// ReleaseMode indicates gotham mode is release.
	ReleaseMode = "release"
	// TestMode indicates gotham mode is test.
	TestMode = "test"
)

Variables

View Source
var (
	ErrEmptyURL  = errors.New("empty url")
	ErrEmptyData = errors.New("empty data")
)

ErrServerClosed is returned by the Server's Serve,

View Source
var DebugPrintRouteFunc func(absolutePath, handlerName string, nuHandlers int)

DebugPrintRouteFunc indicates debug log output format.

View Source
var DefaultErrorWriter io.Writer = os.Stderr
View Source
var DefaultWriter io.Writer = os.Stdout
View Source
var ErrFrameFlags = errors.New("tcp: frame flags error")

ErrFrameFlags is returned from ReadFrame when Flags.has returned false

View Source
var ErrFrameTooLarge = errors.New("tcp: frame too large")

ErrFrameTooLarge is returned from Framer.ReadFrame when the peer sends a frame that is larger than declared with SetMaxReadFrameSize.

View Source
var ErrHybridPath error = errors.New("hybrid type path is not allowed.")
View Source
var (
	ErrNotFlusher = errors.New("this writer is not a flusher")
)
View Source
var ErrServerClosed = errors.New("tcp: Server closed")

ErrServerClosed is returned by the Server's Serve,

Functions

func DefaultNoRouteHandler

func DefaultNoRouteHandler(c *Context)

func DisableConsoleColor

func DisableConsoleColor()

DisableConsoleColor disables color output in the console.

func ForceConsoleColor

func ForceConsoleColor()

ForceConsoleColor force color output in the console.

func IsDebugging

func IsDebugging() bool

IsDebugging returns true if the framework is running in debug mode. Use SetMode(gotham.ReleaseMode) to disable debug mode.

func ListenAndServe

func ListenAndServe(addr string, handler Handler, codec Codec) error

func NewResponseWriter

func NewResponseWriter(w io.Writer, c Codec) *responseWriter

func SetMode

func SetMode(value string)

SetMode sets gotham mode according to input string.

func WriteData

func WriteData(w io.Writer, data []byte) (err error)

WriteData with the payload.

func WriteFrame

func WriteFrame(w io.Writer, data interface{}, codec Codec) error

WriteFrame with given url

Types

type BufFlusher

type BufFlusher interface {
	// Flush writes any buffered data to the underlying io.Writer.
	Flush() error

	// Returns the number of bytes already written into the response.
	// See Written()
	Buffered() int
}

type Codec

type Codec interface {
	Marshal(v interface{}) ([]byte, error)
	Unmarshal(data []byte, req *Request) error
}

type ConnState

type ConnState int

A ConnState represents the state of a client connection to a server.

const (
	// StateNew represents a new connection that is expected to
	StateNew ConnState = iota

	// StateActive represents a connection that has read 1 or more
	StateActive

	// StateIdle represents a connection that has finished
	StateIdle

	// StateClosed represents a closed connection.
	StateClosed
)

func (ConnState) String

func (c ConnState) String() string

type Context

type Context struct {

	// Keys is a key/value pair exclusively for the context of each request.
	Keys map[string]interface{}

	// Errors is a list of Errors attached to all the handlers/middlewares who used this context.
	Errors errorMsgs

	Writer  ResponseWriter
	Request *Request
	// contains filtered or unexported fields
}

Context is the most important part of gamerouter. It allows us to pass variables between middleware, manage the flow, validate the JSON of a request and render a JSON response for example.

func (*Context) Abort

func (c *Context) Abort()

Abort prevents pending handlers from being called. Note that this will not stop the current handler. Let's say you have an authorization middleware that validates that the current request is authorized. If the authorization fails (ex: the password does not match), call Abort to ensure the remaining handlers for this request are not called.

func (*Context) AbortWithStatus

func (c *Context) AbortWithStatus(code int)

func (*Context) Error

func (c *Context) Error(err error) *Error

Error attaches an error to the current context. The error is pushed to a list of errors. It's a good idea to call Error for each error that occurred during the resolution of a request. A middleware can be used to collect all the errors and push them to a database together, print a log, or append it in the HTTP response. Error will panic if err is nil.

func (*Context) Get

func (c *Context) Get(key string) (value interface{}, exists bool)

Get returns the value for the given key, ie: (value, true). If the value does not exists it returns (nil, false)

func (*Context) GetBool

func (c *Context) GetBool(key string) (b bool)

GetBool returns the value associated with the key as a boolean.

func (*Context) GetDuration

func (c *Context) GetDuration(key string) (d time.Duration)

GetDuration returns the value associated with the key as a duration.

func (*Context) GetFloat64

func (c *Context) GetFloat64(key string) (f64 float64)

GetFloat64 returns the value associated with the key as a float64.

func (*Context) GetInt

func (c *Context) GetInt(key string) (i int)

GetInt returns the value associated with the key as an integer.

func (*Context) GetInt64

func (c *Context) GetInt64(key string) (i64 int64)

GetInt64 returns the value associated with the key as an integer.

func (*Context) GetString

func (c *Context) GetString(key string) (s string)

GetString returns the value associated with the key as a string.

func (*Context) GetStringMap

func (c *Context) GetStringMap(key string) (sm map[string]interface{})

GetStringMap returns the value associated with the key as a map of interfaces.

func (*Context) GetStringMapString

func (c *Context) GetStringMapString(key string) (sms map[string]string)

GetStringMapString returns the value associated with the key as a map of strings.

func (*Context) GetStringMapStringSlice

func (c *Context) GetStringMapStringSlice(key string) (smss map[string][]string)

GetStringMapStringSlice returns the value associated with the key as a map to a slice of strings.

func (*Context) GetStringSlice

func (c *Context) GetStringSlice(key string) (ss []string)

GetStringSlice returns the value associated with the key as a slice of strings.

func (*Context) GetTime

func (c *Context) GetTime(key string) (t time.Time)

GetTime returns the value associated with the key as time.

func (*Context) Handler

func (c *Context) Handler() HandlerFunc

Handler returns the main handler.

func (*Context) HandlerName

func (c *Context) HandlerName() string

HandlerName returns the main handler's name. For example if the handler is "handleGetUsers()", this function will return "main.handleGetUsers".

func (*Context) HandlerNames

func (c *Context) HandlerNames() []string

HandlerNames returns a list of all registered handlers for this context in descending order, following the semantics of HandlerName()

func (*Context) IsAborted

func (c *Context) IsAborted() bool

IsAborted returns true if the current context was aborted.

func (*Context) MustGet

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

MustGet returns the value for the given key if it exists, otherwise it panics.

func (*Context) Next

func (c *Context) Next()

Next should be used only inside middleware. It executes the pending handlers in the chain inside the calling handler. See example in GitHub.

func (*Context) Set

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

Set is used to store a new key/value pair exclusively for this context. It also lazy initializes c.Keys if it was not used previously.

func (*Context) Write

func (c *Context) Write(msg interface{}) error

Write message to connection

type Error

type Error struct {
	Err  error
	Type ErrorType
	Meta interface{}
}

Error represents a error's specification.

func (Error) Error

func (msg Error) Error() string

Error implements the error interface.

func (*Error) IsType

func (msg *Error) IsType(flags ErrorType) bool

IsType judges one error.

func (*Error) SetMeta

func (msg *Error) SetMeta(data interface{}) *Error

SetMeta sets the error's meta data.

func (*Error) SetType

func (msg *Error) SetType(flags ErrorType) *Error

SetType sets the error's type.

type ErrorType

type ErrorType uint64

ErrorType is an unsigned 64-bit error code as defined in the gotham spec.

const (
	// ErrorTypePrivate indicates a private error.
	ErrorTypePrivate ErrorType = 1 << 0
	// ErrorTypePublic indicates a public error.
	ErrorTypePublic ErrorType = 1 << 1
	// ErrorTypeAny indicates any other error.
	ErrorTypeAny ErrorType = 1<<64 - 1
)

type Flags

type Flags uint8

Flags is a bitmask of HTTP/2 flags. The meaning of flags varies depending on the frame type.

const (
	// check flag for validating the frame
	FlagFrameAck Flags = 0x10
)

Frame-specific FrameHeader flag bits.

func (Flags) Has

func (f Flags) Has(v Flags) bool

Has reports whether f contains all (0 or more) flags in v.

type FlatbuffersCodec

type FlatbuffersCodec struct {
}

func (*FlatbuffersCodec) Marshal

func (pc *FlatbuffersCodec) Marshal(data interface{}) ([]byte, error)

func (*FlatbuffersCodec) Unmarshal

func (pc *FlatbuffersCodec) Unmarshal(data []byte, req *Request) error

type FrameHeader

type FrameHeader struct {
	// Type is the 1 byte frame type.
	Type FrameType
	// Flags are the 1 byte of 8 potential bit flags per frame.
	// They are specific to the frame type.
	Flags Flags
	// Length is the length of the frame, not including the 9 byte header.
	// The maximum size is one byte less than 16MB (uint24), but only
	// frames up to 16KB are allowed without peer agreement.
	Length uint32
}

FrameHeader store the reading data header

func ReadFrameHeader

func ReadFrameHeader(r io.Reader) (FrameHeader, error)

ReadFrameHeader from the io reader.

type FrameType

type FrameType uint8

A FrameType is a registered frame type as defined in http://http2.github.io/http2-spec/#rfc.section.11.2

const (
	// FrameData type
	FrameData FrameType = 0x0
	// FrameSettings type
	FrameSettings FrameType = 0x1
	// FramePing type
	FramePing FrameType = 0x2
)

func (FrameType) String

func (t FrameType) String() string

type Handler

type Handler interface {
	ServeProto(ResponseWriter, *Request)
}

type HandlerFunc

type HandlerFunc func(*Context)

HandlerFunc defines the handler used by gamerouter middleware as return value.

func Logger

func Logger() HandlerFunc

Logger instances a Logger middleware that will write the logs to gotham.DefaultWriter. By default gotham.DefaultWriter = os.Stdout.

func LoggerWithConfig

func LoggerWithConfig(conf LoggerConfig) HandlerFunc

LoggerWithConfig instance a Logger middleware with config.

func LoggerWithFormatter

func LoggerWithFormatter(f LogFormatter) HandlerFunc

LoggerWithFormatter instance a Logger middleware with the specified log format function.

func LoggerWithWriter

func LoggerWithWriter(out io.Writer, notlogged ...string) HandlerFunc

LoggerWithWriter instance a Logger middleware with the specified writer buffer. Example: os.Stdout, a file opened in write mode, a socket...

func Recovery

func Recovery() HandlerFunc

Recovery returns a middleware that recovers from any panics and writes a 500 if there was one.

func RecoveryWithWriter

func RecoveryWithWriter(out io.Writer) HandlerFunc

RecoveryWithWriter returns a middleware for a given writer that recovers from any panics and writes a 500 if there was one.

type HandlersChain

type HandlersChain []HandlerFunc

HandlersChain defines a HandlerFunc array.

func (HandlersChain) Last

func (c HandlersChain) Last() HandlerFunc

Last returns the last handler in the chain. ie. the last handler is the main one.

type IHandlers

type IHandlers interface {
	Handlers() HandlersChain
	Name() string
}

IHandlers defines all routers which have handlers, and a unique name .

type IRoutes

type IRoutes interface {
	Handle(string, ...HandlerFunc) IRoutes
	Use(...HandlerFunc) IRoutes
}

IRoutes defines all router handle interface.

type LogFormatter

type LogFormatter func(params LogFormatterParams) string

LogFormatter gives the signature of the formatter function passed to LoggerWithFormatter

type LogFormatterParams

type LogFormatterParams struct {
	Request *Request

	// TimeStamp shows the time after the server returns a response.
	TimeStamp time.Time
	// StatusCode is HTTP response code.
	StatusCode int
	// Latency is how much time the server cost to process a certain request.
	Latency time.Duration
	// ClientIP equals Context's ClientIP method.
	ClientIP string
	// Path is a path the client requests.
	Path string
	// ErrorMessage is set if error has occurred in processing the request.
	ErrorMessage string

	// MessageSize is the size of the protobuf message
	MessageSize int
	// Keys are the keys set on the request's context.
	Keys map[string]interface{}
	// contains filtered or unexported fields
}

LogFormatterParams is the structure any formatter will be handed when time to log comes

func (*LogFormatterParams) IsOutputColor

func (p *LogFormatterParams) IsOutputColor() bool

IsOutputColor indicates whether can colors be outputted to the log.

func (*LogFormatterParams) ResetColor

func (p *LogFormatterParams) ResetColor() string

ResetColor resets all escape attributes.

func (*LogFormatterParams) StatusCodeColor

func (p *LogFormatterParams) StatusCodeColor() string

StatusCodeColor is the ANSI color for appropriately logging http status code to a terminal.

type LoggerConfig

type LoggerConfig struct {
	// Optional. Default value is gotham.defaultLogFormatter
	Formatter LogFormatter

	// Output is a writer where logs are written.
	// Optional. Default value is gotham.DefaultWriter.
	Output io.Writer

	// SkipPaths is a url path array which logs are not written.
	// Optional.
	SkipPaths []string
}

LoggerConfig defines the config for Logger middleware.

type ProtobufCodec

type ProtobufCodec struct {
}

func (*ProtobufCodec) Marshal

func (pc *ProtobufCodec) Marshal(data interface{}) ([]byte, error)

func (*ProtobufCodec) Unmarshal

func (pc *ProtobufCodec) Unmarshal(data []byte, req *Request) error

type Request

type Request struct {
	TypeURL string
	Data    interface{}
	// contains filtered or unexported fields
}

Request wrap the connection and other userful information of the client's request

func ReadFrame

func ReadFrame(r io.Reader, codec Codec) (*Request, error)

... for test only

func ReadFrameBody

func ReadFrameBody(r io.Reader, fh FrameHeader, codec Codec) (req *Request, err error)

ReadFrameBody from the io reader and frame header it will return a request if succeed

func (*Request) RemoteAddr

func (req *Request) RemoteAddr() string

type ResponseWriter

type ResponseWriter interface {
	BufFlusher

	// Set the response status code of the current request.
	SetStatus(statusCode int)

	// Returns the response status code of the current request.
	Status() int

	// Returns false if the server should close the connection after flush the data.
	KeepAlive() bool

	// Returns false if the server should close the connection after flush the data.
	SetKeepAlive(value bool)

	// Write the data into sending buffer.
	Write(data interface{}) error
}

ResponseWriter interface is used by a handler to construct an protobuf response.

type RouteInfo

type RouteInfo struct {
	Path        string
	Handler     string
	HandlerFunc HandlerFunc
}

RouteInfo represents a request route's specification which contains path and its handler.

type Router

type Router struct {
	RouterGroup
	// contains filtered or unexported fields
}

Router of the gamerouter

func Default

func Default() *Router

Default returns a Router instance with the Logger and Recovery middleware already attached.

func New

func New() *Router

New returns a new blank Router instance without any middleware attached.

func (*Router) Group

func (router *Router) Group(name string) *RouterGroup

func (*Router) HandleContext

func (router *Router) HandleContext(c *Context)

HandleContext re-enter a context that has been rewritten. This can be done by setting c.Request.URL.Path to your new target. Disclaimer: You can loop yourself to death with this, use wisely.

func (*Router) NoRoute

func (router *Router) NoRoute(handlers ...HandlerFunc)

NoRoute adds handlers for NoRoute. It return a 404 code by default.

func (*Router) Routes

func (router *Router) Routes() (routes RoutesInfo)

Routes returns a slice of registered routes, including some useful information, such as: the http method, path and the handler name.

func (*Router) Run

func (r *Router) Run(addr string, codec Codec) (err error)

func (*Router) ServeProto

func (r *Router) ServeProto(w ResponseWriter, req *Request)

Serve conforms to the Handler interface.

func (*Router) Use

func (router *Router) Use(middleware ...HandlerFunc) IRoutes

Use attaches a global middleware to the router. ie. the middleware attached though Use() will be included in the handlers chain for every single request. Even 404, 405, static files... For example, this is the right place for a logger or error management middleware.

type RouterGroup

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

RouterGroup is used internally to configure router, a RouterGroup is associated with a prefix and an array of handlers (middleware).

func (*RouterGroup) Handle

func (group *RouterGroup) Handle(name string, handlers ...HandlerFunc) IRoutes

Handle

func (*RouterGroup) Handlers

func (group *RouterGroup) Handlers() HandlersChain

Handle registers a new request handle and middleware with the given path and method. The last handler should be the real handler, the other ones should be middleware that can and should be shared among different routes. See the example code in GitHub.

func (*RouterGroup) Name

func (group *RouterGroup) Name() string

func (*RouterGroup) Use

func (group *RouterGroup) Use(middlewares ...HandlerFunc) IRoutes

Use adds middleware to the group, see example code in GitHub.

type RoutesInfo

type RoutesInfo []RouteInfo

RoutesInfo defines a RouteInfo array.

type Server

type Server struct {
	// Addr optionally specifies the TCP address for the server to listen on,
	Addr string

	Handler Handler // handler to invoke

	Codec Codec // encoding and decoding data

	// ReadTimeout is the maximum duration for reading the entire
	// request, including the body.
	ReadTimeout time.Duration
	// WriteTimeout is the maximum duration before timing out
	// writes of the response.
	WriteTimeout time.Duration
	// IdleTimeout is the maximum amount of time to wait for the
	// next request.
	IdleTimeout time.Duration

	// ConnState specifies an optional callback function that is
	// called when a client connection changes state.
	ConnState func(net.Conn, ConnState)

	// ErrorLog specifies an optional logger for errors accepting
	// connections, unexpected behavior from handlers, and
	// underlying FileSystem errors.
	ErrorLog *log.Logger
	// contains filtered or unexported fields
}

Server instance

func (*Server) Close

func (srv *Server) Close() error

Close immediately closes all active net.Listeners and any connections in state StateNew, StateActive, or StateIdle. For a graceful shutdown, use Shutdown.

Close does not attempt to close (and does not even know about) any hijacked connections, such as WebSockets.

Close returns any error returned from closing the Server's underlying Listener(s).

func (*Server) ListenAndServe

func (srv *Server) ListenAndServe() error

func (*Server) Serve

func (srv *Server) Serve(l net.Listener) error

Serve the given listener

func (*Server) Shutdown

func (srv *Server) Shutdown() error

Shutdown gracefully shuts down the server without interrupting any active connections. Shutdown works by first closing all open listeners, then closing all idle connections, and then waiting indefinitely for connections to return to idle and then shut down. If the provided context expires before the shutdown is complete, Shutdown returns the context's error, otherwise it returns any error returned from closing the Server's underlying Listener(s).

When Shutdown is called, Serve, ListenAndServe, and ListenAndServeTLS immediately return ErrServerClosed. Make sure the program doesn't exit and waits instead for Shutdown to return.

Shutdown does not attempt to close nor wait for hijacked connections such as WebSockets. The caller of Shutdown should separately notify such long-lived connections of shutdown and wait for them to close, if desired. See RegisterOnShutdown for a way to register shutdown notification functions.

Once Shutdown has been called on a server, it may not be reused; future calls to methods such as Serve will return ErrServerClosed.

Directories

Path Synopsis
examples
pb

Jump to

Keyboard shortcuts

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