@marcel91200 / caddy Mirror · read-only / commits / 8e821b50
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 14, 05:15 UTC

caddyconfig: Add JSON5 and JSON-C adapters (closes #2735)

Matthew Holt committed Sep 2, 2019 at 12:21 UTC 8e821b5039bd6983814a6b1d11894a649c44f74a
5 files changed +131 -26
admin.go
+33 -26
@@ -22,6 +22,7 @@ import (
22 "io"
23 "io/ioutil"
24 "log"
25 + "mime"
26 "net"
27 "net/http"
28 "net/http/pprof"
@@ -170,38 +171,44 @@ func handleLoadConfig(w http.ResponseWriter, r *http.Request) {
171
172 // if the config is formatted other than Caddy's native
173 // JSON, we need to adapt it before loading it
173 - ct := r.Header.Get("Content-Type")
174 - if !strings.Contains(ct, "/json") {
175 - slashIdx := strings.Index(ct, "/")
176 - if slashIdx < 0 {
177 - http.Error(w, "Malformed Content-Type", http.StatusBadRequest)
178 - return
179 - }
180 - adapterName := ct[slashIdx+1:]
181 - cfgAdapter := caddyconfig.GetAdapter(adapterName)
182 - if cfgAdapter == nil {
183 - http.Error(w, "Unrecognized config adapter: "+adapterName, http.StatusBadRequest)
184 - return
185 - }
186 - body, err := ioutil.ReadAll(http.MaxBytesReader(w, r.Body, 1024*1024))
187 - if err != nil {
188 - http.Error(w, "Error reading request body: "+err.Error(), http.StatusBadRequest)
189 - return
190 - }
191 - result, warnings, err := cfgAdapter.Adapt(body, nil)
174 + if ctHeader := r.Header.Get("Content-Type"); ctHeader != "" {
175 + ct, _, err := mime.ParseMediaType(ctHeader)
176 if err != nil {
193 - log.Printf("[ADMIN][ERROR] adapting config from %s: %v", adapterName, err)
194 - http.Error(w, fmt.Sprintf("Adapting config from %s: %v", adapterName, err), http.StatusBadRequest)
177 + http.Error(w, "Invalid Content-Type: "+err.Error(), http.StatusBadRequest)
178 return
179 }
197 - if len(warnings) > 0 {
198 - respBody, err := json.Marshal(warnings)
180 + if !strings.HasSuffix(ct, "/json") {
181 + slashIdx := strings.Index(ct, "/")
182 + if slashIdx < 0 {
183 + http.Error(w, "Malformed Content-Type", http.StatusBadRequest)
184 + return
185 + }
186 + adapterName := ct[slashIdx+1:]
187 + cfgAdapter := caddyconfig.GetAdapter(adapterName)
188 + if cfgAdapter == nil {
189 + http.Error(w, "Unrecognized config adapter: "+adapterName, http.StatusBadRequest)
190 + return
191 + }
192 + body, err := ioutil.ReadAll(http.MaxBytesReader(w, r.Body, 1024*1024))
193 if err != nil {
200 - log.Printf("[ADMIN][ERROR] marshaling warnings: %v", err)
194 + http.Error(w, "Error reading request body: "+err.Error(), http.StatusBadRequest)
195 + return
196 + }
197 + result, warnings, err := cfgAdapter.Adapt(body, nil)
198 + if err != nil {
199 + log.Printf("[ADMIN][ERROR] adapting config from %s: %v", adapterName, err)
200 + http.Error(w, fmt.Sprintf("Adapting config from %s: %v", adapterName, err), http.StatusBadRequest)
201 + return
202 + }
203 + if len(warnings) > 0 {
204 + respBody, err := json.Marshal(warnings)
205 + if err != nil {
206 + log.Printf("[ADMIN][ERROR] marshaling warnings: %v", err)
207 + }
208 + w.Write(respBody)
209 }
202 - w.Write(respBody)
210 + payload = bytes.NewReader(result)
211 }
204 - payload = bytes.NewReader(result)
212 }
213
214 err := Load(payload)
caddyconfig/json5/json5.go new
+43
@@ -0,0 +1,43 @@
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 json5adapter
16 +
17 +import (
18 + "encoding/json"
19 +
20 + "github.com/caddyserver/caddy/v2/caddyconfig"
21 + "github.com/ilibs/json5"
22 +)
23 +
24 +func init() {
25 + caddyconfig.RegisterAdapter("json5", Adapter{})
26 +}
27 +
28 +// Adapter adapts JSON5 to Caddy JSON.
29 +type Adapter struct{}
30 +
31 +// Adapt converts the JSON5 config in body to Caddy JSON.
32 +func (a Adapter) Adapt(body []byte, options map[string]interface{}) (result []byte, warnings []caddyconfig.Warning, err error) {
33 + var decoded interface{}
34 + err = json5.Unmarshal(body, &decoded)
35 + if err != nil {
36 + return
37 + }
38 + result, err = json.Marshal(decoded)
39 + return
40 +}
41 +
42 +// Interface guard
43 +var _ caddyconfig.Adapter = (*Adapter)(nil)
caddyconfig/jsonc/jsonc.go new
+49
@@ -0,0 +1,49 @@
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 jsoncadapter
16 +
17 +import (
18 + "encoding/json"
19 +
20 + "github.com/caddyserver/caddy/v2/caddyconfig"
21 + "github.com/muhammadmuzzammil1998/jsonc"
22 +)
23 +
24 +func init() {
25 + caddyconfig.RegisterAdapter("jsonc", Adapter{})
26 +}
27 +
28 +// Adapter adapts JSON-C to Caddy JSON.
29 +type Adapter struct{}
30 +
31 +// Adapt converts the JSON-C config in body to Caddy JSON.
32 +func (a Adapter) Adapt(body []byte, options map[string]interface{}) (result []byte, warnings []caddyconfig.Warning, err error) {
33 + result = jsonc.ToJSON(body)
34 +
35 + // any errors in the JSON will be
36 + // reported during config load, but
37 + // we can at least warn here that
38 + // it is not valid JSON
39 + if !json.Valid(result) {
40 + warnings = append(warnings, caddyconfig.Warning{
41 + Message: "Resulting JSON is invalid.",
42 + })
43 + }
44 +
45 + return
46 +}
47 +
48 +// Interface guard
49 +var _ caddyconfig.Adapter = (*Adapter)(nil)
go.mod
+2
@@ -14,12 +14,14 @@ require (
14 github.com/google/go-cmp v0.3.1 // indirect
15 github.com/google/uuid v1.1.1 // indirect
16 github.com/huandu/xstrings v1.2.0 // indirect
17 + github.com/ilibs/json5 v1.0.1
18 github.com/imdario/mergo v0.3.7 // indirect
19 github.com/klauspost/compress v1.7.1-0.20190613161414-0b31f265a57b
20 github.com/klauspost/cpuid v1.2.1
21 github.com/kr/pretty v0.1.0 // indirect
22 github.com/mholt/certmagic v0.6.2
23 github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936
24 + github.com/muhammadmuzzammil1998/jsonc v0.0.0-20190902132743-e4903c4dea48
25 github.com/rs/cors v1.6.0
26 github.com/russross/blackfriday/v2 v2.0.1
27 github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
go.sum
+4
@@ -27,6 +27,8 @@ github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
27 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
28 github.com/huandu/xstrings v1.2.0 h1:yPeWdRnmynF7p+lLYz0H2tthW9lqhMJrQV/U7yy4wX0=
29 github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4=
30 +github.com/ilibs/json5 v1.0.1 h1:3e14wUQM8PyK6Hf1bM+zAQFxfG+N5oZj35x5vCNeQ58=
31 +github.com/ilibs/json5 v1.0.1/go.mod h1:kXsGuzHMPuZZTN15l0IQzy5PR8DrDhPB24tFgwpdKME=
32 github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI=
33 github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
34 github.com/klauspost/compress v1.7.1-0.20190613161414-0b31f265a57b h1:LHpBANNM/cw1PAXJtKV9dgfp6ztOKfdGXcltGmqU9aE=
@@ -45,6 +47,8 @@ github.com/miekg/dns v1.1.3 h1:1g0r1IvskvgL8rR+AcHzUA+oFmGcQlaIm4IqakufeMM=
47 github.com/miekg/dns v1.1.3/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
48 github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936 h1:kw1v0NlnN+GZcU8Ma8CLF2Zzgjfx95gs3/GN3vYAPpo=
49 github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
50 +github.com/muhammadmuzzammil1998/jsonc v0.0.0-20190902132743-e4903c4dea48 h1:BM/fjd7MfvZuyoHXLv3YlWNIuNb47PLp6EyFBL1KIMg=
51 +github.com/muhammadmuzzammil1998/jsonc v0.0.0-20190902132743-e4903c4dea48/go.mod h1:saF2fIVw4banK0H4+/EuqfFLpRnoy5S+ECwTOCcRcSU=
52 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
53 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
54 github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI=