|
// Capstan-specific signals.
|
|
|
|
package capstan
|
|
|
|
import (
|
|
"git.destrealm.org/go/signals/v2"
|
|
"github.com/go-chi/chi"
|
|
)
|
|
|
|
// APPLICATION SIGNALS -->
|
|
|
|
// SigApplicationAttached emits when a new application is attached to the currently running Capstan instance.
|
|
var SigApplicationAttached = signals.New((OnApplicationAttached)(nil))
|
|
|
|
// OnApplicationAttached accepts three arguments: The current application, a
|
|
// boolean status indicating whether Capstan is running in multi-application
|
|
// mode (typically true when this signal is emitted), and the master
|
|
// application.
|
|
//
|
|
// In some cases, the master application and current application may be a
|
|
// pointer to the same interface.
|
|
type OnApplicationAttached func(Application, Application)
|
|
|
|
// SigApplicationListening emits immediatley prior to the call site where the application begins listening to its configured socket(s).
|
|
var SigApplicationListening = signals.New((OnApplicationListening)(nil))
|
|
|
|
// OnApplicationListening accepts the current application at the time of call.
|
|
type OnApplicationListening func(Application)
|
|
|
|
// SigApplicationReady emits when Application.Listen() is called but before any
|
|
// listener startup actually takes effect. This is useful for extending
|
|
// Capstan's behavior just prior to the actual application startup.
|
|
//
|
|
// For multiapp configurations, this signal is fired only from the parent
|
|
// application. If you need to manipulate subapplications at OnApplicationReady,
|
|
// you will need to call Application.Each() with a callback function that
|
|
// performs the desire transformation of individual supapps.
|
|
var SigApplicationReady = signals.New((OnApplicationReady)(nil))
|
|
|
|
// OnApplicationReady accepts the current application at the time of call. If
|
|
// this returns an error, the SigApplicationReady signal will abort and
|
|
// Application.Listen() will immediately return.
|
|
type OnApplicationReady func(Application)
|
|
|
|
// ROUTING SIGNALS -->
|
|
|
|
// SigStartRouteHandler emits when the ServeHTTP Route method is called prior
|
|
// to any internal state handling and after the Context is first initialized.
|
|
// This can be used to modify route parameters prior to processing or modify the
|
|
// Context.
|
|
var SigStartRouteHandler = signals.New((OnStartRouteHandler)(nil))
|
|
|
|
// OnStartRouteHandler accepts the Capstan Route and Context. This can return a
|
|
// signals.Context indicating an error condition which, if non-nil, will
|
|
// interrupt the route handling before any other processing occurs (this also
|
|
// bypasses OnBeforeResponse) if the error code is >= 400.
|
|
//
|
|
// If the signals.Context returned here has MustAbort flagged, this will
|
|
// immediately pass control to the route's error handling without making any
|
|
// changes to the context values as will happen if signals.Context's Error is
|
|
// set. Setting MustAbort() is useful if the caller has modified the
|
|
// capstan.Context directly to reflect a specific error or redirect condition
|
|
// but does not wish for the signal to overwrite these values.
|
|
//
|
|
// Only call signals.Context.SetError() if you actually intend for the signal
|
|
// handler to set an error condition on the request.
|
|
//
|
|
// Access to the raw net/http.ResponseWriter and net/http.Request can be had
|
|
// through the Context.Response() and Context.Request() methods.
|
|
type OnStartRouteHandler func(*Route, Context, signals.Context)
|
|
|
|
// SigEndRouteHandler emits when the route has finished all code paths and is
|
|
// preparing to exit. It is not possible to modify the response, response
|
|
// headers, nor will changing any Route attributes provide expected results.
|
|
// This signal is exclusively for any cleanup code that needs to be run by
|
|
// extensions that have hooked into the route signaling.
|
|
var SigEndRouteHandler = signals.New((OnEndRouteHandler)(nil))
|
|
|
|
// OnEndRouteHandler accepts a capstan.Route, capstan.Context, and the current
|
|
// signals.Context as returned by OnStartRouteHandler.
|
|
//
|
|
// The capstan.Route cannot be modified in this phase.
|
|
type OnEndRouteHandler func(*Route, Context, signals.Context)
|
|
|
|
// SigBeforeResponse emits after the response context and headers have been
|
|
// setup but before any potential protocol upgrades are made (e.g. WebSockets).
|
|
var SigBeforeResponse = signals.New((OnBeforeResponse)(nil))
|
|
|
|
// OnBeforeResponse accepts the Capstan Context and Route. If a signals.Context
|
|
// value is returned and its Error() value is set with a code >= 400, this will
|
|
// skip immediately to the route's error handling.
|
|
type OnBeforeResponse func(Context, *Route, signals.Context)
|
|
|
|
// SigAfterResponse emits after the route has been handled and a response is
|
|
// in-flight but before any error handling code is processed.
|
|
//
|
|
// This signal will only emit with an error condition if and only if there is no
|
|
// error prior to handling the route's endpoint. Error conditions raised by
|
|
// other signals, by connection upgrades, or redirects will not be caught by
|
|
// this signal. To catch all error conditions, use SigRouteError.
|
|
var SigAfterResponse = signals.New((OnAfterResponse)(nil))
|
|
|
|
// OnAfterResponse accepts the Capstan Context and a possible error value. Note
|
|
// that the error value may be nil, capstan.Context, capstan/errors.Redirect,
|
|
// capstan/errors.Internal, or of error.
|
|
type OnAfterResponse func(Context, signals.Context, error)
|
|
|
|
// SigConnectionUpgraded emits when the route has been configured to produce a
|
|
// connection upgrade header, such as for WebSockets. This signal will not be
|
|
// raised if an error occurs during the upgrade process. To catch errors from a
|
|
// failed connection upgrade, you will need to bind to SigRouteError.
|
|
var SigConnectionUpgraded = signals.New((OnConnectionUpgraded)(nil))
|
|
|
|
// OnConnectionUpgraded accepts the capstan.Context and its state immediately
|
|
// after a successful upgrade.
|
|
type OnConnectionUpgraded func(Context, signals.Context)
|
|
|
|
// SigRouteError emits immediately after any error condition has been raised but
|
|
// will not emit if the handled route's endpoint has returned nil (this is in
|
|
// contrast with the actual code which does process nil return values from route
|
|
// endpoints).
|
|
var SigRouteError = signals.New((OnRouteError)(nil))
|
|
|
|
// OnRouteError accepts the capstan.Route, capstan.Context, and the error value
|
|
// encountered at the time of the error.
|
|
//
|
|
// Error returns from routes do not always indicate an error condition. The
|
|
// error type must be checked to see if it is also of type capstan.Context,
|
|
// capstan/errors.Redirect, capstan/errors.Internal, or of type error.
|
|
//
|
|
// If an error condition has occurred and a capstan.Context type was returned,
|
|
// it may be necessary to introspect the Context.Code() value for a value >= 400
|
|
// as well as Context.HasError(). If a capstan.Context has been returned and
|
|
// there is an error condition, both Context.HasError() and Context.Error() will
|
|
// return useful information.
|
|
type OnRouteError func(*Route, Context, signals.Context, error)
|
|
|
|
// SigRouteWriteError emits when an error condition has been reached but prior
|
|
// to the error being written to the HTTP client. This signal may be used to
|
|
// modify the results of the generated error (such as customizing responses
|
|
// without having access to the template system or other internals or
|
|
// configurations).
|
|
var SigRouteWriteError = signals.New((OnRouteWriteError)(nil))
|
|
|
|
// OnRouteWriteError accepts the capstan.Route, capstan.Context, and the error
|
|
// condition that caused the return status.
|
|
//
|
|
// This signal may return a signals.Context. If the signals.Context returns an
|
|
// error, the error value initialize passed to the route error writer will be
|
|
// replaced with the contents of this error and any modifications made to
|
|
// capstan.Conext may be reflected in the returned response. If either
|
|
// MustAbort() or MustStop() are set on the signals.Context, the error writer
|
|
// will exit without writing anything.
|
|
//
|
|
// Setting MustStop() is suggested if callers plan to perform their own error
|
|
// writing directly. MustAbort() is not guaranteed to produce expected results
|
|
// in the near term and its semantics in the function calling OnRouteWriteError
|
|
// may change.
|
|
type OnRouteWriteError func(*Route, Context, error) signals.Context
|
|
|
|
// SigRouteSetup emits after the route has been setup and method handlers have
|
|
// been configured.
|
|
var SigRouteSetup = signals.New((OnRouteSetup)(nil))
|
|
|
|
// OnRouteSetup accepts the router context and a slice of all Route structs
|
|
// derived from the controller as it is processed. Routes will be generated for
|
|
// each HTTP method, each special struct method, and any bind routes that were
|
|
// configured at runtime.
|
|
type OnRouteSetup func(*Router, []*Route)
|
|
|
|
// SigManulRouteSetup emits when routes are manually bound using ManualBind().
|
|
//
|
|
// This is an uncommon trigger since most routes will be configured via their
|
|
// controllers but some users may have a need to manually configure a route.
|
|
//
|
|
// There is no way to differentiate between routes configured via a controller
|
|
// and routes configured via ManualBind; use this signal when catching the
|
|
// latter.
|
|
var SigManualRouteSetup = signals.New((OnManualRouteSetup)(nil))
|
|
|
|
type OnManualRouteSetup func(*Router, *Route)
|
|
|
|
// SigEachRoute emits for each method handler bound per route.
|
|
//
|
|
// In Capstan's semantics, routes are defined individually by path *and* by
|
|
// method. For example, the end point "/demo" would have two separate routes
|
|
// initialized if its controller contains both Get and Post methods (one for
|
|
// each of GET and POST). This signal will emit separately for each of these.
|
|
//
|
|
// Capstan uses this signal internally to expose the renderer's convenience
|
|
// function for attaching template functions and definitions.
|
|
//
|
|
// This signal emits for routes configured with ManualBind.
|
|
var SigEachRoute = signals.New((OnEachRoute)(nil))
|
|
|
|
// OnEachRoute accepts the router context and the Route currently being
|
|
// processed. This is triggered before bindRoute is called (meaning the Route is
|
|
// not yet attached to any muxer) and before the route is completely configured.
|
|
type OnEachRoute func(*Router, *Route)
|
|
|
|
// SigRouteComplete emits for each route after the setup, bindRoute, and URL
|
|
// mapping has been finalized.
|
|
//
|
|
// This signal is also emitted when manually bound routes are completed.
|
|
var SigRouteComplete = signals.New((OnRouteComplete)(nil))
|
|
|
|
// OnRouteComplete accepts the router context and the Route currently processed.
|
|
type OnRouteComplete func(*Router, *Route)
|
|
|
|
// SigBindRoute emits for each invocation of bindRoute (see funcs.go). This provides preliminary access to the router and muxer state prior to configuration.
|
|
var SigBindRoute = signals.New((OnBindRoute)(nil))
|
|
|
|
// OnBindRoute accepts as its arguments the router context, the route currently
|
|
// being processed, and the assigned muxer.
|
|
type OnBindRoute func(*Router, *Route, chi.Router) signals.Context
|