mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
lib/httpserver: make sure the gzipResponseWriter.Write() is called on Flush() and Close() calls
This should fix the `http: superfluous response.WriteHeader call` issue See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1078
This commit is contained in:
parent
9a2bf65134
commit
9e644ef111
2 changed files with 19 additions and 9 deletions
|
@ -26,6 +26,7 @@
|
||||||
* BUGFIX: vmselect: do not cache partial query results on timeout when receiving data from `vmstorage` nodes. See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/1085
|
* BUGFIX: vmselect: do not cache partial query results on timeout when receiving data from `vmstorage` nodes. See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/1085
|
||||||
* BUGFIX: properly handle `stale NFS file handle` error.
|
* BUGFIX: properly handle `stale NFS file handle` error.
|
||||||
* BUGFIX: properly cache query results when `extra_label` query arg is used. Previously the cached results could clash for different `extra_label` values. See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/1095
|
* BUGFIX: properly cache query results when `extra_label` query arg is used. Previously the cached results could clash for different `extra_label` values. See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/1095
|
||||||
|
* BUGFIX: fix `http: superfluous response.WriteHeader call` issue. See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1078
|
||||||
|
|
||||||
|
|
||||||
# [v1.54.1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.54.1)
|
# [v1.54.1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.54.1)
|
||||||
|
|
|
@ -298,9 +298,9 @@ func maybeGzipResponseWriter(w http.ResponseWriter, r *http.Request) http.Respon
|
||||||
zw := getGzipWriter(w)
|
zw := getGzipWriter(w)
|
||||||
bw := getBufioWriter(zw)
|
bw := getBufioWriter(zw)
|
||||||
zrw := &gzipResponseWriter{
|
zrw := &gzipResponseWriter{
|
||||||
ResponseWriter: w,
|
rw: w,
|
||||||
zw: zw,
|
zw: zw,
|
||||||
bw: bw,
|
bw: bw,
|
||||||
}
|
}
|
||||||
return zrw
|
return zrw
|
||||||
}
|
}
|
||||||
|
@ -346,7 +346,7 @@ func putGzipWriter(zw *gzip.Writer) {
|
||||||
var gzipWriterPool sync.Pool
|
var gzipWriterPool sync.Pool
|
||||||
|
|
||||||
type gzipResponseWriter struct {
|
type gzipResponseWriter struct {
|
||||||
http.ResponseWriter
|
rw http.ResponseWriter
|
||||||
zw *gzip.Writer
|
zw *gzip.Writer
|
||||||
bw *bufio.Writer
|
bw *bufio.Writer
|
||||||
statusCode int
|
statusCode int
|
||||||
|
@ -355,6 +355,12 @@ type gzipResponseWriter struct {
|
||||||
disableCompression bool
|
disableCompression bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implements http.ResponseWriter.Header method.
|
||||||
|
func (zrw *gzipResponseWriter) Header() http.Header {
|
||||||
|
return zrw.rw.Header()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements http.ResponseWriter.Write method.
|
||||||
func (zrw *gzipResponseWriter) Write(p []byte) (int, error) {
|
func (zrw *gzipResponseWriter) Write(p []byte) (int, error) {
|
||||||
if !zrw.firstWriteDone {
|
if !zrw.firstWriteDone {
|
||||||
h := zrw.Header()
|
h := zrw.Header()
|
||||||
|
@ -377,11 +383,12 @@ func (zrw *gzipResponseWriter) Write(p []byte) (int, error) {
|
||||||
zrw.firstWriteDone = true
|
zrw.firstWriteDone = true
|
||||||
}
|
}
|
||||||
if zrw.disableCompression {
|
if zrw.disableCompression {
|
||||||
return zrw.ResponseWriter.Write(p)
|
return zrw.rw.Write(p)
|
||||||
}
|
}
|
||||||
return zrw.bw.Write(p)
|
return zrw.bw.Write(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implements http.ResponseWriter.WriteHeader method.
|
||||||
func (zrw *gzipResponseWriter) WriteHeader(statusCode int) {
|
func (zrw *gzipResponseWriter) WriteHeader(statusCode int) {
|
||||||
zrw.statusCode = statusCode
|
zrw.statusCode = statusCode
|
||||||
}
|
}
|
||||||
|
@ -390,11 +397,14 @@ func (zrw *gzipResponseWriter) writeHeader() {
|
||||||
if zrw.statusCode == 0 {
|
if zrw.statusCode == 0 {
|
||||||
zrw.statusCode = http.StatusOK
|
zrw.statusCode = http.StatusOK
|
||||||
}
|
}
|
||||||
zrw.ResponseWriter.WriteHeader(zrw.statusCode)
|
zrw.rw.WriteHeader(zrw.statusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements http.Flusher
|
// Implements http.Flusher
|
||||||
func (zrw *gzipResponseWriter) Flush() {
|
func (zrw *gzipResponseWriter) Flush() {
|
||||||
|
if !zrw.firstWriteDone {
|
||||||
|
zrw.Write(nil)
|
||||||
|
}
|
||||||
if !zrw.disableCompression {
|
if !zrw.disableCompression {
|
||||||
if err := zrw.bw.Flush(); err != nil && !isTrivialNetworkError(err) {
|
if err := zrw.bw.Flush(); err != nil && !isTrivialNetworkError(err) {
|
||||||
logger.Warnf("gzipResponseWriter.Flush (buffer): %s", err)
|
logger.Warnf("gzipResponseWriter.Flush (buffer): %s", err)
|
||||||
|
@ -403,15 +413,14 @@ func (zrw *gzipResponseWriter) Flush() {
|
||||||
logger.Warnf("gzipResponseWriter.Flush (gzip): %s", err)
|
logger.Warnf("gzipResponseWriter.Flush (gzip): %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fw, ok := zrw.ResponseWriter.(http.Flusher); ok {
|
if fw, ok := zrw.rw.(http.Flusher); ok {
|
||||||
fw.Flush()
|
fw.Flush()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (zrw *gzipResponseWriter) Close() error {
|
func (zrw *gzipResponseWriter) Close() error {
|
||||||
if !zrw.firstWriteDone {
|
if !zrw.firstWriteDone {
|
||||||
zrw.writeHeader()
|
zrw.Write(nil)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
zrw.Flush()
|
zrw.Flush()
|
||||||
var err error
|
var err error
|
||||||
|
|
Loading…
Reference in a new issue