requestcore

package module
v2.0.0-...-0e31793 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 2, 2026 License: MIT Imports: 0 Imported by: 0

README

requestCore v2

Go Reference Go Version

A generics-first, framework-agnostic HTTP application toolkit for Go. Requires Go 1.27+.

Status: v2 has no released tags and is under active development. The API described here is the canonical kernel API and will remain the basis for the first stable v2 release, but minor refinements may still occur before a tag is cut. See MIGRATION.md for the migration guide and the list of deferred Tranche 5 features. v1 (the root module) remains supported and stable.

v2 builds on the root requestCore module with a canonical, stdlib-first kernel: typed endpoints, a framework-neutral routing contract, RFC 9457 problem responses, structured telemetry via slog, and typed session access — all without runtime type assertions or reflection in the request lifecycle.


Why v2?

v1 normalizes request parsing across Gin, Fiber, and net/http but couples handlers to the v1 webFramework stack and uses any for request/response types, requiring runtime type assertions. v2 introduces a canonical kernel that is framework-neutral and stdlib-only:

  • Canonical handler signaturefunc(ctx *request.Context, req Req) (Resp, error) flows types through bind → validate → execute → encode → commit → observe without type erasure.
  • Framework-neutral routingrouting.Handler is func(*request.Context, routing.Transport) error; Gin, Fiber, chi, and net/http adapters all translate the same canonical {id} pattern syntax.
  • RFC 9457 errors — every error is mapped to a response.Problem via a response.MapperRegistry, never serialized raw.
  • Structured telemetrytelemetry.Sink (default telemetry.SlogSink) records lifecycle events through slog, ingested by Splunk. The v2 kernel does not import webFramework.
  • Typed sessionssession.FromContext retrieves a *Session stored via request.Context typed keys; GetTyped[T]/SetTyped[T] give compile-time type safety.

Features

  • Typed endpointshandlers.Endpoint[Req, Resp] wraps endpoint.Endpoint[Req, Resp] with operation metadata; convenience constructors handlers.Get/Post/Put/Patch/Delete/Head.
  • Canonical executorendpoint.Executor runs the full lifecycle (bind → validate → execute → encode → commit → observe) with telemetry and problem mapping.
  • Resourcesresources.Resource[ID cmp.Ordered] with 7 CRUD operations, registered via the ResourceBuilder[ID] fluent API.
  • Typed session accesssession.FromContext, GetTyped[T] / SetTyped[T] generic accessors.
  • RFC 9457 problem responsesresponse.Problem and response.MapperRegistry for structured error mapping.
  • Framework-agnostic routing — Gin, Fiber, chi, net/http via adapters; canonical {id} path-parameter syntax.
  • Pluggable renderers — JSON, XML, text, CSV.
  • Structured telemetrytelemetry.Sink / telemetry.SlogSink for request and worker lifecycle events.
  • Background workers — bounded pool with retry and telemetry.Sink observability.
  • Scheduler — periodic background tasks with the same telemetry path.
  • Sessions & flash — cookie store with signed tokens.

Quick Start

package main

import (
    "context"
    "log"
    "os/signal"
    "syscall"

    "github.com/hmmftg/requestCore/v2/app"
    "github.com/hmmftg/requestCore/v2/handlers"
    "github.com/hmmftg/requestCore/v2/renderers"
    "github.com/hmmftg/requestCore/v2/request"
)

type HealthResp struct {
    Status string `json:"status"`
}

func main() {
    application, err := app.Bootstrap(app.Config{
        Framework: app.FrameworkChi,
        Renderer:  renderers.JSONRenderer{},
    })
    if err != nil {
        log.Fatal(err)
    }
    defer application.Close()

    // Register a typed GET endpoint using the canonical handler signature.
    err = handlers.GetEndpoint[struct{}, HealthResp](
        application.Router, application.Executor, "/health",
        func(ctx *request.Context, req struct{}) (HealthResp, error) {
            return HealthResp{Status: "healthy"}, nil
        },
    )
    if err != nil {
        log.Fatal(err)
    }

    ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
    defer stop()

    if err := application.StartWithContext(ctx, ":8080"); err != nil {
        log.Fatal(err)
    }
}

