AnnouncementsIntroducing Arkoren

    Menu

    HTTP Events

    Inspect HTTP publication timing, request metadata, and diagnostic privacy boundaries.

    What's on this page
    1. Enable server, transport, middleware, session, link, and webhook notifications separately.
    2. Interpret exact payload fields and the conditions that suppress publication.
    3. Keep raw diagnostics and identifying request data out of unapproved outputs.
    On this page

    HTTP notifications help you distinguish a refused request, an exhausted outgoing call, and a failure during response-time persistence. They observe local decisions; they do not prove that a client received a response. Enable the relevant component with the policy below and register on the same bus.

    These notifications use synchronous, best-effort Emit. A slow listener delays the operation; a listener error or panic is logged and skips later listeners without changing the result. No bus means no publication. Review payloads and context values before retaining them: selected schemas omit sensitive fields, but raw errors and caller context values are not universally redacted.

    Topics

    Topic Name Enabling Policy
    server.Listening http.server.listening server.Builder.Events
    server.ShutdownTimedOut http.server.shutdown.timed-out server.Builder.Events
    router.PanicRecovered http.panic.recovered router.RecoverBuilder.Events
    client.RequestFailed http.client.request.failed client.Builder.Events
    csrf.Blocked http.csrf.blocked csrf.Builder.Events
    ratelimit.Exceeded http.ratelimit.exceeded ratelimit.Builder.Events
    contenttype.Rejected http.contenttype.rejected contenttype.Builder.Events
    session.Expired session.expired session.Builder.Events
    session.Destroyed session.destroyed session.Builder.Events
    session.PersistFailed session.persist.failed session.Builder.Events
    link.Rejected link.rejected link.Builder.Events on the signer
    link.Consumed link.consumed link.Builder.Events on the signer
    webhook.Rejected http.webhook.rejected webhook.Builder.Events
    webhook.Failed http.webhook.failed webhook.Builder.Events
    webhook.Ignored http.webhook.ignored webhook.Builder.Events

    Authentication, gate, and OAuth notifications have their own catalog entries.

    Server Lifecycle

    ListeningEvent{Addr} fires when Start binds its listener. With port zero, Addr includes the chosen port. It is a bound address, not a public URL or proof that serving or TLS negotiation has begun.

    ShutdownTimedOutEvent{Addr, Timeout} fires only when Serve exceeds its native HTTP drain budget and force-closes tracked connections. Timeout is the configured budget, not total elapsed time. A clean drain, another shutdown failure, and Stop publish nothing. Handler work can still remain, and hijacked connections are outside native draining: their owners must close them and await associated work. See server shutdown.

    Recovered Panics

    PanicRecoveredEvent{Method, Pattern, Err, Stack} fires when Recover converts a handler panic into an error. Pattern is the registered route pattern, including its method when present, or empty if no route matched. It is not the expanded path. http.ErrAbortHandler is re-raised and publishes nothing.

    Err, its causes, and the goroutine Stack are sensitive diagnostics. A monitoring listener can avoid them and select only registered route metadata. With context and arkoren.dev/core/http/router imported, and your existing bus and logger:

    _, err := bus.Listen(router.PanicRecovered,
    	func(ctx context.Context, notice router.PanicRecoveredEvent) error {
    		logger.ErrorContext(ctx, "handler panic", "route", notice.Pattern)
    
    		return nil
    	})

    Keep secrets out of route literals too. Send full diagnostics only to approved, restricted sinks, never directly to clients. The event stack is detached from the returned error’s diagnostic storage, and that error’s Stack() accessor returns an owned copy. Listeners still share the event’s slice: copy before mutation. Ownership copies are not redaction.

    The event does not promise a replacement response after bytes are committed. See panic handling, response commitment, and streaming responses.

    Outgoing Requests

    RequestFailedEvent{Method, Host, Attempts, StatusCode, Err} describes the final outcome of one transport round trip. It fires for a returned transport error, or a response RetryIf would retry after attempts run out or Retry-After exceeds the allowed delay. Arbitrary 4xx/5xx responses do not automatically qualify.

    Attempts includes the initial attempt; redirects have separate round trips. Host is the request URL’s hostname without port, path, or query. Exactly one of nonnil Err and nonzero StatusCode describes the outcome. Native transport errors retain causes and can contain sensitive text.

    If the parent request context is done, publication is suppressed. A per-attempt timeout can still publish while the parent context remains active. Later response body-read failures are not transport outcome events. Retry and body ownership belong in HTTP Client.

    Request Rejections

    csrf.BlockedEvent{Method, Path, Origin, Err} observes rejection by the configured cross-origin policy. Path is the request path without query, not a route template. Origin is the untrusted header, empty when absent; Err is the native diagnostic. Paths can contain identifiers, and an origin is not an authenticated identity. See CSRF Protection.

    ratelimit.ExceededEvent{Key, Method, Path, Limit, Window} describes a denied request. Key is the client part of the counter key—client IP by default—not the internal namespace/window suffix. Path is the decoded request path without query. Limit and Window contain normalized positive policy values; Window is the sliding-window duration, not total counter retention.

    A cache marker normally limits publication to the first denial per key and fixed window. If marker insertion fails, the limiter still publishes and later denials can duplicate it. This is best-effort deduplication, not exactly-once notification. The marker failure does not allow the denied request. Treat keys and paths as potentially identifying data; see Rate Limiting.

    contenttype.RejectedEvent{Method, Path, MediaType} fires on every content-type rejection, including with a custom response status. MediaType is the lower-case base type without parameters; it is empty for missing or unparseable base types. Malformed parameters can still leave a parsed base type. Paths and media types are client-controlled. Keep these callbacks cheap and rate-limit hostile request traffic before it reaches them. See Content Type.

    Session Changes

    ExpiredEvent{CreatedAt, ExpiresAt} fires when middleware encounters an expired session, including maximum-lifetime expiry, and replaces it. This happens on a request after expiry, not on a timer. No session identifier or data is included.

    DestroyedEvent{Method, Path} fires after middleware successfully writes the tombstone for a session ended with Session.Destroy, before expiring its cookie. If retirement fails, it publishes PersistFailed instead: the old identifier can still be usable. Expiry is a different event; regeneration alone publishes no destruction event. Persistence runs at response-header writing and is skipped for server-error responses.

    PersistFailedEvent{Operation, Method, Path} describes the failed persistence step: session.PersistSave (save) writes the record, session.PersistVerify (verify) checks the original record is live, and session.PersistRetire (retire) writes a tombstone. The payload omits the storage error. session.Builder.ErrorHandler still receives that diagnostic with its cause; sanitize it separately.

    For destruction and persistence failure, Path is the registered route pattern with its method prefix removed, or empty without a pattern. Expanded parameters and queries never replace it; host-specific patterns retain their host prefix. Avoid secrets in route literals.

    Destruction uses a persistence context detached from request cancellation, with the persistence timeout. Failure events use a context detached from cancellation and deadlines, so an already-exhausted persistence budget does not cancel them. This does not forcibly bound arbitrary listeners or callbacks. Best-effort lease cleanup has a separate ten-second deadline and requires backend context cooperation. Session persistence and cookie behavior belong in Sessions.

    link.RejectedEvent{Method} observes middleware rejection of invalid link form or signature, including binding failure. Expiry of a valid link publishes no rejection. The payload contains no path, URL, binding, or error; binding causes remain in the middleware’s returned problem for errors.Is/errors.As.

    link.ConsumedEvent{Method} fires only after Consume, ConsumeURL, or ConsumeRequest records single use. The direct URL operations leave Method empty. Failed consumption, including an already-spent link, publishes nothing. Verify, Inspect, and middleware do not consume and publish no consumption event.

    Methods are client-controlled, and contexts and returned errors remain outside payload redaction. See Secure Links.

    Webhook Receipts

    Webhook notifications describe locally selected receipt outcomes:

    Topic Payload Outcome
    webhook.Rejected RejectedEvent{Label, Reason, Status} Selected 4xx rejection, including native 413 body-limit handling.
    webhook.Failed FailedEvent{Label, Stage} Processing failure answered with 503.
    webhook.Ignored IgnoredEvent{Label, Reason} Authenticated, unbound type acknowledged with 200.

    RejectedEvent.Reason is webhook.RejectionReason: compare RejectionReasonBodyTooLarge (body_too_large), RejectionReasonUnreadableBody (unreadable_body), or RejectionReasonVerify (verify). Interrupted body reads from cancellation/timeouts are failures, not malformed-body rejections.

    FailedEvent.Stage is webhook.FailureStage: FailureStageRead (read), FailureStageVerify (verify), FailureStageDecode (decode), or FailureStageAccept (accept). Decoder and Event.Map errors share decode; every acceptance error, including ErrSkip, is an accept failure. Acceptance can already have committed work, so this classification does not imply rollback or safe replay.

    IgnoredEvent.Reason is webhook.IgnoreReason, currently only IgnoreReasonUnbound (unbound). Authenticated decoder/map skips and duplicates publish none of these topics. Empty zero categories remain unspecified (""), not defaults. Compare typed constants; convert explicitly for string-only APIs.

    Payloads omit causes, bodies, headers, provider IDs, and event types. Label remains application-controlled and unvalidated; keep it free of credentials and personal data. Context values are not sanitized. Failure responses are committed locally, including native 413 before authentication; provider retry behavior is separate. See Receiving Webhooks, receiver diagnostics, and acknowledgement outcomes.

    For declarations, see the API references for server, router, client, csrf, ratelimit, contenttype, session, link, and webhook.

    Open a bulk documentation archive?

    This file contains every guide in its scope, not API declarations. Loading it all into an agent can exhaust its context window and increase processing time and cost. For coding tasks, start with the index and read only the relevant pages.

    Use the full archive for offline indexing, bulk processing, or deliberate large-context use.

    Browse the index instead
    Open archive