webgo
packagemoduleThis package is not in the latest version of its module.
Details
Valid go.mod file
The Go module system was introduced in Go 1.11 and is the official dependency management solution for Go.
Redistributable license
Redistributable licenses place minimal restrictions on how software can be used, modified, and redistributed.
Tagged version
Modules with tagged versions give importers more predictable builds.
Stable version
When a project reaches major version v1 it is considered stable.
- Learn more about best practices
Repository
Links
README¶
WebGo v2.4.0
WebGo is a minimalistic web framework for Go. It gives you the following features.
- Multiplexer
- Chaining handlers
- Middleware
- Webgo context
- Helper functions
- HTTPS ready
- Graceful shutdown
- Logging interface
WebGo's route handlers have the same signature as the standard libraries' HTTP handler.i.e.http.HandlerFunc
Multiplexer
WebGo multiplexer lets you define URIs with or without parameters. Following are the ways you candefine a URI for a route.
api/users- no URI parametersapi/users/:userID- named URI parameter; the value would be available in the keyuserIDapi/:wildcard*- wildcard URIs; every router confirming to/api/path/to/anythingwould bematched by this route, and the path would be available inside the named URI parameterwildcard
If there are multiple routes which have matching path patterns, the first one defined in the list of routes takes precedence and is executed.
Chaining
Chaining lets you handle a route with multiple handlers, and are executed in sequence.All handlers in the chain arehttp.HandlerFuncs.
routes := []*webgo.Route{{// A label for the API/URIName: "OPTIONS",// request typeMethod: http.MethodOptions,Pattern: "/:w*",FallThroughPostResponse: true,TrailingSlash: true,// route handlerHandlers: []http.HandlerFunc{CorsOptions("*"), handler},}, }router := webgo.NewRouter(*webgo.Config, routes)Middleware
WebGo middleware signature isfunc(http.ResponseWriter, *http.Request, http.HandlerFunc).Itsrouter exposes a methodUse to add a middleware to the app. e.g.
func accessLog(rw http.ResponseWriter, req *http.Request, next http.HandlerFunc) {start := time.Now()next(rw, req)end := time.Now()log := end.Format("2006-01-02 15:04:05 -0700 MST") + " " + req.Method + " " + req.URL.String() + " " + end.Sub(start).String()fmt.Println(log)}router := webgo.NewRouter(*webgo.Config, []*Route)router.Use(accessLog)You can add as many middleware as you want, middleware execution order is in the same order asthey were added. Execution of the middlware is stopped if you do not callnext().
Context
Any app specific context can be set inside the router, and is available inside every requesthandler via HTTP request context. The Webgo Context (injected into HTTP request context) also provides the route configuration itself as well as the URI parameters.
router := webgo.NewRouter(*webgo.Config, []*Route)router.AppContext = map[string]interface{}{"dbHandler": <db handler>}func API1(rw http.ResponseWriter, req *http.Request) {wctx := webgo.Context(req)wctx.Params // URI paramters, a map of string of string, where the keys are the named URI parameterswctx.Route // is the route configuration itself for which the handler matchedwctx.AppContext // is the app context configured in `router.AppContext`}Helper functions
WebGo has certain helper functions for which the responses are wrapped in a struct according toerror or successful response. All success responses are wrapped in the struct
type dOutput struct {Data interface{} `json:"data"`Status int `json:"status"`}JSON output looks like
{"data": <any data>,"status: <HTTP response status code, integer>}All the error responses are wrapped in the struct
type errOutput struct {Errors interface{} `json:"errors"`Status int `json:"status"`}JSON output for error response looks like
{"errors": <any data>,"status": <HTTP response status code, integer>}It provides the following helper functions.
- SendHeader(w http.ResponseWriter, rCode int) - Send only an HTTP response header with the requiredresponse code.
- Send(w http.ResponseWriter, contentType string, data interface{}, rCode int) - Send any response
- SendResponse(w http.ResponseWriter, data interface{}, rCode int) - Send response wrapped inWebGo's default response struct
- SendError(w http.ResponseWriter, data interface{}, rCode int) - Send an error wrapped in WebGo'sdefault error response struct
- Render(w http.ResponseWriter, data interface{}, rCode int, tpl *template.Template) - Render rendersa Go template, with the requierd data & response code.
- Render404(w http.ResponseWriter, tpl *template.Template) - Renders a static 404 message
- R200(w http.ResponseWriter, data interface{}) - Responds with the provided data, with HTTP 200status code
- R201(w http.ResponseWriter, data interface{}) - Same as R200, but status code 201
- R204(w http.ResponseWriter) - Sends a reponse header with status code 201 and no response body.
- R302(w http.ResponseWriter, data interface{}) - Same as R200, but with status code 302
- R400(w http.ResponseWriter, data interface{}) - Same as R200, but with status code 400 andresponse wrapped in error struct
- R403(w http.ResponseWriter, data interface{}) - Same as R400, but with status code 403
- R404(w http.ResponseWriter, data interface{}) - Same as R400, but with status code 404
- R406(w http.ResponseWriter, data interface{}) - Same as R400, but with status code 406
- R451(w http.ResponseWriter, data interface{}) - Same as R400, but with status code 451
- R500(w http.ResponseWriter, data interface{}) - Same as R400, but with status code 500
HTTPS ready
HTTPS server can be started easily, just by providing the key & cert file required.You can also have both HTTP & HTTPS servers running side by side.
Start HTTPS server
cfg := webgo.Config{Port: "80",HTTPSPort: "443",CertFile: "/path/to/certfile",KeyFile: "/path/to/keyfile",}router := webgo.NewRouter(&cfg, []*Route)router.StartHTTPS()Starting both HTTP & HTTPS server
router := webgo.NewRouter(*webgo.Config, []*Route)go router.StartHTTPS()router.Start()Graceful shutdown
Graceful shutdown lets you shutdown your server without affecting any live connections/clientsconnected to your server.
func main() {osSig := make(chan os.Signal, 5)cfg := webgo.Config{Host: "",Port: "8080",ReadTimeout: 15 * time.Second,WriteTimeout: 60 * time.Second,ShutdownTimeout: 15 * time.Second,}router := webgo.NewRouter(&cfg, getRoutes())go func() {<-osSig// Initiate HTTP server shutdownerr := router.Shutdown()if err != nil {fmt.Println(err)os.Exit(1)} else {fmt.Println("shutdown complete")os.Exit(0)}// err := router.ShutdownHTTPS()// if err != nil {// fmt.Println(err)// os.Exit(1)// } else {// fmt.Println("shutdown complete")// os.Exit(0)// }}()signal.Notify(osSig, os.Interrupt, syscall.SIGTERM)router.Start()for {// Prevent main thread from exiting, and wait for shutdown to completetime.Sleep(time.Second * 1)}}Logging interface
Webgo has a singleton, global variableLOGHANDLER of typeLogger. Logger is an interface whichhas the following methods:
type Logger interface {Debug(data ...interface{})Info(data ...interface{})Warn(data ...interface{})Error(data ...interface{})Fatal(data ...interface{})}The singleton variable is initialized in the package'sinit() function. The default logger whichis initialized in Webgo has uses Go's standardlog library.
A custom logger which implements the same interface can be assigned to the singleton to use your ownlogger.
package mainimport ("github.com/bnkamalesh/webgo")func main() {webgo.LOGHANDLER = customLogger}Full sample
package mainimport ("net/http""time""github.com/bnkamalesh/webgo/middleware""github.com/bnkamalesh/webgo")func helloWorld(w http.ResponseWriter, r *http.Request) {wctx := webgo.Context(r)webgo.R200(w,wctx.Params, // URI parameters)}func getRoutes() []*webgo.Route {return []*webgo.Route{&webgo.Route{Name: "helloworld", // A label for the API/URI, this is not used anywhere.Method: http.MethodGet, // request typePattern: "/", // Pattern for the routeHandlers: []http.HandlerFunc{helloWorld}, // route handler},&webgo.Route{Name: "helloworld", // A label for the API/URI, this is not used anywhere.Method: http.MethodGet, // request typePattern: "/api/:param", // Pattern for the routeHandlers: []http.HandlerFunc{middleware.Cors(), helloWorld}, // route handler},}}func main() {cfg := webgo.Config{Host: "",Port: "8080",ReadTimeout: 15 * time.Second,WriteTimeout: 60 * time.Second,}router := webgo.NewRouter(&cfg, getRoutes())router.Use(middleware.AccessLog)router.Start()}Testing
URI parameters, route matching, HTTP server, HTTPS server, graceful shutdown and context fetching are tested in the tests provided.
$ cd $GOPATH/src/github.com/bnkamalesh/webgo$ go test
Documentation¶
Overview¶
Package webgo is a lightweight framework for building web apps. It has a multiplexer,middleware plugging mechanism & context management of its own. The primary goalof webgo is to get out of the developer's way as much as possible. i.e. it doesnot enforce you to build your app in any particular pattern, instead just helps youget all the trivial things done faster and easier.
e.g.1. Getting named URI parameters.2. Multiplexer for regex matching of URI and such.3. Inject special app level configurations or any such objects to the request context as required.
Index¶
- Constants
- Variables
- func R200(w http.ResponseWriter, data interface{})
- func R201(w http.ResponseWriter, data interface{})
- func R204(w http.ResponseWriter)
- func R302(w http.ResponseWriter, data interface{})
- func R400(w http.ResponseWriter, data interface{})
- func R403(w http.ResponseWriter, data interface{})
- func R404(w http.ResponseWriter, data interface{})
- func R406(w http.ResponseWriter, data interface{})
- func R451(w http.ResponseWriter, data interface{})
- func R500(w http.ResponseWriter, data interface{})
- func Render(w http.ResponseWriter, data interface{}, rCode int, tpl *template.Template)
- func Render404(w http.ResponseWriter, tpl *template.Template)
- func Send(w http.ResponseWriter, contentType string, data interface{}, rCode int)
- func SendError(w http.ResponseWriter, data interface{}, rCode int)
- func SendHeader(w http.ResponseWriter, rCode int)
- func SendResponse(w http.ResponseWriter, data interface{}, rCode int)
- type Config
- type ErrorData
- type Logger
- type Route
- type Router
- type WC
Constants¶
const (// HeaderContentType is the key for mentioning the response header content typeHeaderContentType = "Content-Type"// JSONContentType is the MIME type when the response is JSONJSONContentType = "application/json"// HTMLContentType is the MIME type when the response is HTMLHTMLContentType = "text/html; charset=UTF-8"// ErrInternalServer to send when there's an internal server errorErrInternalServer = "Internal server error.")
Variables¶
var (// ErrInvalidPort is the error returned when the port number provided in the config file is invalidErrInvalidPort =errors.New("Port number not provided or is invalid (should be between 0 - 65535)"))
Functions¶
funcR400¶
func R400(whttp.ResponseWriter, data interface{})
R400 - Invalid request, any incorrect/erraneous value in the request body
funcR406¶
func R406(whttp.ResponseWriter, data interface{})
R406 - Unacceptable header. For any error related to values set in header
funcR451¶
func R451(whttp.ResponseWriter, data interface{})
R451 - Resource taken down because of a legal request
funcRender¶
func Render(whttp.ResponseWriter, data interface{}, rCodeint, tpl *template.Template)
Render is used for rendering templates (HTML)
funcRender404¶
func Render404(whttp.ResponseWriter, tpl *template.Template)
Render404 - used to render a 404 page
funcSend¶
func Send(whttp.ResponseWriter, contentTypestring, data interface{}, rCodeint)
Send sends a completely custom response without wrapping in the`{data: <data>, status: <int>` struct
funcSendError¶
func SendError(whttp.ResponseWriter, data interface{}, rCodeint)
SendError is used to respond to any request with an error
funcSendHeader¶
func SendHeader(whttp.ResponseWriter, rCodeint)
SendHeader is used to send only a response header, i.e no response body
funcSendResponse¶
func SendResponse(whttp.ResponseWriter, data interface{}, rCodeint)
SendResponse is used to respond to any request (JSON response) based on the code, data etc.
Types¶
typeConfig¶
type Config struct {// Host is the host on which the server is listeningHoststring `json:"host,omitempty"`// Port is the port number where the server has to listen for the HTTP requestsPortstring `json:"port,omitempty"`// CertFile is the TLS/SSL certificate file path, required for HTTPSCertFilestring `json:"certFile,omitempty"`// KeyFile is the filepath of private key of the certificateKeyFilestring `json:"keyFile,omitempty"`// HTTPSPort is the port number where the server has to listen for the HTTP requestsHTTPSPortstring `json:"httpsPort,omitempty"`// ReadTimeout is the maximum duration for which the server would read a requestReadTimeouttime.Duration `json:"readTimeout,omitempty"`// WriteTimeout is the maximum duration for which the server would try to respondWriteTimeouttime.Duration `json:"writeTimeout,omitempty"`// InsecureSkipVerify is the HTTP certificate verificationInsecureSkipVerifybool `json:"insecureSkipVerify,omitempty"`// ShutdownTimeout is the duration in which graceful shutdown is completed, in secondsShutdownTimeouttime.Duration}Config is used for reading app's configuration from json file
typeLogger¶
type Logger interface {Debug(data ...interface{})Info(data ...interface{})Warn(data ...interface{})Error(data ...interface{})Fatal(data ...interface{})}Service defines all the logging methods to be implemented
var LOGHANDLERLoggertypeRoute¶
type Route struct {// Name is unique identifier for the routeNamestring// Method is the HTTP request method/typeMethodstring// Pattern is the URI pattern to matchPatternstring// TrailingSlash if set to true, the URI will be matched with or without// a trailing slash. Note: It does not *do* a redirect.TrailingSlashbool// FallThroughPostResponse if enabled will execute all the handlers even if a response was already sent to the clientFallThroughPostResponsebool// Handlers is a slice of http.HandlerFunc which can be middlewares or anything else. Though only 1 of them will be allowed to respond to client.// subsequent writes from the following handlers will be ignoredHandlers []http.HandlerFunc// contains filtered or unexported fields}Route defines a route for each API
typeRouter¶
type Router struct {// NotFound is the generic handler for 404 resource not found responseNotFoundhttp.HandlerFunc// AppContext holds all the app specific context which is to be injected into all HTTP// request contextAppContext map[string]interface{}// contains filtered or unexported fields}Router is the HTTP router
funcNewRouter¶
NewRouter initializes returns a new router instance with all the configurations and routes set
func (*Router)ShutdownHTTPS¶
ShutdownHTTPS gracefully shuts down HTTPS server
func (*Router)Start¶
func (router *Router) Start()
Start starts the HTTP server with the appropriate configurations
func (*Router)StartHTTPS¶
func (router *Router) StartHTTPS()
StartHTTPS starts the server with HTTPS enabled
func (*Router)Use¶
func (rtr *Router) Use(f func(http.ResponseWriter, *http.Request,http.HandlerFunc))
Use adds a middleware layer
Directories¶
| Path | Synopsis |
|---|---|
Package middleware defines the signature/type which can be added as a middleware to Webgo. | Package middleware defines the signature/type which can be added as a middleware to Webgo. |