Core Concepts

Typed Endpoints

handlers.Endpoint[Req, Resp] is the typed descriptor for a route handler. It wraps endpoint.Endpoint[Req, Resp] with operation metadata (operation ID, HTTP method, route pattern) and satisfies the type-erased handlers.EndpointRuntime interface so resources can return heterogeneous typed endpoints without exposing type parameters at the registration boundary.

The canonical v2 handler signature is:

func(ctx *request.Context, req Req) (Resp, error)

The Req and Resp type parameters flow through the entire lifecycle without type erasure — bind, validate, execute, encode, and commit are all compile-time type-safe inside endpoint.Executor.

// Create a typed endpoint with explicit operation metadata.
ep := handlers.Post[CreateUserReq, CreateUserResp](
    "create-user", "/users",
    func(ctx *request.Context, req CreateUserReq) (CreateUserResp, error) {
        return CreateUserResp{ID: "1", Name: req.Name}, nil
    },
)

// Register it on a route group via the executor.
if err := handlers.RegisterEndpoint(application.Router, application.Executor, ep); err != nil {
    log.Fatal(err)
}

For advanced configuration (custom validator, success status, encoder, declared problems, tags, deprecation), access the wrapped endpoint.Endpoint via ep.Inner() and apply endpoint.Option functions:

ep := handlers.Post[CreateUserReq, CreateUserResp]("create-user", "/users", handler)
ep.Inner().
    WithSuccessStatus(http.StatusCreated).
    WithTags("users", "write")
Convenience Constructors

handlers.Get/Post/Put/Patch/Delete/Head create a typed *Endpoint with the appropriate method and (for body methods) JSON binding. The *Endpoint variants (GetEndpoint, PostEndpoint, …) create and register in one call.

Resources

resources.Resource[ID cmp.Ordered] defines 7 CRUD operations:

Operation Method Path
List GET /{resource}
Show GET /{resource}/{id}
New GET /{resource}/new
Create POST /{resource}
Edit GET /{resource}/{id}/edit
Update PUT /{resource}/{id}
Destroy DELETE /{resource}/{id}

Each operation returns handlers.EndpointRuntime (satisfied by *handlers.Endpoint[Req, Resp]). Operations returning nil are skipped, or registered with a default 405 handler when WithDefaults is set.

type ItemResource struct{}

func (r *ItemResource) List() handlers.EndpointRuntime {
    return handlers.Get[struct{}, []ItemResp]("list-items", "/items",
        func(ctx *request.Context, req struct{}) ([]ItemResp, error) {
            return []ItemResp{{ID: "1", Name: "Item 1"}}, nil
        },
    )
}

func (r *ItemResource) Show() handlers.EndpointRuntime {
    return handlers.Get[struct{}, ItemResp]("show-item", "/items/{id}",
        func(ctx *request.Context, req struct{}) (ItemResp, error) {
            id, err := resources.GetParsedID[string](ctx, "id")
            if err != nil {
                return ItemResp{}, err
            }
            return ItemResp{ID: id, Name: "Item " + id}, nil
        },
    )
}
// ... similarly for New, Create, Edit, Update, Destroy

// Register via ResourceBuilder (recommended).
err := resources.NewResource[string]("/items").
    EnablePatch().
    Register(application.Router, application.Executor, &ItemResource{})

EnablePatch() registers PATCH as an alias for Update. Custom non-CRUD operations (e.g. Reload) can be added via WithCustom.

Typed Session Access

Session middleware stores the *Session on the request.Context via a typed key. Handlers retrieve it with session.FromContext and use the generic accessors for compile-time type safety:

sess := session.FromContext(ctx)
if sess == nil {
    return Resp{}, errors.New("no session")
}

// Store a typed value.
session.SetTyped(sess, "user_id", 42)

// Retrieve with compile-time type checking.
userID, err := session.GetTyped[int](sess, "user_id")
RFC 9457 Problem Responses

