mirror of
https://github.com/cozystack/cozystack.git
synced 2026-11-13 08:05:19 +09:00
fix(observability-proxy): open live tails without waiting for a line
Go's transport asks for gzip on its own when a request sets no Accept-Encoding. vlselect answers a gzip-negotiated tail through a gzip writer that holds even the response headers until the first line, so the proxy could not forward its 200 and the console kept showing a connecting state for quiet applications; buffered lines were also delayed. The tail request now sends Accept-Encoding: identity, which also turns off the transport's transparent gzip. Other endpoints keep it: they are bounded responses read to the end, compression saves bandwidth between the proxy and the store, and the transport decompresses before the body is copied to the client. Assisted-by: LLM Signed-off-by: ZverGuy <maximbel2003@gmail.com>
This commit is contained in:
1 parent
f19363ec62
commit
e6e3466b7d
2 files changed
+54
No files matched your search
@@ -199,6 +199,11 @@ func (s *Server) serve(w http.ResponseWriter, r *http.Request, route Route) *HTT
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("AccountID", "0")
|
||||
req.Header.Set("ProjectID", "0")
|
||||
if tail {
|
||||
// vlselect holds even the headers of a gzip-encoded tail until the
|
||||
// first line; an explicit value stops the transport from asking for gzip.
|
||||
req.Header.Set("Accept-Encoding", "identity")
|
||||
}
|
||||
resp, err := s.client.Do(req)
|
||||
switch {
|
||||
case err == nil:
|
||||
|
||||
@@ -326,6 +326,55 @@ func TestServerTailFlushesEveryLine(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestServerTailHeadersBeforeFirstLine mimics vlselect, which holds even the
|
||||
// response headers of a gzip-negotiated tail until the first line arrives.
|
||||
func TestServerTailHeadersBeforeFirstLine(t *testing.T) {
|
||||
done := make(chan struct{})
|
||||
h := newHarness(t, Config{TailIdleTimeout: time.Minute}, func(w http.ResponseWriter, r *http.Request) {
|
||||
if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
|
||||
select {
|
||||
case <-done:
|
||||
case <-r.Context().Done():
|
||||
}
|
||||
return
|
||||
}
|
||||
tailUpstream(nil, done)(w, r)
|
||||
})
|
||||
// Registered after the harness so it runs before the servers close and
|
||||
// releases a held upstream when the assertion below fails.
|
||||
t.Cleanup(func() { close(done) })
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, h.proxy.URL+logsRoot+"tail?query=*", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
req.Header.Set("Authorization", "Bearer good")
|
||||
got := make(chan *http.Response, 1)
|
||||
go func() {
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
close(got)
|
||||
return
|
||||
}
|
||||
got <- resp
|
||||
}()
|
||||
select {
|
||||
case resp, ok := <-got:
|
||||
if !ok {
|
||||
t.Fatal("tail request failed")
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Fatalf("status = %d, want 200", resp.StatusCode)
|
||||
}
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("tail response headers did not reach the client before the first line")
|
||||
}
|
||||
if ae := h.requests()[0].headers.Get("Accept-Encoding"); ae != "identity" {
|
||||
t.Fatalf("upstream tail Accept-Encoding = %q, want identity", ae)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerTailCapsAndIdle(t *testing.T) {
|
||||
done := make(chan struct{})
|
||||
t.Cleanup(func() { close(done) })
|
||||
|
||||
Reference in new issue
Block a user