handleLoad replaces the entire current configuration with a new one provided in the response body. It supports config adapters through the use of the Content-Type header. A config that is identical to the currently-running config will be a no-op unless Cache-Control: must-revalidate is set.
(w http.ResponseWriter, r *http.Request)
| 71 | // config that is identical to the currently-running config |
| 72 | // will be a no-op unless Cache-Control: must-revalidate is set. |
| 73 | func (adminLoad) handleLoad(w http.ResponseWriter, r *http.Request) error { |
| 74 | if r.Method != http.MethodPost { |
| 75 | return caddy.APIError{ |
| 76 | HTTPStatus: http.StatusMethodNotAllowed, |
| 77 | Err: fmt.Errorf("method not allowed"), |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | buf := bufPool.Get().(*bytes.Buffer) |
| 82 | buf.Reset() |
| 83 | defer bufPool.Put(buf) |
| 84 | |
| 85 | _, err := io.Copy(buf, r.Body) |
| 86 | if err != nil { |
| 87 | return caddy.APIError{ |
| 88 | HTTPStatus: http.StatusBadRequest, |
| 89 | Err: fmt.Errorf("reading request body: %v", err), |
| 90 | } |
| 91 | } |
| 92 | body := buf.Bytes() |
| 93 | |
| 94 | // if the config is formatted other than Caddy's native |
| 95 | // JSON, we need to adapt it before loading it |
| 96 | if ctHeader := r.Header.Get("Content-Type"); ctHeader != "" { |
| 97 | result, warnings, err := adaptByContentType(ctHeader, body) |
| 98 | if err != nil { |
| 99 | return caddy.APIError{ |
| 100 | HTTPStatus: http.StatusBadRequest, |
| 101 | Err: err, |
| 102 | } |
| 103 | } |
| 104 | if len(warnings) > 0 { |
| 105 | respBody, err := json.Marshal(warnings) |
| 106 | if err != nil { |
| 107 | caddy.Log().Named("admin.api.load").Error(err.Error()) |
| 108 | } |
| 109 | _, _ = w.Write(respBody) //nolint:gosec // false positive: no XSS here |
| 110 | } |
| 111 | body = result |
| 112 | } |
| 113 | |
| 114 | forceReload := r.Header.Get("Cache-Control") == "must-revalidate" |
| 115 | |
| 116 | err = caddy.Load(body, forceReload) |
| 117 | if err != nil { |
| 118 | return caddy.APIError{ |
| 119 | HTTPStatus: http.StatusBadRequest, |
| 120 | Err: fmt.Errorf("loading config: %v", err), |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | // If this request changed the config, clear the last |
| 125 | // config info we have stored, if it is different from |
| 126 | // the original source. |
| 127 | caddy.ClearLastConfigIfDifferent( |
| 128 | r.Header.Get("Caddy-Config-Source-File"), |
| 129 | r.Header.Get("Caddy-Config-Source-Adapter")) |
| 130 |