webfmwk

package module
v4.3.4 Latest Latest
Warning

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

Go to latest
Published: Apr 26, 2021 License: MIT Imports: 26 Imported by: 0

README

webfmwk

Build Status codecov Go Report Card CodeFactor License Version compatibility with Go 1.13 onward using modules GoDoc

What

webfmwk is a go web API framework

Use it

Import github.com/burgesQ/webfmwk/v4.

Important

Go 1.13 is required.

Example
Hello world
go sample

package main

import (
	"net/http"

	"github.com/burgesQ/webfmwk/v4"
)

// curl -X GET 127.0.0.1:4242/hello
// { "message": "hello world" }
func main() {
	var s = webfmwk.InitServer()

	s.GET("/hello", func(c webfmwk.Context) error {
		c.JSONBlob(http.StatusOK, []byte(`{ "message": "hello world" }`))
	})

	s.Start(":4242")

	// ctrl+c is handled internaly
	defer s.WaitAndStop()
}

Reach the endpoint:

curl sample

$ curl -i 'http://localhost:4242/hello'
HTTP/1.1 200 OK
Accept: application/json; charset=UTF-8
Content-Type: application/json; charset=UTF-8
Produce: application/json; charset=UTF-8
Date: Mon, 18 May 2020 07:45:31 GMT
Content-Length: 25

{"message":"hello world"}%

code samples

Some samples are in the ./doc directory. The main (doc.go) hande the samples orchestration. Use go run . [sample file name] to run the example file.

see more sample

$ cd doc
$ go run . panic_to_error
. panic_to_error
running panic_to_error (use panic to handle some error case)
- DBG  : 	-- crtl-c support enabled
- DBG  : 	-- handlers loaded
- DBG  : exit handler: starting
- DBG  : http server :4242: starting
- DBG  : [+] server 1 (:4242) 
- DBG  : [+] new connection
+ INFO : [+] (f2124b89-414b-4361-96ec-5f227c0e3369) : [GET]/panic
+ INFO : [-] (f2124b89-414b-4361-96ec-5f227c0e3369) : [422](27)
- DBG  : [-] (f2124b89-414b-4361-96ec-5f227c0e3369) : >{"error":"user not logged"}<
what filename
return hello world hello_world.go
fetch value from url url_param.go
fetch query param value query_param.go
post content handling post_content.go
register mutliple endpoints routes.go
overload the framework context custom_context.go
register extra hanlders / middleware handlers.go
generate and expose a swagger doc swagger.go
start the server in https tls.go
attach worker to the server pool custom_worker.go
add an ID per requrest (ease logging for ex) request_id.go
panic to return an http error panic_to_error.go

Test

Simply run make

Contributing

First of all, thank you for contributing hearts

If you find any typo/misconfiguration/... please send me a PR or open an issue.

Also, while creating your Pull Request on GitHub, please write a description which gives the context and/or explains why you are creating it.

Credit

Frafos GmbH 🎉 where I've writted most of that code

Documentation

Overview

Package webfmwk implements an minimalist Go web framework

Example:

  package main

  import (
    w "github.com/burgesQ/webfmwk/v4"
  )

  type Context struct {
    webfmwk.IContext
    content string
  }

  // Handler
  func hello(c w.IContext) error {
    return c.JSONOk("Hello, World!")
  }

  func main() {
    // Echo instance
    s := w.InitServer(
     webfmwk.EnableCheckIsUp()
		webfmwk.WithCORS(),
		webfmwk.WithLogger(log.GetLogger()),
		webfmwk.WithMiddlewars(
			middleware.Logging,
			middleware.Security),
		webfmwk.WithCustomContext(func(c *webfmwk.Context) webfmwk.IContext {
			return &Context{
				Context:  *c,
				content: "testing",
			}
		}))

    // Routes
    s.GET("/hello", hello)

    // start server on :4242
    go func() {
      s.Start(":4242")
    }()

    // ctrl+c is handled internaly
    defer s.WaitAndStop()
  }

Learn more at https://github.com/burgesQ/webfmwk

Index

Constants

