summaryrefslogtreecommitdiff
path: root/caddyconfig/load.go
diff options
context:
space:
mode:
Diffstat (limited to 'caddyconfig/load.go')
-rw-r--r--caddyconfig/load.go93
1 files changed, 55 insertions, 38 deletions
diff --git a/caddyconfig/load.go b/caddyconfig/load.go
index 4855b46..7a390d0 100644
--- a/caddyconfig/load.go
+++ b/caddyconfig/load.go
@@ -69,8 +69,8 @@ func (al adminLoad) Routes() []caddy.AdminRoute {
func (adminLoad) handleLoad(w http.ResponseWriter, r *http.Request) error {
if r.Method != http.MethodPost {
return caddy.APIError{
- Code: http.StatusMethodNotAllowed,
- Err: fmt.Errorf("method not allowed"),
+ HTTPStatus: http.StatusMethodNotAllowed,
+ Err: fmt.Errorf("method not allowed"),
}
}
@@ -81,8 +81,8 @@ func (adminLoad) handleLoad(w http.ResponseWriter, r *http.Request) error {
_, err := io.Copy(buf, r.Body)
if err != nil {
return caddy.APIError{
- Code: http.StatusBadRequest,
- Err: fmt.Errorf("reading request body: %v", err),
+ HTTPStatus: http.StatusBadRequest,
+ Err: fmt.Errorf("reading request body: %v", err),
}
}
body := buf.Bytes()
@@ -90,45 +90,21 @@ func (adminLoad) handleLoad(w http.ResponseWriter, r *http.Request) error {
// if the config is formatted other than Caddy's native
// JSON, we need to adapt it before loading it
if ctHeader := r.Header.Get("Content-Type"); ctHeader != "" {
- ct, _, err := mime.ParseMediaType(ctHeader)
+ result, warnings, err := adaptByContentType(ctHeader, body)
if err != nil {
return caddy.APIError{
- Code: http.StatusBadRequest,
- Err: fmt.Errorf("invalid Content-Type: %v", err),
+ HTTPStatus: http.StatusBadRequest,
+ Err: err,
}
}
- if !strings.HasSuffix(ct, "/json") {
- slashIdx := strings.Index(ct, "/")
- if slashIdx < 0 {
- return caddy.APIError{
- Code: http.StatusBadRequest,
- Err: fmt.Errorf("malformed Content-Type"),
- }
- }
- adapterName := ct[slashIdx+1:]
- cfgAdapter := GetAdapter(adapterName)
- if cfgAdapter == nil {
- return caddy.APIError{
- Code: http.StatusBadRequest,
- Err: fmt.Errorf("unrecognized config adapter '%s'", adapterName),
- }
- }
- result, warnings, err := cfgAdapter.Adapt(body, nil)
+ if len(warnings) > 0 {
+ respBody, err := json.Marshal(warnings)
if err != nil {
- return caddy.APIError{
- Code: http.StatusBadRequest,
- Err: fmt.Errorf("adapting config using %s adapter: %v", adapterName, err),
- }
- }
- if len(warnings) > 0 {
- respBody, err := json.Marshal(warnings)
- if err != nil {
- caddy.Log().Named("admin.api.load").Error(err.Error())
- }
- _, _ = w.Write(respBody)
+ caddy.Log().Named("admin.api.load").Error(err.Error())
}
- body = result
+ _, _ = w.Write(respBody)
}
+ body = result
}
forceReload := r.Header.Get("Cache-Control") == "must-revalidate"
@@ -136,8 +112,8 @@ func (adminLoad) handleLoad(w http.ResponseWriter, r *http.Request) error {
err = caddy.Load(body, forceReload)
if err != nil {
return caddy.APIError{
- Code: http.StatusBadRequest,
- Err: fmt.Errorf("loading config: %v", err),
+ HTTPStatus: http.StatusBadRequest,
+ Err: fmt.Errorf("loading config: %v", err),
}
}
@@ -146,6 +122,47 @@ func (adminLoad) handleLoad(w http.ResponseWriter, r *http.Request) error {
return nil
}
+// adaptByContentType adapts body to Caddy JSON using the adapter specified by contenType.
+// If contentType is empty or ends with "/json", the input will be returned, as a no-op.
+func adaptByContentType(contentType string, body []byte) ([]byte, []Warning, error) {
+ // assume JSON as the default
+ if contentType == "" {
+ return body, nil, nil
+ }
+
+ ct, _, err := mime.ParseMediaType(contentType)
+ if err != nil {
+ return nil, nil, caddy.APIError{
+ HTTPStatus: http.StatusBadRequest,
+ Err: fmt.Errorf("invalid Content-Type: %v", err),
+ }
+ }
+
+ // if already JSON, no need to adapt
+ if strings.HasSuffix(ct, "/json") {
+ return body, nil, nil
+ }
+
+ // adapter name should be suffix of MIME type
+ slashIdx := strings.Index(ct, "/")
+ if slashIdx < 0 {
+ return nil, nil, fmt.Errorf("malformed Content-Type")
+ }
+
+ adapterName := ct[slashIdx+1:]
+ cfgAdapter := GetAdapter(adapterName)
+ if cfgAdapter == nil {
+ return nil, nil, fmt.Errorf("unrecognized config adapter '%s'", adapterName)
+ }
+
+ result, warnings, err := cfgAdapter.Adapt(body, nil)
+ if err != nil {
+ return nil, nil, fmt.Errorf("adapting config using %s adapter: %v", adapterName, err)
+ }
+
+ return result, warnings, nil
+}
+
var bufPool = sync.Pool{
New: func() interface{} {
return new(bytes.Buffer)