This post is about how to create a very simple plugin for Filestash, the plugin does nothing at all but writing a line in the logs, it is not intended to be a guide for plugin development, just to summarize the first steps I didn't found anywhere else so myself or other developers can save a few minutes next time.
A few days ago I published A Docker development environment for Filestash in which I showed how to create a quick and simple development environment for Filestash, a web file manager. As I explore the software, I've been discovering things I would love to document, I think the best way to document it is writing this kind of practical, although very simplistic posts.
I am not a go programmer, so expect comments that may be obvious for developers familiarized with the language.
Why do I need to create a plugin?
Filestash's architecture is modular, and plugins play a huge role. Plugins are used for adding storage types, for authentication, authorization, for handling different types of files, for using different types of servers (starter plugins), etc. I am not 100% sure, but it seems most Filestash tasks are achievable through its plugin system.
The sad part is that I didn't find much documentation about how to customize things. At the beginning I didn't even know how to enable/disable plugins. Eventually this made me create a plugin to try to figure out how the system works.
The entry point: how to enable/disable plugins
Plugins are added to the app in server/plugin/index.go
, there you have to add or remove the reference for the plugin package in the imports.
There are things you need to know about imports:
-
_
is called blank and means that the package is imported for its side effects, that is, the code in its initialization. -
.
is called a period, and it means that all the package's exported identifiers will be available in the importing package without a qualifier, which usually is the name of the imported package.
One additional note about go is that init is a special function that is automatically executed when the package is initialized. This happens before the main function runs and after all package-level variables are initialized.
In conclusion, to add the plugin we simply need to add it to the imports in server/plugin/index.go
, to disable a plugin we can comment out or delete the importing line in this file.
A new plugin
To have a package to import we need to create it, here is the simplest plugin I could think of that has a visible output.
It does one simple thing, write an output line to the logs. Even so, there are some interesting remarks:
- The logger is defined in the
common
package, so we need to import it. We could importfmt
instead and use print, to immediately print the text, but it would feel out of chronological order. - If we plainly write the log it won't work because the logger is not ready, the best way to do it is to put our function inside a lifecycle hook for the app, more on this in the next section.
package plg_plugin_example
import (
. "github.com/mickael-kerjean/filestash/server/common"
)
func init() {
// Apparently Log is not initialized at this point
// Log.Debug("Why this is not printed?")
Hooks.Register.Onload(func() { Log.Debug("My plugin!") })
}
Lifecycle hooks
I didn't find any docs about the lifecycle hooks, so here is a little summary without any detail, and probably with some errors or omissions, from their file server/common/plugin.go
, part of the common
package.
ProcessFileContentBeforeSend
HttpEndpoint
Static
Starter
AuthenticationMiddleware
AuthorisationMiddleware
SearchEngine
Thumbnailer
AuditEngine
FrontendOverrides
XDGOpen
CSS
CSSFunc
Favicon
Onload
Middleware
StaticPatch
Metadata
WorkflowTrigger
WorkflowAction
Just to be clear, I don't know yet the meaning, use case, or configuration of most of these, I am just listing them to keep them at hand. Some may be self-descriptive but a careful analysis of the code is recommended before using it for serious work.
Top comments (0)