mirror of
https://github.com/caddyserver/caddy.git
synced 2025-06-02 21:24:35 -04:00
Merge branch 'master' into golangcilint-v2
This commit is contained in:
commit
924273f6a3
104
caddy.go
104
caddy.go
@ -81,13 +81,14 @@ type Config struct {
|
|||||||
// associated value.
|
// associated value.
|
||||||
AppsRaw ModuleMap `json:"apps,omitempty" caddy:"namespace="`
|
AppsRaw ModuleMap `json:"apps,omitempty" caddy:"namespace="`
|
||||||
|
|
||||||
apps map[string]App
|
apps map[string]App
|
||||||
storage certmagic.Storage
|
storage certmagic.Storage
|
||||||
|
eventEmitter eventEmitter
|
||||||
|
|
||||||
cancelFunc context.CancelFunc
|
cancelFunc context.CancelFunc
|
||||||
|
|
||||||
// filesystems is a dict of filesystems that will later be loaded from and added to.
|
// fileSystems is a dict of fileSystems that will later be loaded from and added to.
|
||||||
filesystems FileSystems
|
fileSystems FileSystems
|
||||||
}
|
}
|
||||||
|
|
||||||
// App is a thing that Caddy runs.
|
// App is a thing that Caddy runs.
|
||||||
@ -442,6 +443,10 @@ func run(newCfg *Config, start bool) (Context, error) {
|
|||||||
}
|
}
|
||||||
globalMetrics.configSuccess.Set(1)
|
globalMetrics.configSuccess.Set(1)
|
||||||
globalMetrics.configSuccessTime.SetToCurrentTime()
|
globalMetrics.configSuccessTime.SetToCurrentTime()
|
||||||
|
|
||||||
|
// TODO: This event is experimental and subject to change.
|
||||||
|
ctx.emitEvent("started", nil)
|
||||||
|
|
||||||
// now that the user's config is running, finish setting up anything else,
|
// now that the user's config is running, finish setting up anything else,
|
||||||
// such as remote admin endpoint, config loader, etc.
|
// such as remote admin endpoint, config loader, etc.
|
||||||
return ctx, finishSettingUp(ctx, ctx.cfg)
|
return ctx, finishSettingUp(ctx, ctx.cfg)
|
||||||
@ -509,7 +514,7 @@ func provisionContext(newCfg *Config, replaceAdminServer bool) (Context, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create the new filesystem map
|
// create the new filesystem map
|
||||||
newCfg.filesystems = &filesystems.FilesystemMap{}
|
newCfg.fileSystems = &filesystems.FileSystemMap{}
|
||||||
|
|
||||||
// prepare the new config for use
|
// prepare the new config for use
|
||||||
newCfg.apps = make(map[string]App)
|
newCfg.apps = make(map[string]App)
|
||||||
@ -696,6 +701,9 @@ func unsyncedStop(ctx Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This event is experimental and subject to change.
|
||||||
|
ctx.emitEvent("stopping", nil)
|
||||||
|
|
||||||
// stop each app
|
// stop each app
|
||||||
for name, a := range ctx.cfg.apps {
|
for name, a := range ctx.cfg.apps {
|
||||||
err := a.Stop()
|
err := a.Stop()
|
||||||
@ -1038,6 +1046,92 @@ func Version() (simple, full string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Event represents something that has happened or is happening.
|
||||||
|
// An Event value is not synchronized, so it should be copied if
|
||||||
|
// being used in goroutines.
|
||||||
|
//
|
||||||
|
// EXPERIMENTAL: Events are subject to change.
|
||||||
|
type Event struct {
|
||||||
|
// If non-nil, the event has been aborted, meaning
|
||||||
|
// propagation has stopped to other handlers and
|
||||||
|
// the code should stop what it was doing. Emitters
|
||||||
|
// may choose to use this as a signal to adjust their
|
||||||
|
// code path appropriately.
|
||||||
|
Aborted error
|
||||||
|
|
||||||
|
// The data associated with the event. Usually the
|
||||||
|
// original emitter will be the only one to set or
|
||||||
|
// change these values, but the field is exported
|
||||||
|
// so handlers can have full access if needed.
|
||||||
|
// However, this map is not synchronized, so
|
||||||
|
// handlers must not use this map directly in new
|
||||||
|
// goroutines; instead, copy the map to use it in a
|
||||||
|
// goroutine. Data may be nil.
|
||||||
|
Data map[string]any
|
||||||
|
|
||||||
|
id uuid.UUID
|
||||||
|
ts time.Time
|
||||||
|
name string
|
||||||
|
origin Module
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEvent creates a new event, but does not emit the event. To emit an
|
||||||
|
// event, call Emit() on the current instance of the caddyevents app insteaad.
|
||||||
|
//
|
||||||
|
// EXPERIMENTAL: Subject to change.
|
||||||
|
func NewEvent(ctx Context, name string, data map[string]any) (Event, error) {
|
||||||
|
id, err := uuid.NewRandom()
|
||||||
|
if err != nil {
|
||||||
|
return Event{}, fmt.Errorf("generating new event ID: %v", err)
|
||||||
|
}
|
||||||
|
name = strings.ToLower(name)
|
||||||
|
return Event{
|
||||||
|
Data: data,
|
||||||
|
id: id,
|
||||||
|
ts: time.Now(),
|
||||||
|
name: name,
|
||||||
|
origin: ctx.Module(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Event) ID() uuid.UUID { return e.id }
|
||||||
|
func (e Event) Timestamp() time.Time { return e.ts }
|
||||||
|
func (e Event) Name() string { return e.name }
|
||||||
|
func (e Event) Origin() Module { return e.origin } // Returns the module that originated the event. May be nil, usually if caddy core emits the event.
|
||||||
|
|
||||||
|
// CloudEvent exports event e as a structure that, when
|
||||||
|
// serialized as JSON, is compatible with the
|
||||||
|
// CloudEvents spec.
|
||||||
|
func (e Event) CloudEvent() CloudEvent {
|
||||||
|
dataJSON, _ := json.Marshal(e.Data)
|
||||||
|
return CloudEvent{
|
||||||
|
ID: e.id.String(),
|
||||||
|
Source: e.origin.CaddyModule().String(),
|
||||||
|
SpecVersion: "1.0",
|
||||||
|
Type: e.name,
|
||||||
|
Time: e.ts,
|
||||||
|
DataContentType: "application/json",
|
||||||
|
Data: dataJSON,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloudEvent is a JSON-serializable structure that
|
||||||
|
// is compatible with the CloudEvents specification.
|
||||||
|
// See https://cloudevents.io.
|
||||||
|
// EXPERIMENTAL: Subject to change.
|
||||||
|
type CloudEvent struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Source string `json:"source"`
|
||||||
|
SpecVersion string `json:"specversion"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Time time.Time `json:"time"`
|
||||||
|
DataContentType string `json:"datacontenttype,omitempty"`
|
||||||
|
Data json.RawMessage `json:"data,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrEventAborted cancels an event.
|
||||||
|
var ErrEventAborted = errors.New("event aborted")
|
||||||
|
|
||||||
// ActiveContext returns the currently-active context.
|
// ActiveContext returns the currently-active context.
|
||||||
// This function is experimental and might be changed
|
// This function is experimental and might be changed
|
||||||
// or removed in the future.
|
// or removed in the future.
|
||||||
|
32
context.go
32
context.go
@ -91,14 +91,14 @@ func (ctx *Context) OnCancel(f func()) {
|
|||||||
ctx.cleanupFuncs = append(ctx.cleanupFuncs, f)
|
ctx.cleanupFuncs = append(ctx.cleanupFuncs, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filesystems returns a ref to the FilesystemMap.
|
// FileSystems returns a ref to the FilesystemMap.
|
||||||
// EXPERIMENTAL: This API is subject to change.
|
// EXPERIMENTAL: This API is subject to change.
|
||||||
func (ctx *Context) Filesystems() FileSystems {
|
func (ctx *Context) FileSystems() FileSystems {
|
||||||
// if no config is loaded, we use a default filesystemmap, which includes the osfs
|
// if no config is loaded, we use a default filesystemmap, which includes the osfs
|
||||||
if ctx.cfg == nil {
|
if ctx.cfg == nil {
|
||||||
return &filesystems.FilesystemMap{}
|
return &filesystems.FileSystemMap{}
|
||||||
}
|
}
|
||||||
return ctx.cfg.filesystems
|
return ctx.cfg.fileSystems
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the active metrics registry for the context
|
// Returns the active metrics registry for the context
|
||||||
@ -277,6 +277,14 @@ func (ctx Context) LoadModule(structPointer any, fieldName string) (any, error)
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// emitEvent is a small convenience method so the caddy core can emit events, if the event app is configured.
|
||||||
|
func (ctx Context) emitEvent(name string, data map[string]any) Event {
|
||||||
|
if ctx.cfg == nil || ctx.cfg.eventEmitter == nil {
|
||||||
|
return Event{}
|
||||||
|
}
|
||||||
|
return ctx.cfg.eventEmitter.Emit(ctx, name, data)
|
||||||
|
}
|
||||||
|
|
||||||
// loadModulesFromSomeMap loads modules from val, which must be a type of map[string]any.
|
// loadModulesFromSomeMap loads modules from val, which must be a type of map[string]any.
|
||||||
// Depending on inlineModuleKey, it will be interpreted as either a ModuleMap (key is the module
|
// Depending on inlineModuleKey, it will be interpreted as either a ModuleMap (key is the module
|
||||||
// name) or as a regular map (key is not the module name, and module name is defined inline).
|
// name) or as a regular map (key is not the module name, and module name is defined inline).
|
||||||
@ -429,6 +437,14 @@ func (ctx Context) LoadModuleByID(id string, rawMsg json.RawMessage) (any, error
|
|||||||
|
|
||||||
ctx.moduleInstances[id] = append(ctx.moduleInstances[id], val)
|
ctx.moduleInstances[id] = append(ctx.moduleInstances[id], val)
|
||||||
|
|
||||||
|
// if the loaded module happens to be an app that can emit events, store it so the
|
||||||
|
// core can have access to emit events without an import cycle
|
||||||
|
if ee, ok := val.(eventEmitter); ok {
|
||||||
|
if _, ok := ee.(App); ok {
|
||||||
|
ctx.cfg.eventEmitter = ee
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return val, nil
|
return val, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -600,3 +616,11 @@ func (ctx *Context) WithValue(key, value any) Context {
|
|||||||
exitFuncs: ctx.exitFuncs,
|
exitFuncs: ctx.exitFuncs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eventEmitter is a small interface that inverts dependencies for
|
||||||
|
// the caddyevents package, so the core can emit events without an
|
||||||
|
// import cycle (i.e. the caddy package doesn't have to import
|
||||||
|
// the caddyevents package, which imports the caddy package).
|
||||||
|
type eventEmitter interface {
|
||||||
|
Emit(ctx Context, eventName string, data map[string]any) Event
|
||||||
|
}
|
||||||
|
@ -7,10 +7,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DefaultFilesystemKey = "default"
|
DefaultFileSystemKey = "default"
|
||||||
)
|
)
|
||||||
|
|
||||||
var DefaultFilesystem = &wrapperFs{key: DefaultFilesystemKey, FS: OsFS{}}
|
var DefaultFileSystem = &wrapperFs{key: DefaultFileSystemKey, FS: OsFS{}}
|
||||||
|
|
||||||
// wrapperFs exists so can easily add to wrapperFs down the line
|
// wrapperFs exists so can easily add to wrapperFs down the line
|
||||||
type wrapperFs struct {
|
type wrapperFs struct {
|
||||||
@ -18,24 +18,24 @@ type wrapperFs struct {
|
|||||||
fs.FS
|
fs.FS
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilesystemMap stores a map of filesystems
|
// FileSystemMap stores a map of filesystems
|
||||||
// the empty key will be overwritten to be the default key
|
// the empty key will be overwritten to be the default key
|
||||||
// it includes a default filesystem, based off the os fs
|
// it includes a default filesystem, based off the os fs
|
||||||
type FilesystemMap struct {
|
type FileSystemMap struct {
|
||||||
m sync.Map
|
m sync.Map
|
||||||
}
|
}
|
||||||
|
|
||||||
// note that the first invocation of key cannot be called in a racy context.
|
// note that the first invocation of key cannot be called in a racy context.
|
||||||
func (f *FilesystemMap) key(k string) string {
|
func (f *FileSystemMap) key(k string) string {
|
||||||
if k == "" {
|
if k == "" {
|
||||||
k = DefaultFilesystemKey
|
k = DefaultFileSystemKey
|
||||||
}
|
}
|
||||||
return k
|
return k
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register will add the filesystem with key to later be retrieved
|
// Register will add the filesystem with key to later be retrieved
|
||||||
// A call with a nil fs will call unregister, ensuring that a call to Default() will never be nil
|
// A call with a nil fs will call unregister, ensuring that a call to Default() will never be nil
|
||||||
func (f *FilesystemMap) Register(k string, v fs.FS) {
|
func (f *FileSystemMap) Register(k string, v fs.FS) {
|
||||||
k = f.key(k)
|
k = f.key(k)
|
||||||
if v == nil {
|
if v == nil {
|
||||||
f.Unregister(k)
|
f.Unregister(k)
|
||||||
@ -47,23 +47,23 @@ func (f *FilesystemMap) Register(k string, v fs.FS) {
|
|||||||
// Unregister will remove the filesystem with key from the filesystem map
|
// Unregister will remove the filesystem with key from the filesystem map
|
||||||
// if the key is the default key, it will set the default to the osFS instead of deleting it
|
// if the key is the default key, it will set the default to the osFS instead of deleting it
|
||||||
// modules should call this on cleanup to be safe
|
// modules should call this on cleanup to be safe
|
||||||
func (f *FilesystemMap) Unregister(k string) {
|
func (f *FileSystemMap) Unregister(k string) {
|
||||||
k = f.key(k)
|
k = f.key(k)
|
||||||
if k == DefaultFilesystemKey {
|
if k == DefaultFileSystemKey {
|
||||||
f.m.Store(k, DefaultFilesystem)
|
f.m.Store(k, DefaultFileSystem)
|
||||||
} else {
|
} else {
|
||||||
f.m.Delete(k)
|
f.m.Delete(k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get will get a filesystem with a given key
|
// Get will get a filesystem with a given key
|
||||||
func (f *FilesystemMap) Get(k string) (v fs.FS, ok bool) {
|
func (f *FileSystemMap) Get(k string) (v fs.FS, ok bool) {
|
||||||
k = f.key(k)
|
k = f.key(k)
|
||||||
c, ok := f.m.Load(strings.TrimSpace(k))
|
c, ok := f.m.Load(strings.TrimSpace(k))
|
||||||
if !ok {
|
if !ok {
|
||||||
if k == DefaultFilesystemKey {
|
if k == DefaultFileSystemKey {
|
||||||
f.m.Store(k, DefaultFilesystem)
|
f.m.Store(k, DefaultFileSystem)
|
||||||
return DefaultFilesystem, true
|
return DefaultFileSystem, true
|
||||||
}
|
}
|
||||||
return nil, ok
|
return nil, ok
|
||||||
}
|
}
|
||||||
@ -71,7 +71,7 @@ func (f *FilesystemMap) Get(k string) (v fs.FS, ok bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default will get the default filesystem in the filesystem map
|
// Default will get the default filesystem in the filesystem map
|
||||||
func (f *FilesystemMap) Default() fs.FS {
|
func (f *FileSystemMap) Default() fs.FS {
|
||||||
val, _ := f.Get(DefaultFilesystemKey)
|
val, _ := f.Get(DefaultFileSystemKey)
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"github.com/caddyserver/caddy/v2"
|
"github.com/caddyserver/caddy/v2"
|
||||||
@ -206,27 +204,26 @@ func (app *App) On(eventName string, handler Handler) error {
|
|||||||
//
|
//
|
||||||
// Note that the data map is not copied, for efficiency. After Emit() is called, the
|
// Note that the data map is not copied, for efficiency. After Emit() is called, the
|
||||||
// data passed in should not be changed in other goroutines.
|
// data passed in should not be changed in other goroutines.
|
||||||
func (app *App) Emit(ctx caddy.Context, eventName string, data map[string]any) Event {
|
func (app *App) Emit(ctx caddy.Context, eventName string, data map[string]any) caddy.Event {
|
||||||
logger := app.logger.With(zap.String("name", eventName))
|
logger := app.logger.With(zap.String("name", eventName))
|
||||||
|
|
||||||
id, err := uuid.NewRandom()
|
e, err := caddy.NewEvent(ctx, eventName, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("failed generating new event ID", zap.Error(err))
|
logger.Error("failed to create event", zap.Error(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
eventName = strings.ToLower(eventName)
|
var originModule caddy.ModuleInfo
|
||||||
|
var originModuleID caddy.ModuleID
|
||||||
e := Event{
|
var originModuleName string
|
||||||
Data: data,
|
if origin := e.Origin(); origin != nil {
|
||||||
id: id,
|
originModule = origin.CaddyModule()
|
||||||
ts: time.Now(),
|
originModuleID = originModule.ID
|
||||||
name: eventName,
|
originModuleName = originModule.String()
|
||||||
origin: ctx.Module(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logger = logger.With(
|
logger = logger.With(
|
||||||
zap.String("id", e.id.String()),
|
zap.String("id", e.ID().String()),
|
||||||
zap.String("origin", e.origin.CaddyModule().String()))
|
zap.String("origin", originModuleName))
|
||||||
|
|
||||||
// add event info to replacer, make sure it's in the context
|
// add event info to replacer, make sure it's in the context
|
||||||
repl, ok := ctx.Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
|
repl, ok := ctx.Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
|
||||||
@ -239,15 +236,15 @@ func (app *App) Emit(ctx caddy.Context, eventName string, data map[string]any) E
|
|||||||
case "event":
|
case "event":
|
||||||
return e, true
|
return e, true
|
||||||
case "event.id":
|
case "event.id":
|
||||||
return e.id, true
|
return e.ID(), true
|
||||||
case "event.name":
|
case "event.name":
|
||||||
return e.name, true
|
return e.Name(), true
|
||||||
case "event.time":
|
case "event.time":
|
||||||
return e.ts, true
|
return e.Timestamp(), true
|
||||||
case "event.time_unix":
|
case "event.time_unix":
|
||||||
return e.ts.UnixMilli(), true
|
return e.Timestamp().UnixMilli(), true
|
||||||
case "event.module":
|
case "event.module":
|
||||||
return e.origin.CaddyModule().ID, true
|
return originModuleID, true
|
||||||
case "event.data":
|
case "event.data":
|
||||||
return e.Data, true
|
return e.Data, true
|
||||||
}
|
}
|
||||||
@ -269,7 +266,7 @@ func (app *App) Emit(ctx caddy.Context, eventName string, data map[string]any) E
|
|||||||
// invoke handlers bound to the event by name and also all events; this for loop
|
// invoke handlers bound to the event by name and also all events; this for loop
|
||||||
// iterates twice at most: once for the event name, once for "" (all events)
|
// iterates twice at most: once for the event name, once for "" (all events)
|
||||||
for {
|
for {
|
||||||
moduleID := e.origin.CaddyModule().ID
|
moduleID := originModuleID
|
||||||
|
|
||||||
// implement propagation up the module tree (i.e. start with "a.b.c" then "a.b" then "a" then "")
|
// implement propagation up the module tree (i.e. start with "a.b.c" then "a.b" then "a" then "")
|
||||||
for app.subscriptions[eventName] != nil {
|
for app.subscriptions[eventName] != nil {
|
||||||
@ -288,7 +285,7 @@ func (app *App) Emit(ctx caddy.Context, eventName string, data map[string]any) E
|
|||||||
zap.Any("handler", handler))
|
zap.Any("handler", handler))
|
||||||
|
|
||||||
if err := handler.Handle(ctx, e); err != nil {
|
if err := handler.Handle(ctx, e); err != nil {
|
||||||
aborted := errors.Is(err, ErrAborted)
|
aborted := errors.Is(err, caddy.ErrEventAborted)
|
||||||
|
|
||||||
logger.Error("handler error",
|
logger.Error("handler error",
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
@ -322,76 +319,9 @@ func (app *App) Emit(ctx caddy.Context, eventName string, data map[string]any) E
|
|||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event represents something that has happened or is happening.
|
|
||||||
// An Event value is not synchronized, so it should be copied if
|
|
||||||
// being used in goroutines.
|
|
||||||
//
|
|
||||||
// EXPERIMENTAL: As with the rest of this package, events are
|
|
||||||
// subject to change.
|
|
||||||
type Event struct {
|
|
||||||
// If non-nil, the event has been aborted, meaning
|
|
||||||
// propagation has stopped to other handlers and
|
|
||||||
// the code should stop what it was doing. Emitters
|
|
||||||
// may choose to use this as a signal to adjust their
|
|
||||||
// code path appropriately.
|
|
||||||
Aborted error
|
|
||||||
|
|
||||||
// The data associated with the event. Usually the
|
|
||||||
// original emitter will be the only one to set or
|
|
||||||
// change these values, but the field is exported
|
|
||||||
// so handlers can have full access if needed.
|
|
||||||
// However, this map is not synchronized, so
|
|
||||||
// handlers must not use this map directly in new
|
|
||||||
// goroutines; instead, copy the map to use it in a
|
|
||||||
// goroutine.
|
|
||||||
Data map[string]any
|
|
||||||
|
|
||||||
id uuid.UUID
|
|
||||||
ts time.Time
|
|
||||||
name string
|
|
||||||
origin caddy.Module
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e Event) ID() uuid.UUID { return e.id }
|
|
||||||
func (e Event) Timestamp() time.Time { return e.ts }
|
|
||||||
func (e Event) Name() string { return e.name }
|
|
||||||
func (e Event) Origin() caddy.Module { return e.origin }
|
|
||||||
|
|
||||||
// CloudEvent exports event e as a structure that, when
|
|
||||||
// serialized as JSON, is compatible with the
|
|
||||||
// CloudEvents spec.
|
|
||||||
func (e Event) CloudEvent() CloudEvent {
|
|
||||||
dataJSON, _ := json.Marshal(e.Data)
|
|
||||||
return CloudEvent{
|
|
||||||
ID: e.id.String(),
|
|
||||||
Source: e.origin.CaddyModule().String(),
|
|
||||||
SpecVersion: "1.0",
|
|
||||||
Type: e.name,
|
|
||||||
Time: e.ts,
|
|
||||||
DataContentType: "application/json",
|
|
||||||
Data: dataJSON,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CloudEvent is a JSON-serializable structure that
|
|
||||||
// is compatible with the CloudEvents specification.
|
|
||||||
// See https://cloudevents.io.
|
|
||||||
type CloudEvent struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Source string `json:"source"`
|
|
||||||
SpecVersion string `json:"specversion"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
Time time.Time `json:"time"`
|
|
||||||
DataContentType string `json:"datacontenttype,omitempty"`
|
|
||||||
Data json.RawMessage `json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrAborted cancels an event.
|
|
||||||
var ErrAborted = errors.New("event aborted")
|
|
||||||
|
|
||||||
// Handler is a type that can handle events.
|
// Handler is a type that can handle events.
|
||||||
type Handler interface {
|
type Handler interface {
|
||||||
Handle(context.Context, Event) error
|
Handle(context.Context, caddy.Event) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interface guards
|
// Interface guards
|
||||||
|
@ -69,11 +69,11 @@ func (xs *Filesystems) Provision(ctx caddy.Context) error {
|
|||||||
}
|
}
|
||||||
// register that module
|
// register that module
|
||||||
ctx.Logger().Debug("registering fs", zap.String("fs", f.Key))
|
ctx.Logger().Debug("registering fs", zap.String("fs", f.Key))
|
||||||
ctx.Filesystems().Register(f.Key, f.fileSystem)
|
ctx.FileSystems().Register(f.Key, f.fileSystem)
|
||||||
// remember to unregister the module when we are done
|
// remember to unregister the module when we are done
|
||||||
xs.defers = append(xs.defers, func() {
|
xs.defers = append(xs.defers, func() {
|
||||||
ctx.Logger().Debug("unregistering fs", zap.String("fs", f.Key))
|
ctx.Logger().Debug("unregistering fs", zap.String("fs", f.Key))
|
||||||
ctx.Filesystems().Unregister(f.Key)
|
ctx.FileSystems().Unregister(f.Key)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -274,7 +274,7 @@ func celFileMatcherMacroExpander() parser.MacroExpander {
|
|||||||
func (m *MatchFile) Provision(ctx caddy.Context) error {
|
func (m *MatchFile) Provision(ctx caddy.Context) error {
|
||||||
m.logger = ctx.Logger()
|
m.logger = ctx.Logger()
|
||||||
|
|
||||||
m.fsmap = ctx.Filesystems()
|
m.fsmap = ctx.FileSystems()
|
||||||
|
|
||||||
if m.Root == "" {
|
if m.Root == "" {
|
||||||
m.Root = "{http.vars.root}"
|
m.Root = "{http.vars.root}"
|
||||||
|
@ -117,7 +117,7 @@ func TestFileMatcher(t *testing.T) {
|
|||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
m := &MatchFile{
|
m := &MatchFile{
|
||||||
fsmap: &filesystems.FilesystemMap{},
|
fsmap: &filesystems.FileSystemMap{},
|
||||||
Root: "./testdata",
|
Root: "./testdata",
|
||||||
TryFiles: []string{"{http.request.uri.path}", "{http.request.uri.path}/"},
|
TryFiles: []string{"{http.request.uri.path}", "{http.request.uri.path}/"},
|
||||||
}
|
}
|
||||||
@ -229,7 +229,7 @@ func TestPHPFileMatcher(t *testing.T) {
|
|||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
m := &MatchFile{
|
m := &MatchFile{
|
||||||
fsmap: &filesystems.FilesystemMap{},
|
fsmap: &filesystems.FileSystemMap{},
|
||||||
Root: "./testdata",
|
Root: "./testdata",
|
||||||
TryFiles: []string{"{http.request.uri.path}", "{http.request.uri.path}/index.php"},
|
TryFiles: []string{"{http.request.uri.path}", "{http.request.uri.path}/index.php"},
|
||||||
SplitPath: []string{".php"},
|
SplitPath: []string{".php"},
|
||||||
@ -273,7 +273,7 @@ func TestPHPFileMatcher(t *testing.T) {
|
|||||||
func TestFirstSplit(t *testing.T) {
|
func TestFirstSplit(t *testing.T) {
|
||||||
m := MatchFile{
|
m := MatchFile{
|
||||||
SplitPath: []string{".php"},
|
SplitPath: []string{".php"},
|
||||||
fsmap: &filesystems.FilesystemMap{},
|
fsmap: &filesystems.FileSystemMap{},
|
||||||
}
|
}
|
||||||
actual, remainder := m.firstSplit("index.PHP/somewhere")
|
actual, remainder := m.firstSplit("index.PHP/somewhere")
|
||||||
expected := "index.PHP"
|
expected := "index.PHP"
|
||||||
|
@ -186,7 +186,7 @@ func (FileServer) CaddyModule() caddy.ModuleInfo {
|
|||||||
func (fsrv *FileServer) Provision(ctx caddy.Context) error {
|
func (fsrv *FileServer) Provision(ctx caddy.Context) error {
|
||||||
fsrv.logger = ctx.Logger()
|
fsrv.logger = ctx.Logger()
|
||||||
|
|
||||||
fsrv.fsmap = ctx.Filesystems()
|
fsrv.fsmap = ctx.FileSystems()
|
||||||
|
|
||||||
if fsrv.FileSystem == "" {
|
if fsrv.FileSystem == "" {
|
||||||
fsrv.FileSystem = "{http.vars.fs}"
|
fsrv.FileSystem = "{http.vars.fs}"
|
||||||
|
@ -660,7 +660,8 @@ nextName:
|
|||||||
var httpsRec libdns.Record
|
var httpsRec libdns.Record
|
||||||
var nameHasExistingRecord bool
|
var nameHasExistingRecord bool
|
||||||
for _, rec := range recs {
|
for _, rec := range recs {
|
||||||
if rec.Name == relName {
|
// TODO: providers SHOULD normalize root-level records to be named "@"; remove the extra conditions when the transition to the new semantics is done
|
||||||
|
if rec.Name == relName || (rec.Name == "" && relName == "@") {
|
||||||
// CNAME records are exclusive of all other records, so we cannot publish an HTTPS
|
// CNAME records are exclusive of all other records, so we cannot publish an HTTPS
|
||||||
// record for a domain that is CNAME'd. See #6922.
|
// record for a domain that is CNAME'd. See #6922.
|
||||||
if rec.Type == "CNAME" {
|
if rec.Type == "CNAME" {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user