http

package
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 6, 2018 License: MIT Imports: 14 Imported by: 0

README

http

import “github.com/tonto/kit/http”

Package http provides server implementation with lifecycle control, graceful shutdown, commonly used adapters, easy service registration and response/error handling, endpoints implementation, tls support...

See the example package for example usage and to see how you can integrate twirp.

Creating and running the server

With minimal setup:

server := http.NewServer()

server.RegisterServices(
	...
)

log.Fatal(server.Run(8080))

With server options (see the adapter package):

logger := log.New(os.Stdout, "http/example => ", log.Ldate|log.Ltime|log.Lshortfile)

server := http.NewServer(
  http.WithLogger(logger),
  http.WithTLSConfig("cert.pem", "key.pem"),
  http.WithMux(customMux), // Override default gorilla mux router
  http.WithNotFoundHandler(notFoundHdlr),
  http.WithAdapters(
    adapter.WithRequestLogger(logger),
    adapter.WithCORS(
      adapter.WithCORSAllowOrigins("*"),
      adapter.WithCORSAllowMethods("PUT", "DELETE"),
      adapter.WithCORSMaxAge(86400),
    ),
  ),
)

server.RegisterServices(
  ...
)

log.Fatal(server.Run(8080))

You can use server.Stop() to explicitly stop the server.

Services

With this package, there is a notion of service which is simply a type that implements http.Service

Creating basic http service

Creating a service is as easy as embeding http.BaseService, and registering an endpoint.

type OrderService struct {
  http.BaseService
}

Service routing prefix

Implement Prefix method to return service routing prefix ("/" by default)

func (os *OrderService) Prefix() string { return "order" }

HandlerFuncs and Endpoints

With services there is a notion of HandlerFunc and an Endpoint. HandlerFunc is basically a standard http handler func with context added as first param:

type HandlerFunc func(context.Context, http.ResponseWriter, *http.Request)

You can use it the same way you would a normal http handler func with no restrictions, or caveats (you only have the extra context passed in).

Extending service to register HandlerFunc:

func NewOrderService() *Order {
  svc := Order{}

  svc.RegisterHandler("POST", "/create", svc.create)

  return &svc
}

type OrderService struct {
  http.BaseService
}

func (os *OrderService) Prefix() string { return "order" }

func (os *OrderService) create(c context.Context, w ghttp.ResponseWriter, r *ghttp.Request) {
  respond.WithJSON(w, r, http.NewResponse("order created", ghttp.StatusOK))
}

See the respond package for more info on it's usage.

Endpoints

Endpoints however, are specificaly designed to be used for json api endpoints. They provide easy request decoding and response encoding.

Endpoint is a func of the following signature:

func(c context.Context, w http.ResponseWriter, req *CustomType) (*http.Response, error)

Instead of go http request the third parameter is a custom type that you choose to which the request body will be json decoded.

Return parameters are http.Response and an error

Let's extend our service with two new endpoints:

func NewOrderService() *Order {
  svc := Order{}

  svc.RegisterHandler("POST", "/create", svc.create)
  svc.RegisterEndpoint("POST", "/add_item", svc.addItem)

  return &svc
}

type OrderService struct {
  http.BaseService
}

func (os *OrderService) Prefix() string { return "order" }

func (os *OrderService) create(c context.Context, w ghttp.ResponseWriter, r *ghttp.Request) {
  respond.WithJSON(w, r, http.NewResponse("order created", ghttp.StatusOK))
}

type addItemReq struct {
  ItemID  int64 `json:"item_id"`
  OrderID int64 `json: "order_id"`
  UserID  int64 `json:"user_id"`
}

func (os *OrderService) addItem(c context.Context, w ghttp.ResponseWriter, r *addItemReq) (*http.Response, error) {
  // r now contains the decoded json request
  return http.NewResponse("item added", ghttp.StatusOK), nil
}

If you don't expect any request body from an endpoint you can omit the *http.Response return value, and only keep the error (which cannot be omited).

You can return a regular go error or use http.NewError to create a composite error with custom status. Both will be correctly json encoded.

Service adapters

You can use svc.Adapt(...adapters) to register per service adapters. Check out example package for an example.

Putting it all together

The only thing that is left is to register our service with the server:

server := http.NewServer()

server.RegisterServices(
	NewOrderService(),
)

log.Fatal(server.Run(8080))

Documentation

Overview

Package http provides HTTP server implementation with server lifecycle control, commonly used adapters, easy service registration and response/error handling, tls support...

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ReqFromCtx

func ReqFromCtx(c context.Context) *http.Request

ReqFromCtx returns http request associated with context (used with endpoints)

Types

type Adapter

type Adapter func(HandlerFunc) HandlerFunc

Adapter represents HandlerFunc middleware adapter

type BaseService

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

BaseService represents base http service

func (*BaseService) Adapt

func (b *BaseService) Adapt(mw ...Adapter)

Adapt is used to adapt the service with provided adapters

func (*BaseService) Endpoints

func (b *BaseService) Endpoints() Endpoints

Endpoints returns all registered endpoints

func (*BaseService) MustRegisterEndpoint added in v0.2.8

func (b *BaseService) MustRegisterEndpoint(verb string, path string, method interface{}, a ...Adapter)

MustRegisterEndpoint panic version of RegisterEndpoint

func (*BaseService) Prefix

func (b *BaseService) Prefix() string

Prefix returns service routing prefix

func (*BaseService) RegisterEndpoint

