From e5a0594c5f4c5995e7a52bdba70976caf5743201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Thu, 7 Dec 2023 15:22:26 -0500 Subject: [PATCH] incusd/operations: Use ManualResponse to send headers early MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids hitting a timeout waiting for headers to arrive and properly marks the connection for keep-alive which should avoid other timeouts when going through proxies. Signed-off-by: Stéphane Graber --- cmd/incusd/operations.go | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/cmd/incusd/operations.go b/cmd/incusd/operations.go index 42e0f5f6e4..5c5f140026 100644 --- a/cmd/incusd/operations.go +++ b/cmd/incusd/operations.go @@ -947,19 +947,37 @@ func operationWaitGet(d *Daemon, r *http.Request) response.Response { ctx, cancel = context.WithCancel(r.Context()) } - defer cancel() + waitResponse := func(w http.ResponseWriter) error { + defer cancel() + + // Write header to avoid client side timeouts. + w.Header().Set("Connection", "keep-alive") + w.Header().Set("Content-Type", "application/json") + w.Header().Set("X-Content-Type-Options", "nosniff") + w.WriteHeader(http.StatusOK) + f, ok := w.(http.Flusher) + if ok { + f.Flush() + } - err = op.Wait(ctx) - if err != nil { - return response.SmartError(err) - } + // Wait for the operation. + err = op.Wait(ctx) + if err != nil { + _ = response.SmartError(err).Render(w) + return nil + } - _, body, err := op.Render() - if err != nil { - return response.SmartError(err) + _, body, err := op.Render() + if err != nil { + _ = response.SmartError(err).Render(w) + return nil + } + + _ = response.SyncResponse(true, body).Render(w) + return nil } - return response.SyncResponse(true, body) + return response.ManualResponse(waitResponse) } // Then check if the query is from an operation on another node, and, if so, forward it