Documentation
¶
Overview ¶
Package gear is the implementation of Gear framewrok.
Gear is about two things: middleware and encoding(binding).
1. Middleware
A middleware is a function that wraps another HTTP handler and performs some action before or after the wrapped handler executes.
A middleware in Gear is the Middleware interface, the wrapping is implemented by the Wrap and other Wrap... functions.
For example the following code add logging to a handler:
var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Handle the request
})
handler = gear.Wrap(handler, gear.Logger(nil))
or if you want to log the entire server:
var server = &http.Server{}
gear.WrapServer(server)
or listen and serve with logger:
gear.ListenAndServe("", nil, gear.Logger(nil))
Here is another example of doing authentication:
var authMiddleware = gear.MiddlewareFunc(func(g *gear.Gear, next func(*gear.Gear)) {
if !adminAuth(g.R) {
// Authentication failed, sends 401 and skips the handler.
g.Code(http.StatusUnauthorized)
return
}
// Executes the handler.
next(g)
})
gear.NewGroup("/admin", nil, authMiddleware).
HandleFunc("action1", func(w http.ResponseWriter, r *http.Request) {
// Do action1 of administrator
}).
HandleFunc("action2", func(w http.ResponseWriter, r *http.Request) {
// Do action2 of administrator
})
gear.ListenAndServe("", nil)
See package examples section for more examples.
Index ¶
- Constants
- Variables
- func ListenAndServe(addr string, handler http.Handler, middlewares ...Middleware) error
- func ListenAndServeTLS(addr, certFile, keyFile string, handler http.Handler, ...) error
- func Log(level slog.Level, msg string, args ...any)
- func LogD(msg string, args ...any)
- func LogE(msg string, args ...any)
- func LogI(msg string, args ...any)
- func LogIfErr(err error) error
- func LogIfErrT[T any](ret T, err error) error
- func LogW(msg string, args ...any)
- func NewTestServer(handler http.Handler, middlewares ...Middleware) *httptest.Server
- func NoLog() *slog.Logger
- func Wrap(handler http.Handler, middlewares ...Middleware) http.Handler
- func WrapFunc(f func(w http.ResponseWriter, r *http.Request), middlewares ...Middleware) http.Handler
- func WrapServer(server *http.Server, middlewares ...Middleware) *http.Server
- type Gear
- func (g *Gear) Code(code int)
- func (g *Gear) ContextValue(key any) any
- func (g *Gear) DecodeBody(v any) error
- func (g *Gear) DecodeForm(v any) error
- func (g *Gear) DecodeHeader(v any) error
- func (g *Gear) DecodeQuery(v any) error
- func (g *Gear) JSON(v any) error
- func (g *Gear) JSONResponse(code int, v any) error
- func (g *Gear) MustDecodeBody(v any) (err error)
- func (g *Gear) MustDecodeForm(v any) (err error)
- func (g *Gear) MustDecodeHeader(v any) (err error)
- func (g *Gear) MustDecodeQuery(v any) (err error)
- func (g *Gear) SetContextValue(key, val any)
- func (g *Gear) Stop()
- func (g *Gear) String(body string) error
- func (g *Gear) StringResponse(code int, body string) error
- func (g *Gear) StringResponsef(code int, format string, a ...any) error
- func (g *Gear) Write(r io.Reader) error
- func (g *Gear) XML(v any) error
- func (g *Gear) XMLResponse(code int, v any) error
- type Group
- type LoggerOptions
- type Middleware
- type MiddlewareFunc
- type MiddlewareName
- type PathInterceptor
Examples ¶
Constants ¶
const ( // LoggerMethodKey is the key used by [Logger] for the HTTP method of HTTP request. // The associated Value is a string. LoggerMethodKey = "method" // LoggerMethodKey is the key used by [Logger] for the host of HTTP request. // The associated Value is a string. LoggerHostKey = "host" // LoggerMethodKey is the key used by [Logger] for the URL of HTTP request. // The associated Value is a string. LoggerURLKey = "URL" // LoggerMethodKey is the group key used by [Logger] for the header of HTTP request. // The associated Value in group is a string. LoggerHeaderKey = "header" )
Variables ¶
var RawLogger *slog.Logger = slog.Default()
RawLogger used by Gear. Do not set a nil Logger, using log level to control output. See NoLog.
Functions ¶
func ListenAndServe ¶
func ListenAndServe(addr string, handler http.Handler, middlewares ...Middleware) error
ListenAndServe calls http.ListenAndServe(addr, Wrap(handler, middlewares...)). If handler is nil, http.DefaultServeMux wil be used.
Example ¶
package main
import (
"net/http"
"github.com/mkch/gear"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
var g = gear.G(r)
// Use g here.
_ = g
})
gear.ListenAndServe(":8080", nil)
}
func ListenAndServeTLS ¶
func ListenAndServeTLS(addr, certFile, keyFile string, handler http.Handler, middlewares ...Middleware) error
ListenAndServe calls http.ListenAndServeTLS(addr, certFile, keyFile, Wrap(handler, middlewares...)). If handler is nil, http.DefaultServeMux wil be used.
Example ¶
package main
import (
"net/http"
"github.com/mkch/gear"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
var g = gear.G(r)
// Use g here.
_ = g
})
gear.ListenAndServeTLS(":8080", "certfile", "keyfile", nil)
}
func LogIfErr ¶
LogIfErr logs err at slog.LevelError with RawLogger if err != nil. The log message has attribute {"err":err}. LogIfErr returns err. This function is convenient to log non-nil return value. For example:
LogIfErr(g.JSON(v))
Example ¶
package main
import (
"github.com/mkch/gear"
)
func main() {
var (
g *gear.Gear
v any
) // From somewhere else.
gear.LogIfErr(g.JSON(v))
}
func LogIfErrT ¶
LogIfErrT logs ret and err at slog.LevelError with RawLogger if err != nil. The log message has attribute {"ret": ret, "err":err}. LogIfErrorT returns err. This function is convenient to log non-nil return value. For example:
LogIfErrT(fmt.Println("msg"))
Example ¶
package main
import (
"fmt"
"github.com/mkch/gear"
)
func main() {
gear.LogIfErrT(fmt.Println("msg"))
}
func NewTestServer ¶
func NewTestServer(handler http.Handler, middlewares ...Middleware) *httptest.Server
Server calls httptest.NewServer() with Wrap(handler, middlewares...)).
Example ¶
package main
import (
"net/http"
"github.com/mkch/gear"
)
func main() {
var server = gear.NewTestServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var g = gear.G(r)
// Use g here.
_ = g
}))
defer server.Close()
}
func NoLog ¶
NoLog returns a Logger discards all messages and has a level of -99. The following code disables message logging to a certain extent:
RawLogger = NoLog()
func Wrap ¶
func Wrap(handler http.Handler, middlewares ...Middleware) http.Handler
Wrap wraps handler and adds Gear to it. If handler is nil, http.DefaultServeMux will be used. Parameter middlewares will be added to the result Handler. Middlewares will be served in reversed order of addition, so panic recovery middleware should be added last to catch all panics.
Example ¶
package main
import (
"net/http"
"github.com/mkch/gear"
)
func main() {
var handler http.Handler = gear.Wrap(
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var g = gear.G(r)
// Use g here.
_ = g
}))
http.Handle("/", handler)
}
func WrapFunc ¶
func WrapFunc(f func(w http.ResponseWriter, r *http.Request), middlewares ...Middleware) http.Handler
WrapFunc wraps f to a handler and adds Gear to it. If f is nil, http.DefaultServeMux.ServeHTTP will be used. Parameter middlewares will be added to the result Handler. Middlewares will be served in reversed order of addition , so panic recovery middleware should be added last to catch all panics.
Example ¶
package main
import (
"net/http"
"github.com/mkch/gear"
)
func main() {
var handler http.Handler = gear.WrapFunc(
func(w http.ResponseWriter, r *http.Request) {
var g = gear.G(r)
// Use g here.
_ = g
})
http.Handle("/", handler)
}
func WrapServer ¶
func WrapServer(server *http.Server, middlewares ...Middleware) *http.Server
WrapServer wraps server.Handler using Wrap() and returns server itself.
Example ¶
package main
import (
"net/http"
"github.com/mkch/gear"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
var g = gear.G(r)
// Use g here.
_ = g
})
var server = gear.WrapServer(&http.Server{})
server.ListenAndServe()
}
Types ¶
type Gear ¶
type Gear struct {
R *http.Request // R of this request.
W http.ResponseWriter // W of this request.
// contains filtered or unexported fields
}
Gear, the core of this framework.
func (*Gear) ContextValue ¶
ContextValue returns the request context value associated with key, or nil if no value is associated with key.
func (*Gear) DecodeBody ¶
DecodeBody parses body and stores the result in the value pointed to by v. This method is a shortcut of encoding.DecodeBody(g.R, nil, v). See encoding.DecodeBody for more details.
Example ¶
package main
import (
"net/http"
"github.com/mkch/gear"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
type User struct {
Name string `map:"user"`
ID int `map:"id"`
}
var user User
gear.G(r).DecodeBody(&user)
// If the client posts a body:
//
// {
// "user": "USER1",
// "id": 100,
// }
//
// user equals User{"USER1", 100}
})
}
func (*Gear) DecodeForm ¶
DecodeFrom calls g.R.ParseForm(), decodes g.R.Form and stores the result in the value pointed by v. See encoding.DecodeForm for more details. Call ParseMultipartForm() of the request to include values in multi-part form.
func (*Gear) DecodeHeader ¶
DecodeHeader decodes g.R.Header and stores the result in the value pointed by v. See encoding.DecodeForm for more details.
func (*Gear) DecodeQuery ¶
DecodeQuery decodes r.URL.Query() and stores the result in the value pointed by v. See encoding.DecodeForm for more details.
func (*Gear) JSONResponse ¶
JSONResponse writes code and JSON encoding of v to the response.
func (*Gear) MustDecodeBody ¶
MustDecodeBody calls Gear.DecodeBody. If DecodeBody returns an error, MustDecodeBody returns it but also writes a http.StatusBadRequest response and stops the middleware processing.
func (*Gear) MustDecodeForm ¶
MustDecodeForm calls Gear.DecodeForm. If DecodeForm returns an error, MustDecodeForm returns it but also writes a http.StatusBadRequest response and stops the middleware processing.
func (*Gear) MustDecodeHeader ¶
MustDecodeHeader calls Gear.DecodeHeader. If DecodeHeader returns an error, MustDecodeHeader returns it but also writes a http.StatusBadRequest response and stops the middleware processing.
func (*Gear) MustDecodeQuery ¶
MustDecodeQuery calls Gear.DecodeQuery. If DecodeQuery returns an error, MustDecodeHeader returns it but also writes a http.StatusBadRequest response and stops the middleware processing.
func (*Gear) SetContextValue ¶
SetContextValue sets the request context value associated with key to val.
func (*Gear) Stop ¶
func (g *Gear) Stop()
Stop stops further middleware processing. Current middleware is unaffected.
func (*Gear) StringResponse ¶
StringResponse writes code and body to the response.
func (*Gear) StringResponsef ¶
StringResponsef writes code and then call fmt.Fprintf() to write the formated string.
type Group ¶
type Group struct {
// contains filtered or unexported fields
}
Group is prefix of a group of urls registered to http.ServeMux.
Example ¶
package main
import (
"net/http"
"github.com/mkch/gear"
)
func adminAuth() bool { return false }
func op1() {}
func main() {
gear.NewGroup("/admin", nil, gear.MiddlewareFunc(func(g *gear.Gear, next func(*gear.Gear)) {
// Handle admin authentication
if !adminAuth() {
http.Error(g.W, "", http.StatusUnauthorized)
return
}
// OK, go ahead.
next(g)
})).Handle("op1", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// The request path will be /admin/op1
op1() // Do the operation.
}))
}
func NewGroup ¶
func NewGroup(prefix string, mux *http.ServeMux, middlewares ...Middleware) *Group
NewGroup create a prefix of URLs on mux. When any URL has the prefix is requested, middlewares of group handle the request before URL handler. If mux is nil, http.DefaultServeMux will be used.
func (*Group) Group ¶
func (parent *Group) Group(prefix string, middlewares ...Middleware) *Group
Group creates a new URL prefix: path.Join(parent.prefix, prefix). When any URL has the prefix is requested, middlewares of parent group handle the request before the new group.
func (*Group) Handle ¶
Handle registers handler for a pattern which is the group prefix joined (path.Join) pattern parameter. The handler and middlewares are wrapped(see Wrap) before registering. Group's middlewares take precedence over the wrapped handler here. If handler is nil, an empty handler will be used.
func (*Group) HandleFunc ¶
func (group *Group) HandleFunc(pattern string, f func(w http.ResponseWriter, r *http.Request), middlewares ...Middleware) *Group
HandleFunc converts f to http.HandlerFunc and then call [Handle].
type LoggerOptions ¶
type LoggerOptions struct {
// Keys are the keys to log. Keys is a set of strings.
// Zero value means all Logger keys available(See LoggerMethodKey etc).
Keys map[string]bool
// HeaderKeys are the keys of HTTP header to log.
// HeaderKeys are only used when LoggerHeaderKey is in Keys.
// Zero value means not logging any header value.
HeaderKeys []string
// Attrs can be used to generate the slog.Attr slice to log for r.
// If Attrs is not nil, all fields above are ignored, the Logger just
// calls LogAttrs() to log the return value of this function.
// This function should not retain or modify r.
Attrs func(r *http.Request) []slog.Attr
}
LoggerOptions are options for Logger. A zero LoggerOptions consists entirely of zero values.
type Middleware ¶
type Middleware interface {
// Serve serves http and optionally pass control to next middleware by calling next(g).
Serve(g *Gear, next func(*Gear))
}
Middleware is a middleware used in Gear framework.
Example ¶
package main
import (
"fmt"
"log"
"github.com/mkch/gear"
)
// LogMiddleware is a middleware to log HTTP message.
type LogMiddleware log.Logger
// Serve implements gear.Middleware.
func (l *LogMiddleware) Serve(g *gear.Gear, next func(*gear.Gear)) {
fmt.Printf("%v %v", g.R.Method, g.R.URL)
// Call the real handler.
next(g)
}
func main() {
// Use LogMiddleware.
gear.ListenAndServe(":80", nil, (*LogMiddleware)(log.Default()))
}
func Logger ¶
func Logger(opt *LoggerOptions) Middleware
Logger returns a Middleware to log HTTP access log. If opt is nil, the default options are used.
Log level: LevelInfo
Log attributes:
"msg": "HTTP" "method": request.Method "host": request.Host "URL": request.URL "header.headerKey": request.Header[headerKey]
Example ¶
package main
import (
"github.com/mkch/gear"
)
func main() {
// logger logs HTTP method, host, URL(by default) and User-Agent header for request.
logger := gear.Logger(&gear.LoggerOptions{
HeaderKeys: []string{"User-Agent"},
})
gear.ListenAndServe(":http", nil, logger)
}
func MiddlewareFuncWitName ¶
func MiddlewareFuncWitName(f func(g *Gear, next func(*Gear)), name string) Middleware
MiddlewareFuncWitName is an adapter to allow the use of ordinary functions as Middleware. Parameter name will be used as the name of Middleware.
func PanicRecovery ¶
func PanicRecovery(addStack bool) Middleware
PanicRecovery returns a Middleware which recovers from panics, logs a LevelError message "recovered from panic" and sends 500 responses. The "value" attribute is set to panic value. If addStack is true, "stack" attribute is set to the string representation of the call stack. Panic recovery middleware should be added as the last middleware to catch all panics.
Example ¶
package main
import (
"github.com/mkch/gear"
)
func main() {
gear.ListenAndServe(":80", nil, gear.PanicRecovery(true))
}
type MiddlewareFunc ¶
MiddlewareFunc is an adapter to allow the use of ordinary functions as Middleware. If f is a function with the appropriate signature, MiddlewareFunc(f) is a Middleware that calls f.
Example ¶
package main
import (
"log"
"github.com/mkch/gear"
)
func main() {
var logMiddleware = gear.MiddlewareFuncWitName(func(g *gear.Gear, next func(*gear.Gear)) {
// Pre-processing.
log.Printf("Before request: Path=%v", g.R.URL.Path)
// Call the real handler.
next(g)
// Post-processing.
log.Printf("After request: Path=%v", g.R.URL.Path)
}, "logger")
gear.ListenAndServe(":80", nil, logMiddleware)
}
func (MiddlewareFunc) Serve ¶
func (m MiddlewareFunc) Serve(g *Gear, next func(*Gear))
Serve implements Serve() method of Middleware.
type MiddlewareName ¶
type MiddlewareName interface {
MiddlewareName() string
}
MiddlewareName is an optional interface to be implemented by a Middleware. If a Middleware implements this interface, MiddlewareName() will be used to get it's name, or the reflect type name will be used.
type PathInterceptor ¶
type PathInterceptor struct {
// contains filtered or unexported fields
}
PathInterceptor is a Middleware intercepting requests with matching URLs.
Example ¶
package main
import (
"net/http"
"github.com/mkch/gear"
)
func main() {
var handler = gear.MiddlewareFunc(func(g *gear.Gear, next func(*gear.Gear)) {
// Do admin authentication.
var authOK bool
if !authOK {
http.Error(g.W, "", http.StatusUnauthorized)
g.Stop()
}
})
// "/admin" and all paths starts with "/admin/" will be intercepted by handler.
gear.ListenAndServe(":80", nil, gear.NewPathInterceptor("/admin", handler))
}
func NewPathInterceptor ¶
func NewPathInterceptor(prefix string, handler Middleware) *PathInterceptor
NewPathInterceptor returns a PathInterceptor which executes handler when the path of request URL contains prefix.
func (*PathInterceptor) Serve ¶
func (m *PathInterceptor) Serve(g *Gear, next func(*Gear))
Serve implements Serve() method of Middleware.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package encoding implements data encoding and decoding used in Gear.
|
Package encoding implements data encoding and decoding used in Gear. |
|
Package impl contains implementation details of Gear.
|
Package impl contains implementation details of Gear. |
|
geartest
Package geartest contains test utilities used in Gear.
|
Package geartest contains test utilities used in Gear. |
|
Package validator provides a generic interface for value validation.
|
Package validator provides a generic interface for value validation. |
|
goplayground
module
|