Errors returned by handlers are mapped to response.Problem (RFC 9457) via the response.MapperRegistry configured on the executor and router. Unknown errors always become sanitized 500 problems; causes are never serialized. Register custom mappers before StartWithContext (the registry is frozen at startup):

mapper := response.DefaultMapperRegistry()
_ = mapper.Register(
    func(err error) bool {
        var e *MyError
        return errors.As(err, &e)
    },
    func(err error) *response.Problem {
        return response.NewProblemWithCode(409, "Conflict", "MY_ERROR").
            WithDetail("resource already exists")
    },
)

application, err := app.Bootstrap(app.Config{
    Framework:     app.FrameworkChi,
    ProblemMapper: mapper,
})

Handlers can also return a *response.Problem directly — the mapper returns it as-is.

Framework Adapters

Switch frameworks by changing one config field:

app.Bootstrap(app.Config{Framework: app.FrameworkGin})    // Gin
app.Bootstrap(app.Config{Framework: app.FrameworkFiber})  // Fiber
app.Bootstrap(app.Config{Framework: app.FrameworkChi})    // chi + net/http
app.Bootstrap(app.Config{Framework: app.FrameworkNetHTTP}) // net/http

All handlers, resources, and middleware work unchanged across frameworks. Route patterns use canonical {id} syntax; adapters translate to the framework-specific form (:id for Gin/Fiber, {id} for chi).

Telemetry

The v2 kernel records lifecycle events through telemetry.Sink. The default sink is telemetry.SlogSink, which emits structured slog records ingested by Splunk. The canonical event names are <operation>-req (success) and <operation>-req-failed (failure), matching the v1 webFramework.AddLog key convention so Splunk dashboards remain consistent.

The executor automatically emits start, success, and failure events for every request. Request and response bodies are never included in telemetry attributes; slog.LogValuer masking is honored.

Configure a custom sink via app.Config.TelemetrySink or endpoint.WithTelemetrySink. telemetry.NopSink is intended for tests only — production setups must use an observable sink.

Background Workers
err := application.Worker.Submit(context.Background(), workers.Job{
    Name: "send-email",
    Handler: func(ctx *workers.JobContext) error {
        // ctx.Logger is a job-scoped *slog.Logger.
        // ctx.Sink is the telemetry.Sink for lifecycle events.
        ctx.Logger.Info("sending email", slog.String("recipient", email))
        // ... send email ...
        return nil
    },
    Options: workers.JobOptions{MaxAttempts: 3},
})

For periodic tasks, use application.Scheduler.Schedule(...) with a workers.ScheduledJob. Both the worker pool and scheduler emit worker-<name>-req / worker-<name>-req-failed telemetry events and are shut down automatically by app.Shutdown.

Renderers
app.Bootstrap(app.Config{
    Framework: app.FrameworkChi,
    Renderer:  renderers.JSONRenderer{},  // or XMLRenderer{}, TextRenderer{}, CSVRenderer{}
})

The configured renderer is used as the executor's default encoder. Per-endpoint encoders can be set via endpoint.WithEncoder.


Package Map

Package Description
app Bootstrap, Config, App — application entry point
request Context, ResponseState, typed keys — per-request state
routing Router, RouteGroup, Handler, Middleware, Chain, Transport
endpoint Endpoint[Req, Resp], Executor, Options — canonical lifecycle
handlers Endpoint[Req, Resp], EndpointRuntime, New/Get/Post/…, RegisterEndpoint
operation Operation, Registry — endpoint metadata
binding Plan, binding modes — request binding
validation Validator — request validation
response Problem (RFC 9457), MapperRegistry, Handler, Registry
renderers Renderer interface, JSON/XML/text/CSV renderers
resources Resource[ID], ResourceBuilder[ID], Register, CustomOperation, GetParsedID
session Session, Flash, Manager, CookieStore, FromContext, GetTyped[T], SetTyped[T]
telemetry Sink, SlogSink, NopSink, Event — lifecycle observability
workers InProcessWorker, Scheduler, Job, JobContext, ScheduledJob
adapter Framework-agnostic endpoint/transport bridging
libGin Gin adapter
libFiber Fiber adapter
libChi chi adapter
libNetHttp net/http adapter
testingtools Test helpers and mock infrastructure

