Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 14, 05:15 UTC
Improve godoc for contexts
Matthew Holt committed
May 17, 2019 at 08:48 UTC
1a20fe330ecc39e8b98b5669b836f3b1b185f622
2 files changed
+58
-12
context.go
+38
-1
@@ -10,12 +10,30 @@ import (
10
"github.com/mholt/certmagic"
11
)
12
13
+// Context is a type which defines the lifetime of modules that
14
+// are loaded and provides access to the parent configuration
15
+// that spawned the modules which are loaded. It should be used
16
+// with care and only wrapped with derivation functions from
17
+// the standard context package if you don't need the Caddy
18
+// specific features. These contexts are cancelled when the
19
+// lifetime of the modules loaded from it are over.
20
+//
21
+// Use NewContext() to get a valid value (but most modules will
22
+// not actually need to do this).
23
type Context struct {
24
context.Context
25
moduleInstances map[string][]interface{}
26
cfg *Config
27
}
28
29
+// NewContext provides a new context derived from the given
30
+// context ctx. Normally, you will not need to call this
31
+// function unless you are loading modules which have a
32
+// different lifespan than the ones for the context the
33
+// module was provisioned with. Be sure to call the cancel
34
+// func when the context is to be cleaned up so that
35
+// modules which are loaded will be properly unloaded.
36
+// See standard library context package's documentation.
37
func NewContext(ctx Context) (Context, context.CancelFunc) {
38
newCtx := Context{moduleInstances: make(map[string][]interface{}), cfg: ctx.cfg}
39
c, cancel := context.WithCancel(ctx.Context)
@@ -36,6 +54,14 @@ func NewContext(ctx Context) (Context, context.CancelFunc) {
54
return newCtx, wrappedCancel
55
}
56
57
+// LoadModule decodes rawMsg into a new instance of mod and
58
+// returns the value. If mod.New() does not return a pointer
59
+// value, it is converted to one so that it is unmarshaled
60
+// into the underlying concrete type. If mod.New is nil, an
61
+// error is returned. If the module implements Validator or
62
+// Provisioner interfaces, those methods are invoked to
63
+// ensure the module is fully configured and valid before
64
+// being used.
65
func (ctx Context) LoadModule(name string, rawMsg json.RawMessage) (interface{}, error) {
66
modulesMu.Lock()
67
mod, ok := modules[name]
@@ -74,7 +100,7 @@ func (ctx Context) LoadModule(name string, rawMsg json.RawMessage) (interface{},
100
}
101
102
if validator, ok := val.(Validator); ok {
77
- err := validator.Validate(ctx)
103
+ err := validator.Validate()
104
if err != nil {
105
if cleanerUpper, ok := val.(CleanerUpper); ok {
106
err2 := cleanerUpper.Cleanup()
@@ -91,6 +117,17 @@ func (ctx Context) LoadModule(name string, rawMsg json.RawMessage) (interface{},
117
return val, nil
118
}
119
120
+// LoadModuleInline loads a module from a JSON raw message which decodes
121
+// to a map[string]interface{}, where one of the keys is moduleNameKey
122
+// and the corresponding value is the module name as a string, which
123
+// can be found in the given scope.
124
+//
125
+// This allows modules to be decoded into their concrete types and
126
+// used when their names cannot be the unique key in a map, such as
127
+// when there are multiple instances in the map or it appears in an
128
+// array (where there are no custom keys). In other words, the key
129
+// containing the module name is treated special/separate from all
130
+// the other keys.
131
func (ctx Context) LoadModuleInline(moduleNameKey, moduleScope string, raw json.RawMessage) (interface{}, error) {
132
moduleName, err := getModuleNameInline(moduleNameKey, raw)
133
if err != nil {
modules.go
+20
-11
@@ -136,23 +136,32 @@ func getModuleNameInline(moduleNameKey string, raw json.RawMessage) (string, err
136
return moduleName, nil
137
}
138
139
-// Validator is implemented by modules which can verify that their
140
-// configurations are valid. This method will be called after New()
141
-// instantiations of modules (if implemented). Validation should
142
-// always be fast (imperceptible running time) and an error should
143
-// be returned only if the value's configuration is invalid.
144
-type Validator interface {
145
- Validate(Context) error
146
-}
147
-
139
// Provisioner is implemented by modules which may need to perform
140
// some additional "setup" steps immediately after being loaded.
150
-// This method will be called after Validate() (if implemented).
141
+// Provisioning should be fast (imperceptible running time). If
142
+// any side-effects result in the execution of this function (e.g.
143
+// creating global state, any other allocations which require
144
+// garbage collection, opening files, starting goroutines etc.),
145
+// be sure to clean up properly by implementing the CleanerUpper
146
+// interface to avoid leaking resources.
147
type Provisioner interface {
148
Provision(Context) error
149
}
150
155
-// TODO: different name...
151
+// Validator is implemented by modules which can verify that their
152
+// configurations are valid. This method will be called after
153
+// Provision() (if implemented). Validation should always be fast
154
+// (imperceptible running time) and an error should be returned only
155
+// if the value's configuration is invalid.
156
+type Validator interface {
157
+ Validate() error
158
+}
159
+
160
+// CleanerUpper is implemented by modules which may have side-effects
161
+// such as opened files, spawned goroutines, or allocated some sort
162
+// of non-local state when they were provisioned. This method should
163
+// deallocate/cleanup those resources to prevent memory leaks. Cleanup
164
+// should be fast and efficient.
165
type CleanerUpper interface {
166
Cleanup() error
167
}