http

package module
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Oct 8, 2018 License: MIT Imports: 13 Imported by: 0

README

CircleCI codecov GoDoc Go Report Card

HTTP

This is one more web development framework for GO using the fasthttp as base. Or, maybe, it is just a set of utility of helpful functions that apply some sugar to the fasthttp "daily" usage.

Extra Features

Routing

Routable is described as an interface which have the DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT methods for routing. This aims to replace the fasthttprouter implementation ([#fasthttprouter](check why here)).

In order to get things going, the below example shows how to define an endpoint serving a GET method:

	router := http.NewRouter()

	router.GET("/api/v1/user", func(ctx *Context) {
		fmt.Fprint(ctx, "the user is: Snake Eyes")
	})
Grouping

When dealing with routes, groups are awesome!

	router := http.NewRouter()

	apiGroup := router.Group("/api") // This retuns a `Routable` that can be used
	                                 // to create other subgroups or define routes.

	apiv1 := apiGroup.Group("/v1")   // This is what we define as a subgroup.

	apiv1.GET(                       // Now a definition of the route itself.
		"/user",
		func(ctx *Context) {
			fmt.Fprint(ctx, "the user is: Snake Eyes")
		},
	)
	// many other routes using `apiv1` ...

There is no difference from using, or not, grouping into the routes definition. Internally, the implementation ends up joining all the routes of the group with the group prefix. Hence, groups will not affect performance.

Middlewares

In order to provide a more flexible API, Middleware supports were added.

Middlewares can implement some verification or extension logic and decide whether or not continue to run the "next" middleware/handler.

	router := http.NewRouter()

	apiGroup := router.Group("/api")
	apiv1 := apiGroup.Group("/v1")
	apiv1.GET(
		"/user",
		func(ctx *Context) {
			fmt.Fprint(ctx, "the user is: Snake Eyes")
		},
		func(ctx *Context, next Handler) {
			// This is a middleware that could do something smart...
			next(ctx)
		},
	)

Yet, you can also define multiple middlewares for each route and their priority will be from the left to the right.

	router := http.NewRouter()

	apiGroup := router.Group("/api")
	apiv1 := apiGroup.Group("/v1")
	apiv1.GET(
		"/user",
		func(ctx *Context) {
			fmt.Fprint(ctx, "the user is: Snake Eyes")
		},
		func(ctx *Context, next Handler) {
			// This is a middleware that could do something smart...
			next(ctx)
		},
		func(ctx *Context, next Handler) {
			// This is a second middleware for the endpoint...
			next(ctx)
		},
	)

Middlewares are also supported on groups:

	router := http.NewRouter()

	apiGroup := router.Group("/api", func(ctx *Context, next Handler) {
		// This is a middleware that could do something smart...
		next(ctx)
	})
	apiv1 := apiGroup.Group("/v1", func(ctx *Context, next Handler) {
		// Yet another middleware applied just for this subgroup...
		next(ctx)
	})
	apiv1.GET(
		"/user",
		func(ctx *Context) {
			fmt.Fprint(ctx, "the user is: Snake Eyes")
		},
		func(ctx *Context, next Handler) {
			// This is a middleware that is applied just for this endpoint
			next(ctx)
		},
	)

Again, there is no performance difference when using middlewares in a specific route or in a whole group. The internal implementation will append both middleware definitions into one big sequence of middlewares for each route.

Thin JSON layer

For simple sake of ease the use of sending and receiving JSON objects SendJson and BodyJson methods were added to the Context.

Sending a JSON

Above an example of sending a JSON document:

	router := http.NewRouter()

	apiGroup := router.Group("/api")
	apiv1 := apiGroup.Group("/v1")
	apiv1.GET(
		"/user",
		func(ctx *Context) {
			ctx.SendJson(map[string]interface{}{
				"name": "Snake Eyes",
				"email": "s.eyes@gijoe.com",
			})
		},
	)
Receiving a JSON

Above an example of sending a JSON document:

	router := http.NewRouter()

	apiGroup := router.Group("/api")
	apiv1 := apiGroup.Group("/v1")
	apiv1.POST(
		"/user",
		func(ctx *Context) {
			user := make(map[string]interface{})
			err = ctx.BodyJson(&user)
			if err != nil {
				fmt.SendJson(map[string]interface{}{
					"error": "user data invalid"
				})
			}
			// To process the user information
		},
	)

fasthttprouter

buaazp/fasthttprouter forks julienschmidt/httprouter adding support for the valyala/fasthttp.

The implementation is very efficient. However, sometimes we could not find a way to place our routes the exact way we wanted to. In order to solve this problem, we implemented our own version (unfortunately less effective).

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	StrApplicationJson = []byte("application/json")
	StrXForwardedFor   = []byte("X-Forwarded-For")
)
View Source
var (
	ErrWrongConfigurationInformed = errors.New("wrong configuration informed")
	ErrServiceNotRunning          = errors.New("service not running")
)

Functions

func Split

func Split(source []byte, dest [][]byte) [][]byte

Types

type ColorServiceReporter

type ColorServiceReporter struct{}

func (*ColorServiceReporter) AfterApplyConfiguration

func (*ColorServiceReporter) AfterApplyConfiguration(service Service, conf interface{}, err error)

func (*ColorServiceReporter) AfterLoadConfiguration

func (*ColorServiceReporter) AfterLoadConfiguration(service Service, conf interface{}, err error)

func (*ColorServiceReporter) AfterStart

func (*ColorServiceReporter) AfterStart(service Service, err error)

func (*ColorServiceReporter) BeforeApplyConfiguration

func (*ColorServiceReporter) BeforeApplyConfiguration(service Service)

func (*ColorServiceReporter) BeforeBegin

func (*ColorServiceReporter) BeforeBegin(service Service)

func (*ColorServiceReporter) BeforeLoadConfiguration

func (*ColorServiceReporter) BeforeLoadConfiguration(service Service)

func (*ColorServiceReporter) BeforeStart

func (*ColorServiceReporter) BeforeStart(service Service)

type ConfigurationLoader

type ConfigurationLoader interface {
	// Load receives the `id` of the configuration and Unmarshals it
	// int the `dst` pointer. If no error is reported the method will
	// return nil otherwise the error will be returned.
	Load(id string) ([]byte, error)
}

ConfigurationLoader defines the contract to load a configuration from a repository.

The repository is an abstract idea that can be represented as a directory, a S3 bucket, or "anything" else.

type ConfigurationUnmarshaler

type ConfigurationUnmarshaler interface {
	Unmarshal(buf []byte, dst interface{}) error
}

ConfigurationUnmarshaler describes the unmarshaling contract of a configuration.

type ConfigurationUnmarshalerYaml

type ConfigurationUnmarshalerYaml struct {
}
var DefaultConfigurationUnmarshalerYaml ConfigurationUnmarshalerYaml

func (*ConfigurationUnmarshalerYaml) Unmarshal

func (loader *ConfigurationUnmarshalerYaml) Unmarshal(buff []byte, dst interface{}) error

Unmarshal is an abstract method that should be override

type ConfigurationUnmarshelerJson

type ConfigurationUnmarshelerJson struct {
}
var DefaultConfigurationUnmarshalerJson ConfigurationUnmarshelerJson

func (*ConfigurationUnmarshelerJson) Unmarshal

func (loader *ConfigurationUnmarshelerJson) Unmarshal(buff []byte, dst interface{}) error

Unmarshal is an abstract method that should be override

type Context

type Context struct {
	Ctx      *fasthttp.RequestCtx
	Response *fasthttp.Response
	Request  *fasthttp.Request
}

Context is the wrapper structure on top of the fasthttp.

func NewContext

func NewContext(ctx *fasthttp.RequestCtx) *Context

NewContext returns a new `Context` from a `fasthttp.RequestCtx`.

func (*Context) BodyJson

func (ctx *Context) BodyJson(dst interface{}) error

BodyJson tries to Unmarshal the body content of the request as a JSON file. The destiny of the unmarshaled data is placed into the passed `dst` pointer. If the unmarshaling process fails `BodyJson` will return an error.

func (*Context) IsJson

func (ctx *Context) IsJson() bool

IsJson checks if the Content-type of the request is `application/json`.

func (*Context) SendJson

func (ctx *Context) SendJson(obj interface{}) error

SendJson marshals the given `obj` and then uses the `SendJsonBytes` to deliver the information to the response.

func (*Context) SendJsonBytes

func (ctx *Context) SendJsonBytes(data []byte) error

SendJsonBytes prepares the repsonse header to send the JSON Data. Afterwards, it appends the received `data` to the body.

func (*Context) UserValue

func (ctx *Context) UserValue(name string) interface{}

UserValue is an alias for the `fasthttp.RequestCtx.UserValue` method.

func (*Context) Write

func (ctx *Context) Write(buff []byte) (int, error)

Write writes `buff` to the body response. It is an alias for the `fasthttp.RequestCtx.Write`.

type FasthttpService

type FasthttpService struct {
	Router        *Router
	Configuration FasthttpServiceConfiguration
	Listener      net.Listener
	Server        fasthttp.Server
	// contains filtered or unexported fields
}

FasthttpService implements the server for starting

func (*FasthttpService) ApplyConfiguration

func (service *FasthttpService) ApplyConfiguration(configuration interface{}) error

ApplyConfiguration checks if the passing interface is a `FasthttpServiceConfiguration` and applies its configuration to the service.

func (*FasthttpService) LoadConfiguration

func (service *FasthttpService) LoadConfiguration() (interface{}, error)

LoadConfiguration does not do anything in this implementation. This methods is just a placeholder to be overwritten on its usage.

func (*FasthttpService) Restart

func (service *FasthttpService) Restart() error

Reload returns an error due to fasthttp not being able to stop the service.

func (*FasthttpService) Start

func (service *FasthttpService) Start() error

Start ListenAndServe the server. This method is blocking because it uses the fasthttp.ListenAndServe implementation.

func (*FasthttpService) Stop

func (service *FasthttpService) Stop() error

Stop closes the listener and waits the `Start` to stop.

type FasthttpServiceConfiguration

type FasthttpServiceConfiguration struct {
	Bind string
}

FasthttpServiceConfiguration keeps all the configuration needed to start the `FasthttpService`.

type FileConfigurationLoader

type FileConfigurationLoader struct {
	Directory string
}

func NewFileConfigurationLoader

func NewFileConfigurationLoader(dir string) *FileConfigurationLoader

func (*FileConfigurationLoader) Load

func (loader *FileConfigurationLoader) Load(id string) ([]byte, error)

type Handler

type Handler func(ctx *Context)

type Middleware

type Middleware func(ctx *Context, next Handler)

Middleware is the descriptor of a middleware that wraps a handler.

A middleware implementation will receive a `*Context` and a `next` as a representation of the next middleware (or the end handler itself) that should be called if the endpoint execution should carry on.

If you need to avoid the endpoint execution to continue, you should not to call the `next` handler.

type NopServiceReporter

type NopServiceReporter struct{}

func (*NopServiceReporter) AfterApplyConfiguration

func (*NopServiceReporter) AfterApplyConfiguration(service Service, conf interface{}, err error)

func (*NopServiceReporter) AfterLoadConfiguration

func (*NopServiceReporter) AfterLoadConfiguration(service Service, conf interface{}, err error)

func (*NopServiceReporter) AfterStart

func (*NopServiceReporter) AfterStart(service Service, err error)

func (*NopServiceReporter) BeforeApplyConfiguration

func (*NopServiceReporter) BeforeApplyConfiguration(service Service)

func (*NopServiceReporter) BeforeBegin

func (*NopServiceReporter) BeforeBegin(service Service)

func (*NopServiceReporter) BeforeLoadConfiguration

func (*NopServiceReporter) BeforeLoadConfiguration(service Service)

func (*NopServiceReporter) BeforeStart

func (*NopServiceReporter) BeforeStart(service Service)

type Routable

type Routable interface {
	DELETE(path string, handler Handler, middlewares ...Middleware)
	GET(path string, handler Handler, middlewares ...Middleware)
	HEAD(path string, handler Handler, middlewares ...Middleware)
	OPTIONS(path string, handler Handler, middlewares ...Middleware)
	PATCH(path string, handler Handler, middlewares ...Middleware)
	POST(path string, handler Handler, middlewares ...Middleware)
	PUT(path string, handler Handler, middlewares ...Middleware)

	Group(path string, middlewares ...Middleware) Routable
}

type Router

type Router struct {
	NotFound Handler
	// contains filtered or unexported fields
}

func NewRouter

func NewRouter() *Router

func (*Router) DELETE

func (router *Router) DELETE(path string, handler Handler, middlewares ...Middleware)

func (*Router) GET

func (router *Router) GET(path string, handler Handler, middlewares ...Middleware)

func (*Router) Group

func (router *Router) Group(path string, middlewares ...Middleware) Routable

func (*Router) HEAD

func (router *Router) HEAD(path string, handler Handler, middlewares ...Middleware)

func (*Router) Handler

func (router *Router) Handler(fCtx *fasthttp.RequestCtx)

func (*Router) OPTIONS

func (router *Router) OPTIONS(path string, handler Handler, middlewares ...Middleware)

func (*Router) PATCH

func (router *Router) PATCH(path string, handler Handler, middlewares ...Middleware)

func (*Router) POST

func (router *Router) POST(path string, handler Handler, middlewares ...Middleware)

func (*Router) PUT

func (router *Router) PUT(path string, handler Handler, middlewares ...Middleware)

type Service

type Service interface {
	// Name identifies the service.
	Name() string

	// Loads the configuration. If successful nil will be returned, otherwise
	// the error.
	LoadConfiguration() (interface{}, error)

	// Applies a given configuration object to the service. If successful nil
	// will be returned, otherwise the error.
	ApplyConfiguration(interface{}) error

	// Restarts the service. If successful nil will be returned, otherwise the
	// error.
	Restart() error

	// Start starts the service. If successful nil will be returned, otherwise
	// the error.
	Start() error

	// Stop stops the service. If successful nil will be returned, otherwise the
	// error.
	Stop() error
}

Service is an abstraction for implementing parts that can be loaded, reloaded, started and stopped inside of the system.

Maybe you can implement your HTTP service like this, or your Redis resource. As simple and wide as it could be this directive will provide an defined signature to implement all your resources.

type ServiceStarter

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

func NewServiceStarter

func NewServiceStarter(services []Service, reporter ServiceStarterReporter) *ServiceStarter

func (*ServiceStarter) Start

func (engineStarter *ServiceStarter) Start() error

type ServiceStarterReporter

type ServiceStarterReporter interface {
	BeforeBegin(service Service)

	BeforeLoadConfiguration(service Service)
	AfterLoadConfiguration(service Service, conf interface{}, err error)

	BeforeApplyConfiguration(service Service)
	AfterApplyConfiguration(service Service, conf interface{}, err error)

	BeforeStart(service Service)
	AfterStart(service Service, err error)
}

Directories

Path Synopsis
examples
srvstarter command

Jump to

Keyboard shortcuts

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