Observability

The v2 kernel records request and transaction lifecycle events through telemetry.Sink (default telemetry.SlogSink), not webFramework.AddLog. The production slog handler ingests these records into Splunk, preserving the canonical <operation>-req / <operation>-req-failed outcome keys.

Both success and failure paths are recorded: success events include the safely projected response (never raw bodies); failure events include the error. Session load/save failures emit session-load-failed and session-save-failed events via the configured sink.

v2 packages must record lifecycle events through telemetry.Sink. Direct slog.* / log.* calls are only permitted for startup/diagnostic messages, not transaction tracing. telemetry.NopSink is acceptable in tests only.


Examples

  • examples/simple/ — chi-based example with typed endpoints, CRUD resource, workers, sessions, and typed session access.

Migration from v1

See MIGRATION.md for the complete v1-to-v2 migration guide, including breaking changes from the alpha API and deferred Tranche 5 features.


License

See LICENSE for license information.

Documentation

Overview

Package requestcore is the v2 module of requestCore.

v2 is a typed, framework-neutral HTTP toolkit built on a canonical kernel. It requires Go 1.22+ for the net/http ServeMux pattern matching and Go 1.27+ for generic methods on typed endpoints.

Architecture

The v2 kernel is organized as a layered DAG:

  • request — stdlib-only request state, lazy body source, typed values, response metadata, before-commit hooks.
  • telemetry — stdlib-only event/sink contracts and slog sink.
  • binding, validation, operation, renderers — leaf capabilities.
  • response — Problems (RFC 9457), mapper registry, commit coordinator, no-content/redirect helpers.
  • endpoint — typed endpoint and executor; the canonical lifecycle (bind → validate → execute → encode → commit → observe).
  • routing — handler/middleware/router and response-transport contracts; imports request only.
  • adapter — adapts typed endpoints and mapped errors to routing handlers.
  • libGin, libFiber, libChi, libNetHttp — native context/transport construction for each framework.
  • handlers — convenience constructors and the non-generic runtime endpoint boundary used by resources.
  • resources, session, workers, app, testingtools — high-level packages with no v1 imports.

Core Features

  • **Typed endpoints** — [handlers.Endpoint[Req, Resp]] wraps [endpoint.Endpoint[Req, Resp]] with a canonical handler signature: func(*request.Context, Req) (Resp, error).

  • **Transport-aware routing** — [routing.Handler] receives (*request.Context, routing.Transport), separating request state from response writing.

  • **RFC 9457 Problems** — [response.Problem] and [response.MapperRegistry] provide structured error responses with a frozen, immutable registry.

  • **Telemetry via slog** — [telemetry.Sink] and [telemetry.SlogSink] replace v1's webFramework.AddLog for the Splunk transaction pipeline.

  • **Framework-agnostic** — [routing.Router] and [routing.RouteGroup] work across Gin, Fiber, chi, and net/http via adapter packages.

  • **Pluggable renderers** — [renderers.Renderer] interface with built-in JSON, XML, text, and CSV renderers.

  • **Sessions** — [session.Manager] with cookie store, flash messages, and typed session access via [session.FromContext].

  • **Workers and scheduler** — [workers.InProcessWorker] and [workers.Scheduler] with telemetry-based observability.

  • **Application bootstrap** — [app.Bootstrap] composes the executor, router, worker pool, scheduler, and session manager with Problem-based error handling.

Migration from v1

See MIGRATION.md for a detailed migration guide. The v1 module (github.com/hmmftg/requestCore) remains supported and stable.

Directories

