@marcel91200 / caddy Mirror · read-only
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 10, 23:45 UTC

master
go 130 lines 4.11 KB
Raw
1 // Copyright 2015 Matthew Holt and The Caddy Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package caddyconfig
16
17 import (
18 "encoding/json"
19 "fmt"
20
21 "github.com/caddyserver/caddy/v2"
22 "github.com/caddyserver/caddy/v2/caddyconfig/warning"
23 )
24
25 // Adapter is a type which can adapt a configuration to Caddy JSON.
26 // It returns the results and any warnings, or an error.
27 type Adapter interface {
28 Adapt(body []byte, options map[string]any) ([]byte, []Warning, error)
29 }
30
31 // Warning represents a warning or notice related to conversion.
32 type Warning = warning.Warning
33
34 // JSON encodes val as JSON, returning it as a json.RawMessage. Any
35 // marshaling errors (which are highly unlikely with correct code)
36 // are converted to warnings. This is convenient when filling config
37 // structs that require a json.RawMessage, without having to worry
38 // about errors.
39 func JSON(val any, warnings *[]Warning) json.RawMessage {
40 b, err := json.Marshal(val)
41 if err != nil {
42 if warnings != nil {
43 *warnings = append(*warnings, Warning{Message: err.Error()})
44 }
45 return nil
46 }
47 return b
48 }
49
50 // JSONModuleObject is like JSON(), except it marshals val into a JSON object
51 // with an added key named fieldName with the value fieldVal. This is useful
52 // for encoding module values where the module name has to be described within
53 // the object by a certain key; for example, `"handler": "file_server"` for a
54 // file server HTTP handler (fieldName="handler" and fieldVal="file_server").
55 // The val parameter must encode into a map[string]any (i.e. it must be
56 // a struct or map). Any errors are converted into warnings.
57 func JSONModuleObject(val any, fieldName, fieldVal string, warnings *[]Warning) json.RawMessage {
58 // encode to a JSON object first
59 enc, err := json.Marshal(val)
60 if err != nil {
61 if warnings != nil {
62 *warnings = append(*warnings, Warning{Message: err.Error()})
63 }
64 return nil
65 }
66
67 // then decode the object
68 var tmp map[string]any
69 err = json.Unmarshal(enc, &tmp)
70 if err != nil {
71 if warnings != nil {
72 message := err.Error()
73 if jsonErr, ok := err.(*json.SyntaxError); ok {
74 message = fmt.Sprintf("%v, at offset %d", jsonErr.Error(), jsonErr.Offset)
75 }
76 *warnings = append(*warnings, Warning{Message: message})
77 }
78 return nil
79 }
80
81 // so we can easily add the module's field with its appointed value
82 tmp[fieldName] = fieldVal
83
84 // then re-marshal as JSON
85 result, err := json.Marshal(tmp)
86 if err != nil {
87 if warnings != nil {
88 *warnings = append(*warnings, Warning{Message: err.Error()})
89 }
90 return nil
91 }
92
93 return result
94 }
95
96 // RegisterAdapter registers a config adapter with the given name.
97 // This should usually be done at init-time. It panics if the
98 // adapter cannot be registered successfully.
99 func RegisterAdapter(name string, adapter Adapter) {
100 if _, ok := configAdapters[name]; ok {
101 panic(fmt.Errorf("%s: already registered", name))
102 }
103 configAdapters[name] = adapter
104 caddy.RegisterModule(adapterModule{name, adapter})
105 }
106
107 // GetAdapter returns the adapter with the given name,
108 // or nil if one with that name is not registered.
109 func GetAdapter(name string) Adapter {
110 return configAdapters[name]
111 }
112
113 // adapterModule is a wrapper type that can turn any config
114 // adapter into a Caddy module, which has the benefit of being
115 // counted with other modules, even though they do not
116 // technically extend the Caddy configuration structure.
117 // See caddyserver/caddy#3132.
118 type adapterModule struct {
119 name string
120 Adapter
121 }
122
123 func (am adapterModule) CaddyModule() caddy.ModuleInfo {
124 return caddy.ModuleInfo{
125 ID: caddy.ModuleID("caddy.adapters." + am.name),
126 New: func() caddy.Module { return am },
127 }
128 }
129
130 var configAdapters = make(map[string]Adapter)