View Source
const (
	GET    = "GET"
	POST   = "POST"
	PATCH  = "PATCH"
	PUT    = "PUT"
	DELETE = "DELETE"
)

Variables

View Source
var (
	ErrMissingContentType = NewNotAcceptable(NewError("Missing Content-Type header"))
	ErrNotJSON            = NewNotAcceptable(NewError("Content-Type is not application/json"))
)

Functions

func GetIPFromRequest added in v4.3.0

func GetIPFromRequest(r *http.Request) string

func GetLogger

func GetLogger() log.Log

GetLogger return an instance of the Log interface used

func HandleError added in v4.3.0

func HandleError(ctx Context, e error)

func RegisterValidatorAlias added in v4.1.7

func RegisterValidatorAlias(name, what string)

RegisterCustomValidator register some validation alias see gtihub.com/go-playground/validator.v10

func RegisterValidatorRule added in v4.1.7

func RegisterValidatorRule(name string, fn func(fl validator.FieldLevel) bool) error

RegisterValidatorRule register the validation rule param see gtihub.com/go-playground/validator.v10

func RegisterValidatorTrans added in v4.1.7

func RegisterValidatorTrans(name, what string) error

RegisterValidatorTrans register some validation alias see gtihub.com/go-playground/validator.v10

func Shutdown

func Shutdown(ctx context.Context)

Shutdown terminate all running servers. Call shutdown with a context.context on each http(s) server.

func UseOption added in v4.1.2

func UseOption(s *Server, o Option)

UseOption apply the param o option to the params s server

func UseOptions added in v4.1.2

func UseOptions(s *Server, opts ...Option)

UseOptions apply the params opts option to the param s server

Types

type Address added in v4.1.4

type Address struct {
	Addr string     `json:"addr"`
	TLS  *TLSConfig `json:"tls,omitempty" mapstructure:"tls,omitempty"`
	Name string     `json:"name"`
}

Address hold the api server address

func (Address) GetAddr added in v4.1.10

func (a Address) GetAddr() string

func (Address) GetName added in v4.1.10

func (a Address) GetName() string

func (Address) GetTLS added in v4.1.10

func (a Address) GetTLS() *TLSConfig

func (Address) IsOk added in v4.1.5

func (a Address) IsOk() bool

func (Address) String added in v4.1.4

func (a Address) String() string

type Context

type Context interface {
	SendResponse
	InputHandling
	ContextLogger

	// GetRequest return the holded http.Request object
	GetRequest() *http.Request

	// GetVar return the url var parameters. Empty string for none
	GetVar(key string) (val string)

	// GetQueries return the queries object
	GetQueries() map[string][]string

	// GetQuery fetch the query object key
	GetQuery(key string) (val string, ok bool)

	// GetContext fetch the previously saved context object
	GetContext() context.Context
}

Context Interface implement the context used in this project

type ContextLogger added in v4.3.0

type ContextLogger interface {
	// SetLogger set the logger of the ctx
	SetLogger(logger log.Log) Context

	// GetLogger return the logger of the ctx
	GetLogger() log.Log
}

type DocHandler added in v4.2.1

type DocHandler struct {
	// H represent the doc handler to expose
	H http.HandlerFunc
	// Name is used in debug message
	Name string
	// Path hold the URI at  which the handler is exposed.
	// If one used, will be prefixed by the api base.
	Path string
}

DocHandler hold the required data to expose a documentation handlers

type Error added in v4.1.8

type Error struct {
	// Status hold the error code status
	//
	// Example: 500
	Status int `json:"status" validate:"required"`

	// Message hold the error message
	//
	// Example: the impossible appened
	Message string `json:"message" example:"no such resource" validate:"required"`
	// contains filtered or unexported fields
}

Error struct is used to answer error

func NewAnonymousWrappedError

func NewAnonymousWrappedError(err error, msg string) Error

NewAnonymousWrappedError generate a Error which wrap the err params

func NewError added in v4.1.8

func NewError(err string) Error

NewError generate a new json error response payload

func NewErrorFromError added in v4.1.8

func NewErrorFromError(err error) Error

NewAnonymousWrappedError generate a Error which wrap the err params

func (Error) Error added in v4.1.8

func (a Error) Error() string

Error implement the Error interface

func (*Error) SetStatusCode added in v4.1.8

func (a *Error) SetStatusCode(op int)

SetStatusCode set the AE internal status code

type ErrorHandled

type ErrorHandled interface {
	// error
	Error() string
	Unwrap() error
	GetOPCode() int
	SetStatusCode(op int) ErrorHandled
	GetContent() interface{}
	SetWrapped(err error) ErrorHandled
}

IErrorHandled interface implement the panic recovering

func NewBadRequest

func NewBadRequest(content interface{}) ErrorHandled

NewBadRequest produce an errorHandled with the status code 400

func NewConflict

func NewConflict(content interface{}) ErrorHandled

NewConflict produce an ErrorHandled with the status code 409

func NewErrorHandled

func NewErrorHandled(op int, content interface{}) ErrorHandled

NewError return a new errorHandled var

func NewForbidden added in v4.2.1

func NewForbidden(content interface{}) ErrorHandled

NewUnauthorized produce an ErrorHandled with the status code 403

func NewInternal

func NewInternal(content interface{}) ErrorHandled

NewUnprocessable produce an ErrorHandled with the status code 500

func NewNoContent

func NewNoContent() ErrorHandled

NewNoContent produce an errorHandled with the status code 204

func NewNotAcceptable

func NewNotAcceptable(content interface{}) ErrorHandled

NewNotAcceptable produce an ErrorHandled with the status code 406

func NewNotFound

func NewNotFound(content interface{}) ErrorHandled

NewNotAcceptable produce an ErrorHandled with the status code 404

func NewNotImplemented

func NewNotImplemented(content interface{}) ErrorHandled

NewUnprocessable produce an ErrorHandled with the status code 501

func NewProcessing

func NewProcessing(content interface{}) ErrorHandled

NewProcessing produce an errorHandled with the status code 102

func NewServiceUnavailable

func NewServiceUnavailable(content interface{}) ErrorHandled

NewServiceUnavailable produce an ErrorHandled with the status code 422

func NewUnauthorized

func NewUnauthorized(content interface{}) ErrorHandled

NewUnauthorized produce an ErrorHandled with the status code 401

func NewUnprocessable

func NewUnprocessable(content interface{}) ErrorHandled

NewUnprocessable produce an ErrorHandled with the status code 422

type Handler

type Handler func(HandlerFunc) HandlerFunc

Handler hold the function signature of a webfmwk handler chaning (middlware)

type HandlerFunc

type HandlerFunc func(c Context) error

HandlerSign hold the signature of a webfmwk handler (chain of middlware)

func UseHanlder added in v4.1.2

func UseHanlder(next HandlerFunc) HandlerFunc

UseHanlder apply the HandlerFunc method

type Header [2]string

type IAddress added in v4.1.10

type IAddress interface {
	GetAddr() string
	GetTLS() *TLSConfig
	GetName() string
	IsOk() bool
}

type ITLSConfig

type ITLSConfig interface {
	fmt.Stringer

	// GetCert return the full path to the server certificate file
	GetCert() string
	// GetKey return the full path to the server key file
	GetKey() string
	// GetCa return the full path to the server ca cert file
	GetCa() string

	// GetInsecure return true if the TLS Certificate shouldn't be checked
	GetInsecure() bool

	// IsEmpty return true if the config is empty
	Empty() bool
}

ITLSConfig is used to interface the TLS implemtation.

type InputHandling added in v4.3.0

type InputHandling interface {
	// FetchContent extract the content from the body
	FetchContent(content interface{}) ErrorHandled

	// Validate is used to validate a content of the content params
	Validate(content interface{}) ErrorHandled

	// FetchAndValidateContent fetch the content then validate it
	FetchAndValidateContent(content interface{}) ErrorHandled

	// Decode load the query param in the content object
	DecodeQP(content interface{}) ErrorHandled
}

type JSONResponse added in v4.3.0

type JSONResponse interface {
	// JSONBlob answer the JSON content with the status code op
	JSONBlob(op int, content []byte) error

	// JSON answer the JSON content with the status code op
	JSON(op int, content interface{}) error

	// JSONOk return the interface with an http.StatusOK (200)
	JSONOk(content interface{}) error

	// JSONCreated return the interface with an http.StatusCreated (201)
	JSONCreated(content interface{}) error

	// JSONAccepted return the interface with an http.StatusAccepted (202)
	JSONAccepted(content interface{}) error

	// JSONNoContent return an empty payload an http.StatusNoContent (204)
	JSONNoContent() error

	// JSONBadRequest return the interface with an http.StatusBadRequest (400)
	JSONBadRequest(content interface{}) error

	// JSONUnauthorized return the interface with an http.StatusUnauthorized (401)
	JSONUnauthorized(content interface{}) error

	// JSONForbiden return the interface with an http.StatusForbidden (403)
	JSONForbiden(content interface{}) error

	// JSONNoContent return the interface with an http.StatusNotFound (404)
	JSONNotFound(content interface{}) error

	// JSONConflict return the interface with an http.StatusConflict (409)
	JSONConflict(content interface{}) error

	// JSONUnauthorized return the interface with an http.StatusUnprocessableEntity (422)
	JSONUnprocessable(content interface{}) error

	// JSONInternalError return the interface with an http.StatusInternalServerError (500)
	JSONInternalError(content interface{}) error

	// JSONNotImplemented return the interface with an http.StatusNotImplemented (501)
	JSONNotImplemented(content interface{}) error
}

type Option

type Option func(s *Server)

Option are tu be used this way :

  s := w.InitServer(
    webfmwk.WithLogger(log.GetLogger()),
    webfmwk.EnableCheckIsUp()
    webfmwk.WithCORS(),
    webfmwk.WithPrefix("/api"),
    webfmwk.WithMiddlewares(log.GetLogger()),
    webfmwk.WithDocHanlders(docs.GetRedocHandler(nil))
    webfmwk.WithHanlders(
			hanlder.Logging,
			handler.Security))

func CheckIsUp

func CheckIsUp() Option

CheckIsUp expose a `/ping` endpoint and try to poll to check the server healt when it's started

func SetMaxHeaderBytes

func SetMaxHeaderBytes(val int) Option

SetMaxHeaderBytes set the max header bytes of both request and response

func SetPrefix

func SetPrefix(prefix string) Option

SetPrefix set the API root prefix

func SetReadHeaderTimeout

func SetReadHeaderTimeout(val time.Duration) Option

SetReadHeaderTimeout set the value of the timeout on the read header process

func SetReadTimeout

func SetReadTimeout(val time.Duration) Option

SetReadTimeout is a timing constraint on the client http request imposed by the server from the moment of initial connection up to the time the entire request body has been read.

[Accept] --> [TLS Handshake] --> [Request Headers] --> [Request Body] --> Response

func SetWriteTimeout

func SetWriteTimeout(val time.Duration) Option

SetWriteTimeout is a time limit imposed on client connecting to the server via http from the time the server has completed reading the request header up to the time it has finished writing the response.

[Accept] --> [TLS Handshake] --> [Request Headers] --> [Request Body] --> Response

func WithCORS

func WithCORS() Option

WithCORS enable the CORS (Cross-Origin Resource Sharing) support

func WithCtrlC

func WithCtrlC() Option

WithCtrlC enable the internal ctrl+c support from the server

func WithDocHandlers added in v4.2.1

func WithDocHandlers(handler ...DocHandler) Option

WithDocHandlers allow to register custom DocHandler struct (ex: swaggo, redoc). If use with SetPrefix, register WithDocHandler after the SetPrefix one

package main

import (
  "github.com/burgesQ/webfmwk/v4"
  "github.com/burgesQ/webfmwk/v4/docs"
)

func main() {
  var s = webfmwk.InitServer(webfmwk.WithDocHandlers(docs.GetRedocHandler(nil)))
}

func WithHandlers

func WithHandlers(h ...Handler) Option

