@marcel91200 / caddy Mirror · read-only / commits / 4a0492f3
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 12, 14:30 UTC

admin: Make `Etag` a header, not a trailer (#6208)

* Making eTags a header not a trailer * Checked the write * Fixed typo * Corrected comment * Added sync Pool * Changed control flow of buffer reset / putting and changed error code * Switched from interface{} to any in bufferPool

Hayder committed Apr 11, 2024 at 17:19 UTC 4a0492f3e178c8ab970234b27702c76fedffec5f
1 file changed +21 -6
admin.go
+21 -6
@@ -954,17 +954,28 @@ func makeEtag(path string, hash hash.Hash) string {
954 return fmt.Sprintf(`"%s %x"`, path, hash.Sum(nil))
955 }
956
957 +// This buffer pool is used to keep buffers for
958 +// reading the config file during eTag header generation
959 +var bufferPool = sync.Pool{
960 + New: func() any {
961 + return new(bytes.Buffer)
962 + },
963 +}
964 +
965 func handleConfig(w http.ResponseWriter, r *http.Request) error {
966 switch r.Method {
967 case http.MethodGet:
968 w.Header().Set("Content-Type", "application/json")
961 - // Set the ETag as a trailer header.
962 - // The alternative is to write the config to a buffer, and
963 - // then hash that.
964 - w.Header().Set("Trailer", "ETag")
965 -
969 hash := etagHasher()
967 - configWriter := io.MultiWriter(w, hash)
970 +
971 + // Read the config into a buffer instead of writing directly to
972 + // the response writer, as we want to set the ETag as the header,
973 + // not the trailer.
974 + buf := bufferPool.Get().(*bytes.Buffer)
975 + buf.Reset()
976 + defer bufferPool.Put(buf)
977 +
978 + configWriter := io.MultiWriter(buf, hash)
979 err := readConfig(r.URL.Path, configWriter)
980 if err != nil {
981 return APIError{HTTPStatus: http.StatusBadRequest, Err: err}
@@ -973,6 +984,10 @@ func handleConfig(w http.ResponseWriter, r *http.Request) error {
984 // we could consider setting up a sync.Pool for the summed
985 // hashes to reduce GC pressure.
986 w.Header().Set("Etag", makeEtag(r.URL.Path, hash))
987 + _, err = w.Write(buf.Bytes())
988 + if err != nil {
989 + return APIError{HTTPStatus: http.StatusInternalServerError, Err: err}
990 + }
991
992 return nil
993