-
Notifications
You must be signed in to change notification settings - Fork 3
Extending Casket
Casket can be extended with plugins. Plugins add missing functionality to Casket. They are "plugged in" at compile-time.
Almost everything in Casket is a plugin. The HTTP server is a plugin. Casket's advanced TLS features are plugins. Every single directive you type in the Casketfile is a plugin.
Some plug into Casket core, while others plug into a specific server type. Some plugins even plug into other plugins (for example, DNS providers plug into the tls
plugin). Casket ships with certain plugins by default: the HTTP server with its standard directives and the standard Casketfile loaders.
There are different kinds of plugins you can write:
- Server Types - A kind of server that Casket can run (HTTP and DNS for example)
- Directives - A directive for the Casketfile
- HTTP Middleware - A function that handles HTTP requests, usually invoked by a Casketfile directive
- Casketfile Loader - Customize how the Casketfile is loaded
- DNS Provider - Make ACME's DNS challenge compatible with your DNS provider
- Listener Middleware - Wrap a net.Listener with your own Listener to do something at the transport or protocol layer
- Event Hook - Execute a function when the Casket process emits certain events
- Cluster Support - Storage backends that enable sharing resources behind load balancers or in a cluster
The links above will show you how to write those kinds of plugins, but always refer to the godoc and the code base itself when you have questions!
Even though there are different kinds of plugins, the process of creating one is roughly the same for all.
Start a new Go package with an init function and register your plugin with Casket or the server type or the other plugin that uses it. The registration function you use depends on the kind of plugin. A few are shown here:
import "github.com/tmpim/casket"
import "github.com/tmpim/casket/caskettls"
func init() {
// register a "generic" plugin, like a directive or middleware
casket.RegisterPlugin("name", myPlugin)
// register a plugin that can load the Casketfile when Casket starts
casket.RegisterCasketfileLoader("name", myLoader)
// register a plugin that implements an entire server type
// for use with Casket
casket.RegisterServerType("name", myServerType)
// register a function that runs when Casket emits events
casket.RegisterEventHook("eventName", myHookFn)
// register a cluster plugin
caskettls.RegisterClusterPlugin("name", constructorFn)
// add a function that wraps listeners for the HTTP server
// (it's more common for a directive to call this rather than a standalone plugin)
httpserver.AddListenerMiddleware(myListenerMiddleware)
// ... there are others. See the godoc.
}
Every plugin must have a name and, when applicable, the name must be unique for that server type.
To plug your plugin into Casket, import it. This is usually done near the top of run.go:
import _ "your/plugin/package/path/here"
Write tests. Get good coverage where possible, and make sure your assertions test what you think they are testing! Use go vet
and go test -race
to ensure your plugin is as error-free as possible.
People will use plugins that are useful, clearly documented, easy to use, and maintained by their owner.
And congratulations, you're a Casket plugin author!