strv backend go net
v0.8.0
Go package facilitating writing API applications in a fast and easy manner.
Definition of common errors.
Common functionality that comes in handy regardless of the used API architecture. net currently supports generating request IDs with some helper methods.
Wrapper around the Go native http server. http defines the Server that can be configured by the ServerConfig. Implemented features:
Run method.Server can be configured with a slog.Logger for logging important information during starting/ending of the server.Server listens for SIGINT and SIGTERM signals so it can be stopped by firing the signal.ServerConfig can be configured functions to be called before the Server ends.http defines several helper consctructs:
RequestIDMiddleware sets request id in to the context.RecoverMiddleware recovers from panic and sets panic object into the response writer for logging.LoggingMiddleware logs information about the request (method, path, status code, request id, duration of the request, error message and panic message).WriteResponse for writing a http response and WriteErrorResponse for writing an error http response. Writing of responses can be configured by ResponseOption.Starting the server:
package main
import (
...
httpx "go.strv.io/net/http"
)
func main() {
...
h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{
Level: level,
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
if a.Key == slog.TimeKey {
a.Value = slog.StringValue(a.Value.Time().Format("2006-01-02T15:04:05.000Z"))
}
return a
},
})
l := slog.New(h)
serverConfig := httpx.ServerConfig{
Addr: ":8080",
Handler: handler(), // define your http handler
Hooks: httpx.ServerHooks{
BeforeShutdown: []httpx.ServerHookFunc{
func(_ context.Context) {
storage.Close() // it may be useful for example to close a storage before the server ends
},
},
},
Limits: nil,
Logger: l.WithGroup("httpx.Server"), // the server expects *slog.Logger
}
server := httpx.NewServer(&serverConfig)
if err = server.Start(ctx); err != nil {
l.Error("HTTP server unexpectedly ended", slog.Any("error", err))
}
}Writing http responses:
func (h *Handler) GetUser(w http.ResponseWriter, r *http.Request) {
userID := userIDFromCtx(r.Context())
user, err := h.service.GetUser(r.Context(), userID)
if err != nil {
_ = httpx.WriteErrorResponse(w, http.StatusInternalServerError, httpx.WithErrorCode("ERR_UNKNOWN"))
return
}
userResp := model.ToUser(user)
_ = httpx.WriteResponse(w, userResp, http.StatusOK)
}