func (b *BaseService) RegisterEndpoint(verb string, path string, method interface{}, a ...Adapter) error

RegisterEndpoint is a helper method that registers service json endpoint JSON endpoint method should have the following signature: func(c context.Context, w http.ResponseWriter, req *CustomType) (*http.Response, error) where *CustomType is your custom request type to which r.Body will be json unmarshalled automatically *http.Response can be omitted if endpoint has no reasonable response, error is always required however

func (*BaseService) RegisterHandler

func (b *BaseService) RegisterHandler(verb string, path string, h HandlerFunc, a ...Adapter)

RegisterHandler is a helper method that registers service HandlerFunc Service HandlerFunc is an extension of http.HandlerFunc which only adds context.Context as first parameter, the rest stays the same

type ContextKey added in v0.2.8

type ContextKey string

ContextKey is a context key type

type Endpoint

type Endpoint struct {
	Methods []string
	Handler HandlerFunc
}

Endpoint represents http api endpoint interface

type Endpoints

type Endpoints map[string]*Endpoint

Endpoints represents a map of service endpoints

type Error

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

Error represents http error

func NewError

func NewError(code int, errs ...error) *Error

NewError wraps provided errs and http response code thus creating new http error

func (*Error) Code

func (e *Error) Code() int

Code returns http response code associated with Error

func (*Error) Error

func (e *Error) Error() string

Error returns error description

func (*Error) Errs

func (e *Error) Errs() []error

Errs returns wrapped errors

type HandlerFunc

type HandlerFunc func(context.Context, http.ResponseWriter, *http.Request)

HandlerFunc represents kit http handler func

func AdaptHandlerFunc

func AdaptHandlerFunc(hf HandlerFunc, adapters ...Adapter) HandlerFunc

AdaptHandlerFunc decorates given HandlerFunc with provided adapters

func (HandlerFunc) ServeHTTP

func (hf HandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler for HandlerFunc so it can be chained with third party middleware

type Response

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

Response represents http response

func NewResponse

func NewResponse(resp interface{}, code int) *Response

NewResponse wraps provided code and resp into Response so it can be used with respond

func (*Response) Body

func (r *Response) Body() interface{}

Body returns associated response body

func (*Response) Code

func (r *Response) Code() int

Code returns response http code

type Server

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

Server represents kit http server

func NewServer

func NewServer(opts ...ServerOption) *Server

NewServer creates new http server instance

func (*Server) MustRegisterService added in v0.2.8

func (s *Server) MustRegisterService(svc Service)

MustRegisterService panic version of RegisterService

func (*Server) MustRegisterServices added in v0.2.8

func (s *Server) MustRegisterServices(svcs ...Service)

MustRegisterServices panic version of RegisterServices

func (*Server) MustRun added in v0.2.8

func (s *Server) MustRun(port int)

MustRun panic version of Run

func (*Server) RegisterService

func (s *Server) RegisterService(svc Service) error

RegisterService registers a given http Service with the server and sets up routes

func (*Server) RegisterServices

func (s *Server) RegisterServices(svcs ...Service) error

RegisterServices registers given http Services with the server and sets up routes

func (*Server) Run

func (s *Server) Run(port int) error

Run will start a server listening on a given port

func (*Server) Stop

func (s *Server) Stop()

Stop attempts to gracefully shutdown the server

type ServerOption

type ServerOption func(*Server)

ServerOption is used for setting up server configuration

func WithAdapters

func WithAdapters(a ...Adapter) ServerOption

WithAdapters represents server option for setting up server-wide request adapters

func WithLogger

func WithLogger(l *log.Logger) ServerOption

WithLogger represents server option for setting up logger

func WithMux added in v0.2.5

func WithMux(h http.Handler) ServerOption

WithMux represents server option for setting a custom router. gorilla/mux is used as default

func WithNotFoundHandler

func WithNotFoundHandler(h http.Handler) ServerOption

WithNotFoundHandler represents server option for setting default not found handler

func WithReadTimeout added in v0.2.7

func WithReadTimeout(d time.Duration) ServerOption

WithReadTimeout sets http server read timeout

func WithTLSConfig

func WithTLSConfig(cert, key string) ServerOption

WithTLSConfig represents server option for setting tls cer and key files

func WithWriteTimeout added in v0.2.7

func WithWriteTimeout(d time.Duration) ServerOption

WithWriteTimeout sets http server write timeout

type Service

type Service interface {
	Prefix() string
	Endpoints() Endpoints
}

Service defines http service interface

type TwirpService added in v0.2.8

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

TwirpService is designed to be embedded into kit Service implementations in order to enable easier twirp Handler/hooks registration

func (*TwirpService) Endpoints added in v0.2.8

func (ts *TwirpService) Endpoints() Endpoints

Endpoints returns all registered endpoints

func (*TwirpService) Prefix added in v0.2.8

func (ts *TwirpService) Prefix() string

Prefix returns service routing prefix

func (*TwirpService) TwirpInit added in v0.2.8

func (ts *TwirpService) TwirpInit(twirpPrefix string, twirpServer http.Handler)

TwirpInit sets up kit endpoints and prefix for twirp handler

type Validator

type Validator interface {
	Validate() error
}

Validator interface can be implemented by endpoint request types and it will be automatically called by service upon decoding

Directories

Path Synopsis
proto/account
Package account is a generated protocol buffer package.
Package account is a generated protocol buffer package.
Package respond provides common http response functionality
Package respond provides common http response functionality

Jump to

Keyboard shortcuts

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