serbewr

April 18, 2026 · View on GitHub

Pronounced "server". D'oooh you kno.

Built on net/http with routing via Go 1.22+ ServeMux patterns.

srv, _ := serbewr.New()                    // defaults from env vars
srv, _ := serbewr.NewWithConfig(config)     // explicit config

Router

Groups, nested groups, per-group middleware, method-based routing.

router := &serbewr.Router{
    GlobalMiddlewares: []middleware.Middleware{
        middleware.RequestID(),
        middleware.Logger(),
        middleware.Recovery(),
        middleware.SecurityHeaders(),
        middleware.CORS(),
    },
    Static: []serbewr.StaticRouteConfig{
        {Dir: "./static", Path: "/static"},
    },
    Groups: []serbewr.GroupConfig{
        {
            Path: "/api/v1",
            Routes: []serbewr.RouteConfig{
                {Method: http.MethodGet, Path: "/users", Handler: listUsers},
                {Method: http.MethodPost, Path: "/users", Handler: createUser},
            },
        },
        {
            Path: "/admin",
            Middlewares: []middleware.Middleware{
                middleware.BasicAuth(middleware.WithBasicAuthUsers(users)),
            },
            Routes: []serbewr.RouteConfig{
                {Method: http.MethodGet, Path: "/stats", Handler: adminStats},
            },
        },
    },
}

srv.Start(ctx, router)

You can also use the root group directly:

root := srv.GetRootGroup()
root.GET("/health", srv.HealthHandler)
root.POST("/upload", srv.FileUploadHandler("./uploads"))

api := root.Group("/api/v1", authMiddleware)
api.GET("/users", listUsers)
api.POST("/users", createUser)

Built-in handlers

HealthHandler — returns {"status": "ok", "timestamp": "..."}.

EchoHandler — echoes back method, path, query, headers (sensitive headers filtered), and body. Useful for debugging.

FileUploadHandler — multipart file upload with configurable filename strategy:

srv.FileUploadHandler("./uploads",
    serbewr.WithFilenamePrependType(serbewr.FilenamePrependTypeUUID),     // default
    serbewr.WithFilenamePrependType(serbewr.FilenamePrependTypeDateTime), // 2024_01_15_...
    serbewr.WithFilenamePrependType(serbewr.FilenamePrependTypeNone),     // original name
    serbewr.WithFileUploadHandlerPostprocessor(func(resp map[string]any, r *http.Request) (map[string]any, error) {
        resp["custom_field"] = "value"
        return resp, nil
    }),
)

Filenames are sanitized (filepath.Base) to prevent path traversal. Files are created with 0600 permissions and O_EXCL (won't overwrite existing files).

Static file serving

Path traversal protection (both .. components and symlink resolution), file existence caching with LRU eviction, and optional directory indexing.

Static: []serbewr.StaticRouteConfig{
    {
        Dir:                   "./public",
        Path:                  "/static",
        DirectoryIndexingType: serbewr.DirectoryIndexingTypeHTML, // or JSON, or None
    },
}

Directories with an index.html serve it automatically. Without one, behavior depends on DirectoryIndexingType.

TLS

export HTTP_SERVER_TLSENABLED=true
export HTTP_SERVER_TLSCERTFILE=/path/to/cert.pem
export HTTP_SERVER_TLSKEYFILE=/path/to/key.pem

HTTP and HTTPS servers run simultaneously on separate ports.

Configuration

All config is read from environment variables with sensible defaults. Or just use NewWithConfig(config) and set everything in code — your call.

VariableDefaultDescription
HTTP_SERVER_LISTENADDRESS127.0.0.1:8080HTTP listen address
HTTP_SERVER_READTIMEOUT15sMax time to read request
HTTP_SERVER_READHEADERTIMEOUT10sMax time to read headers
HTTP_SERVER_WRITETIMEOUT30sMax time to write response
HTTP_SERVER_IDLETIMEOUT60sKeep-alive idle timeout
HTTP_SERVER_SHUTDOWNTIMEOUT10sGraceful shutdown timeout
HTTP_SERVER_MAXHEADERBYTES1MBMax header size
HTTP_SERVER_FILEUPLOADMAXMEMORY32MBMax upload memory before temp file
HTTP_SERVER_SERVICENAMEhttp-serverService name for logging
HTTP_SERVER_TLSENABLEDfalseEnable HTTPS
HTTP_SERVER_TLSLISTENADDRESS127.0.0.1:8443HTTPS listen address
HTTP_SERVER_TLSCERTFILETLS certificate path
HTTP_SERVER_TLSKEYFILETLS private key path