Path Synopsis
Package adapter adapts typed endpoints and mapped errors to routing handlers.
Package adapter adapts typed endpoints and mapped errors to routing handlers.
Package app provides a framework-neutral application bootstrap for v2 requestCore applications.
Package app provides a framework-neutral application bootstrap for v2 requestCore applications.
Package binding provides framework-neutral request decoding for the redesigned v2 kernel.
Package binding provides framework-neutral request decoding for the redesigned v2 kernel.
cmd
requestcore
Package cmd provides the requestcore CLI for generating v2 application scaffolding, including handlers, resources, middleware, and project structure.
Package cmd provides the requestcore CLI for generating v2 application scaffolding, including handlers, resources, middleware, and project structure.
requestcore/cmd command
Package endpoint is the public typed endpoint descriptor and lifecycle executor for the v2 kernel.
Package endpoint is the public typed endpoint descriptor and lifecycle executor for the v2 kernel.
examples
simple command
Package main is a v2 requestCore example application using chi.
Package main is a v2 requestCore example application using chi.
Package handlers provides the canonical v2 endpoint descriptors and registration helpers built on top of the endpoint.Executor kernel.
Package handlers provides the canonical v2 endpoint descriptors and registration helpers built on top of the endpoint.Executor kernel.
internal
endpoint
Package endpoint provides the internal typed endpoint descriptor and lifecycle executor for the v2 kernel.
Package endpoint provides the internal typed endpoint descriptor and lifecycle executor for the v2 kernel.
nextadapter
Package nextadapter: addlog_sink.go previously contained addLogSink, which forwarded telemetry events to the legacy AddLog pipeline.
Package nextadapter: addlog_sink.go previously contained addLogSink, which forwarded telemetry events to the legacy AddLog pipeline.
Package libChi provides the v2 chi web framework adapter for requestCore.
Package libChi provides the v2 chi web framework adapter for requestCore.
Package libFiber provides the v2 Fiber framework adapter for requestCore.
Package libFiber provides the v2 Fiber framework adapter for requestCore.
Package libGin provides the v2 Gin framework adapter for requestCore.
Package libGin provides the v2 Gin framework adapter for requestCore.
Package libNetHttp provides the v2 net/http framework adapter for requestCore.
Package libNetHttp provides the v2 net/http framework adapter for requestCore.
Package operation provides immutable endpoint metadata and a registry contract shared by handlers, OpenAPI generation, policies, and the application bootstrap.
Package operation provides immutable endpoint metadata and a registry contract shared by handlers, OpenAPI generation, policies, and the application bootstrap.
Package renderers provides pluggable content renderers for v2 response handling.
Package renderers provides pluggable content renderers for v2 response handling.
Package request provides the stdlib-only request Context, typed value keys, and response metadata for the redesigned v2 kernel.
Package request provides the stdlib-only request Context, typed value keys, and response metadata for the redesigned v2 kernel.
faketransport
Package faketransport provides an internal fake HTTP transport for testing the redesigned v2 kernel without any adapter.
Package faketransport provides an internal fake HTTP transport for testing the redesigned v2 kernel without any adapter.
Package resources provides v2 resource registration with seven standard CRUD operations, inspired by Buffalo's resource pattern.
Package resources provides v2 resource registration with seven standard CRUD operations, inspired by Buffalo's resource pattern.
Package routing provides framework-agnostic route groups, middleware, and a Router interface implemented by Gin, Fiber, and net/http+chi adapters.
Package routing provides framework-agnostic route groups, middleware, and a Router interface implemented by Gin, Fiber, and net/http+chi adapters.
Package session provides pluggable session and flash management for v2.
Package session provides pluggable session and flash management for v2.
Package telemetry provides framework-neutral event recording for the redesigned v2 kernel.
Package telemetry provides framework-neutral event recording for the redesigned v2 kernel.
Package testingtools provides test utilities for v2 handler and middleware testing using the canonical kernel (*request.Context, routing.Transport, endpoint.Executor, telemetry.Sink).
Package testingtools provides test utilities for v2 handler and middleware testing using the canonical kernel (*request.Context, routing.Transport, endpoint.Executor, telemetry.Sink).
Package validation provides struct-tag validation that returns response.Violation slices for integration with the v2 problem mapper.
Package validation provides struct-tag validation that returns response.Violation slices for integration with the v2 problem mapper.
Package workers provides a bounded in-process worker pool with retry, tracing, and mandatory observability through telemetry.Sink.
Package workers provides a bounded in-process worker pool with retry, tracing, and mandatory observability through telemetry.Sink.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL