Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

admin: Making Etag a header, not a trailer #6208

Merged
merged 8 commits into from
Apr 11, 2024
Merged
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 22 additions & 6 deletions admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -954,17 +954,26 @@ 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() interface{} {
jadidbourbaki marked this conversation as resolved.
Show resolved Hide resolved
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)

configWriter := io.MultiWriter(buf, hash)
err := readConfig(r.URL.Path, configWriter)
if err != nil {
return APIError{HTTPStatus: http.StatusBadRequest, Err: err}
Expand All @@ -973,6 +982,13 @@ 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.StatusBadRequest, Err: err}
jadidbourbaki marked this conversation as resolved.
Show resolved Hide resolved
}

buf.Reset()
jadidbourbaki marked this conversation as resolved.
Show resolved Hide resolved
bufferPool.Put(buf)

return nil

Expand Down
Loading