WithHandlers allow to register a list of webfmwk.Handler Handler signature is the webfmwk.HandlerFunc one (func(c Context)). To register a custom context, simply do it in the toppest handler

  package main

  import (
    "github.com/burgesQ/webfmwk/v4"
    "github.com/burgesQ/webfmwk/v4/handler"
  )

  type CustomContext struct {
     webfmwk.Context
     val String
  }

  func main() {
    var s = webfmwk.InitServer(webfmwk.WithHandlers(handler.Logging, handler.RequestID,
       webfmwk.HandlerFunc {
          return webfmwk.HandlerFunc(func(c webfmwk.Context) error {
						 cc := Context{c, "val"}
						 return next(cc)})}))
 }

func WithLogger

func WithLogger(lg log.Log) Option

WithLogger set the server logger which implement the log.Log interface Try to set it the earliest posible.

func WithMiddlewares

func WithMiddlewares(mw ...mux.MiddlewareFunc) Option

WithMiddlewares allow to register a list of gorilla/mux.MiddlewareFunc. Middlwares signature is the http.Handler one (func(w http.ResponseWriterm r *http.Request))

Middlewates were depreceated since v4 in favor of Handlers.

package main

import (
  "github.com/burgesQ/webfmwk/v4"
  "github.com/burgesQ/webfmwk/v3/middleware"
)

func main() {
  var s = webfmwk.InitServer(webfmwk.WithMiddlewares(middleware.Security))
}

type Options added in v4.1.1

type Options []Option

type Response

type Response struct {
	// Status hold the error code status
	//
	// Example: 200
	Status int `json:"status" example:"204" validate:"required"`

	// Message hold the error message
	//
	// Example: action successfully completed
	Message string `json:"content,omitempty"`
}

Response is returned in case of success

func NewResponse

func NewResponse(str string) Response

NewResponse generate a new json response payload

func (*Response) SetStatusCode added in v4.1.6

func (r *Response) SetStatusCode(op int)

type Route

type Route struct {
	Verbe   string      `json:"verbe"`
	Path    string      `json:"path"`
	Name    string      `json:"name"`
	Handler HandlerFunc `json:"-"`
}

Route hold the data for one route

type Routes

type Routes []Route

Routes hold an array of route

type RoutesPerPrefix

type RoutesPerPrefix map[string]Routes

RoutesPerPrefix hold the routes and there respectiv prefix

type SendResponse added in v4.3.0

type SendResponse interface {
	JSONResponse
	XMLResponse

	// SendResponse create & send a response according to the parameters
	SendResponse(op int, content []byte, headers ...Header) error

	// SetHeader set the header of the http response
	SetHeaders(headers ...Header)

	SetHeader(k, v string)

	// IsPretty toggle the compact output mode
	IsPretty() bool
}

type Server

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

Server is a struct holding all the necessary data / struct

func InitServer

func InitServer(opts ...Option) *Server

InitServer initialize a webfmwk.Server instance It take the server options as parameters. List of server options : WithLogger, WithCtrlC, CheckIsUp, WithCORS, SetPrefix, WithHandlers, SetReadTimeout, SetWriteTimeout, SetMaxHeaderBytes, SetReadHeaderTimeout,

func (*Server) AddRoutes

func (s *Server) AddRoutes(r ...Route)

AddRoute add the endpoint to the server

func (*Server) CustomHandler

func (s *Server) CustomHandler(handler HandlerFunc) func(http.ResponseWriter, *http.Request)

webfmwk main logic, return a HandlerFunc wrapper in an http handler

func (*Server) DELETE

func (s *Server) DELETE(path string, handler HandlerFunc)

DELETE expose a route to the http verb DELETE

func (*Server) DumpRoutes

func (s *Server) DumpRoutes()

DumpRoutes dump the API endpoints using the server logger

func (*Server) EnableCheckIsUp added in v4.1.3

func (s *Server) EnableCheckIsUp() *Server

EnableCheckIsUp add an /ping endpoint. Is used, cnce a server is started, the user can check weather the server is up or not by reading the isReady channel vie the IsReady() method

func (*Server) GET

func (s *Server) GET(path string, handler HandlerFunc)

GET expose a route to the http verb GET

func (*Server) GetContext

func (s *Server) GetContext() context.Context

GetContext return the context.Context used

func (*Server) GetLauncher

