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