aboutsummaryrefslogtreecommitdiffhomepage
path: root/admin.go
diff options
context:
space:
mode:
Diffstat (limited to 'admin.go')
-rw-r--r--admin.go27
1 files changed, 21 insertions, 6 deletions
diff --git a/admin.go b/admin.go
index 7c1e9e80e..3950a92fa 100644
--- a/admin.go
+++ b/admin.go
@@ -953,17 +953,28 @@ func makeEtag(path string, hash hash.Hash) string {
return fmt.Sprintf(`"%s %x"`, path, hash.Sum(nil))
}
+// This buffer pool is used to keep buffers for
+// reading the config file during eTag header generation
+var bufferPool = sync.Pool{
+ New: func() any {
+ return new(bytes.Buffer)
+ },
+}
+
func handleConfig(w http.ResponseWriter, r *http.Request) error {
switch r.Method {
case http.MethodGet:
w.Header().Set("Content-Type", "application/json")
- // Set the ETag as a trailer header.
- // The alternative is to write the config to a buffer, and
- // then hash that.
- w.Header().Set("Trailer", "ETag")
-
hash := etagHasher()
- configWriter := io.MultiWriter(w, hash)
+
+ // Read the config into a buffer instead of writing directly to
+ // the response writer, as we want to set the ETag as the header,
+ // not the trailer.
+ buf := bufferPool.Get().(*bytes.Buffer)
+ buf.Reset()
+ defer bufferPool.Put(buf)
+
+ configWriter := io.MultiWriter(buf, hash)
err := readConfig(r.URL.Path, configWriter)
if err != nil {
return APIError{HTTPStatus: http.StatusBadRequest, Err: err}
@@ -972,6 +983,10 @@ func handleConfig(w http.ResponseWriter, r *http.Request) error {
// we could consider setting up a sync.Pool for the summed
// hashes to reduce GC pressure.
w.Header().Set("Etag", makeEtag(r.URL.Path, hash))
+ _, err = w.Write(buf.Bytes())
+ if err != nil {
+ return APIError{HTTPStatus: http.StatusInternalServerError, Err: err}
+ }
return nil