Documentation
¶
Overview ¶
Package restapi provides a chi-based HTTP server with built-in middleware (structured request logging, Prometheus metrics, recoverer), a /ping health endpoint, and optional /debug pprof support.
Example ¶
package main
import (
"context"
"fmt"
"net/http"
"os"
"strings"
"sync"
"time"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"github.com/habaduday/go-lib/config"
)
func main() {
logger := newExampleLogger()
cfg, err := config.Load()
if err != nil {
fmt.Println(err)
return
}
cfg.API.Host = "localhost"
cfg.API.Port = 18080
exampleSpec := `{"openapi":"3.0.0","info":{"title":"Test"}}`
srv, err := New(cfg, WithLogger(logger), WithOpenAPI(strings.NewReader(exampleSpec)))
if err != nil {
fmt.Println(err)
return
}
wg := sync.WaitGroup{}
wg.Go(func() {
if err := srv.Run(); err != nil {
fmt.Println(err)
}
})
_, err = http.Get("http://localhost:18080/ping")
if err != nil {
fmt.Println(err)
return
}
_, err = http.Get("http://localhost:18080/docs")
if err != nil {
fmt.Println(err)
return
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_ = srv.Shutdown(ctx)
wg.Wait()
_ = logger.Sync()
}
func newExampleLogger() *zap.Logger {
encoderCfg := zapcore.EncoderConfig{
MessageKey: "msg",
LevelKey: "level",
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString("<time>")
},
EncodeDuration: func(d time.Duration, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString("<elapsed>")
},
}
core := zapcore.NewCore(
zapcore.NewJSONEncoder(encoderCfg),
os.Stdout,
zapcore.InfoLevel,
)
return zap.New(&maskingCore{Core: core})
}
type maskingCore struct {
zapcore.Core
}
func (c *maskingCore) Write(entry zapcore.Entry, fields []zapcore.Field) error {
for i, f := range fields {
if f.Key == "size" {
fields[i] = zap.String("size", "<size>")
}
}
return c.Core.Write(entry, fields)
}
func (c *maskingCore) Check(entry zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
if c.Enabled(entry.Level) {
return ce.AddCore(entry, c)
}
return ce
}
func (c *maskingCore) With(fields []zapcore.Field) zapcore.Core {
return &maskingCore{Core: c.Core.With(fields)}
}
Output: {"level":"info","msg":"enabling openapi endpoint"} {"level":"info","msg":"starting api server","addr":"localhost:18080"} {"level":"info","msg":"GET /docs","time":"<time>","latency":"<elapsed>","remote_ip":"","host":"localhost:18080","method":"GET","uri":"/docs","status":200,"size":"<size>","user_agent":"Go-http-client/1.1","trace_id":""} {"level":"info","msg":"shutting down api server"}
Index ¶
- func MethodNotAllowedHandler(w http.ResponseWriter, r *http.Request)
- func NotFoundHandler(w http.ResponseWriter, r *http.Request)
- func OpenAPIHandler(basePath string, jsonSpec []byte, next http.Handler) http.Handler
- func PingHandler(cfg *config.Config) http.HandlerFunc
- type Error
- type LogFormatter
- type Server
- type ServerOption
- type SubRoute
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func MethodNotAllowedHandler ¶
func MethodNotAllowedHandler(w http.ResponseWriter, r *http.Request)
MethodNotAllowedHandler writes a 405 JSON response.
func NotFoundHandler ¶
func NotFoundHandler(w http.ResponseWriter, r *http.Request)
NotFoundHandler writes a 404 JSON response.
func OpenAPIHandler ¶
OpenAPIHandler returns an http.Handler that serves the OpenAPI spec at {basePath}/openapi.json and renders Swagger UI at {basePath}.
NOTE: the basePath must be the same as handler mount point (/docs if empty)
func PingHandler ¶
func PingHandler(cfg *config.Config) http.HandlerFunc
PingHandler returns an HTTP handler that responds with service status, name, version and hostname as JSON. Useful for health checks.
Types ¶
type LogFormatter ¶
LogFormatter implements chi's LogFormatter interface to produce structured request logs via zap. If Skip returns true for a request, logging is suppressed for that request.
func (LogFormatter) NewLogEntry ¶
func (l LogFormatter) NewLogEntry(r *http.Request) middleware.LogEntry
NewLogEntry creates a new middleware.LogEntry for the given request.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server wraps an HTTP server with a chi router, built-in middleware (zap request logging, Prometheus metrics, recoverer), a /ping health endpoint, and optional /debug pprof when Debug is enabled.
func New ¶
func New(cfg *config.Config, options ...ServerOption) (*Server, error)
New creates a Server from config. It builds a chi router with built-in middleware. Returns an error if cfg is nil or any option failed to apply
func (*Server) Mount ¶
Mount adds provided subroutes. Returns an error if subroute prefix is empty or handler is nil
type ServerOption ¶
ServerOption configures a Server during construction.
func WithLogger ¶
func WithLogger(logger *zap.Logger) ServerOption
WithLogger sets the logger used by the server.
func WithMiddlewares ¶
func WithMiddlewares(mws ...func(http.Handler) http.Handler) ServerOption
WithMiddlewares appends user-defined HTTP middlewares to the server's middleware stack. They run after the built-in middlewares (logging, metrics, tracing, recoverer).
func WithOpenAPI ¶
func WithOpenAPI(spec io.Reader) ServerOption
WithOpenAPI mounts an OpenAPI/Swagger UI endpoint. It accepts an OpenAPI spec in JSON or YAML format and serves it at /docs with Swagger UI.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package middlewares provides custom chi HTTP middlewares for Prometheus request metrics (count, duration, response size) and OpenTelemetry tracing integration.
|
Package middlewares provides custom chi HTTP middlewares for Prometheus request metrics (count, duration, response size) and OpenTelemetry tracing integration. |