Skip to content

Commit

Permalink
incusd/operations: Use ManualResponse to send headers early
Browse files Browse the repository at this point in the history
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 <stgraber@stgraber.org>
  • Loading branch information
stgraber committed Dec 7, 2023
1 parent 3515a79 commit e5a0594
Showing 1 changed file with 27 additions and 9 deletions.
36 changes: 27 additions & 9 deletions cmd/incusd/operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit e5a0594

Please sign in to comment.