func (s *Server) GetLauncher() *WorkerLauncher

GetLauncher return a pointer to the internal workerLauncher

func (*Server) GetLogger

func (s *Server) GetLogger() log.Log

GetLogger return the used Log instance

func (*Server) IsReady

func (s *Server) IsReady() chan bool

IsReady return the channel on which `true` is send once the server is up

func (*Server) PATCH

func (s *Server) PATCH(path string, handler HandlerFunc)

PATCH expose a route to the http verb PATCH

func (*Server) POST

func (s *Server) POST(path string, handler HandlerFunc)

POST expose a route to the http verb POST

func (*Server) PUT

func (s *Server) PUT(path string, handler HandlerFunc)

PUT expose a route to the http verb PUT

func (*Server) RouteApplier

func (s *Server) RouteApplier(rpps ...RoutesPerPrefix)

RouteApplier apply the array of RoutePerPrefix

func (*Server) Run added in v4.1.4

func (s *Server) Run(addrs ...Address)

Run allow to launch multiple server from a single call. It take an vaarg Address param argument. WaitAndStop is called via defer.

func (*Server) SetRouter

func (s *Server) SetRouter() *mux.Router

SetRouter create a mux.Handler router and then : register the middle wares, register the user defined routes per prefix, and return the routes handler

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context)

Shutdown call the framework shutdown to stop all running server

func (*Server) Start

func (s *Server) Start(addr string)

Start expose an server to an HTTP endpoint

func (*Server) StartTLS

func (s *Server) StartTLS(addr string, tlsStuffs ITLSConfig)

StartTLS expose an server to an HTTPS address.

func (*Server) WaitAndStop

func (s *Server) WaitAndStop()

WaitAndStop wait for all servers to terminate. Use of a sync.waitGroup to properly wait all running servers.

type TLSConfig

type TLSConfig struct {
	Cert     string `json:"cert" mapstructur:"cert"`
	Key      string `json:"key" mapstructur:"key"`
	Ca       string `json:"ca" mapstructur:"ca"`
	Insecure bool   `json:"insecure" mapstructur:"insecure"`
}

TLSConfig contain the tls config passed by the config file. It implement ITLSConfig

func (TLSConfig) Empty added in v4.1.0

func (config TLSConfig) Empty() bool

GetInsecure implemte ITLSConfig

func (TLSConfig) GetCa added in v4.3.1

func (config TLSConfig) GetCa() string

GetCert implemte ITLSConfig

func (TLSConfig) GetCert

func (config TLSConfig) GetCert() string

GetCert implemte ITLSConfig

func (TLSConfig) GetInsecure

func (config TLSConfig) GetInsecure() bool

GetInsecure implemte ITLSConfig

func (TLSConfig) GetKey

func (config TLSConfig) GetKey() string

GetKey implemte ITLSConfig

func (TLSConfig) String added in v4.1.0

func (config TLSConfig) String() string

String implement Stringer interface

type ValidationError

type ValidationError struct {
	Status int                                    `json:"status"`
	Error  validator.ValidationErrorsTranslations `json:"message"`
}

ValidationError is returned in case of form / query validation error see gtihub.com/go-playground/validator.v10

type WorkerLauncher

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

WorkerLauncher hold the different workers and wait for them to finish before exiting.

func CreateWorkerLauncher

func CreateWorkerLauncher(wg *sync.WaitGroup, cancel context.CancelFunc) WorkerLauncher

CreateWorkerLauncher initialize and return a WorkerLauncher instance.

func (*WorkerLauncher) Start

func (l *WorkerLauncher) Start(name string, fn func() error)

Start launch a worker job.

type XMLResponse added in v4.3.0

type XMLResponse interface {
	// JSONBlob answer the JSON content with the status code op
	XMLBlob(op int, content []byte) error
}

Directories

Path Synopsis
Package handler implement some extra handler to the webfmwk.
Package handler implement some extra handler to the webfmwk.
Package log implement the Log interface used by the webfmwk
Package log implement the Log interface used by the webfmwk
Package webfmwktest implement wrapper around httptest
Package webfmwktest implement wrapper around httptest

Jump to

Keyboard shortcuts

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