Capstan is a Golang web framework that shares some similarities with others in its segment.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

215 lines
10 KiB

// 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