mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-17 12:42:16 +01:00
fix(api): propagate request context to stop processing on client disconnect
This commit is contained in:
committed by
Julien Neuhart
parent
3220ca4140
commit
e14cab0c8b
@@ -87,7 +87,7 @@ type downloadFrom struct {
|
|||||||
|
|
||||||
// newContext returns a [Context] by parsing a "multipart/form-data" request.
|
// newContext returns a [Context] by parsing a "multipart/form-data" request.
|
||||||
func newContext(echoCtx echo.Context, logger *zap.Logger, fs *gotenberg.FileSystem, timeout time.Duration, bodyLimit int64, downloadFromCfg downloadFromConfig, traceHeader, trace string) (*Context, context.CancelFunc, error) {
|
func newContext(echoCtx echo.Context, logger *zap.Logger, fs *gotenberg.FileSystem, timeout time.Duration, bodyLimit int64, downloadFromCfg downloadFromConfig, traceHeader, trace string) (*Context, context.CancelFunc, error) {
|
||||||
processCtx, processCancel := context.WithTimeout(context.Background(), timeout)
|
processCtx, processCancel := context.WithTimeout(echoCtx.Request().Context(), timeout)
|
||||||
|
|
||||||
// We want to make sure the multipart/form-data does not exceed a given
|
// We want to make sure the multipart/form-data does not exceed a given
|
||||||
// limit. We consider: form fields (keys, values, files) and files
|
// limit. We consider: form fields (keys, values, files) and files
|
||||||
|
|||||||
71
pkg/modules/api/context_test.go
Normal file
71
pkg/modules/api/context_test.go
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"mime/multipart"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/labstack/echo/v4"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
|
||||||
|
"github.com/gotenberg/gotenberg/v8/pkg/gotenberg"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Propagate HTTP request context cancellation to processing modules to save resources
|
||||||
|
// https://github.com/gotenberg/gotenberg/issues/1455
|
||||||
|
func TestNewContext_Cancellation(t *testing.T) {
|
||||||
|
e := echo.New()
|
||||||
|
|
||||||
|
body := new(bytes.Buffer)
|
||||||
|
writer := multipart.NewWriter(body)
|
||||||
|
err := writer.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to close multipart writer: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a request with a cancellable context.
|
||||||
|
reqCtx, cancelReq := context.WithCancel(context.Background())
|
||||||
|
req := httptest.NewRequest(http.MethodPost, "/", body).WithContext(reqCtx)
|
||||||
|
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||||
|
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
c := e.NewContext(req, rec)
|
||||||
|
|
||||||
|
logger := zap.NewNop()
|
||||||
|
fs := gotenberg.NewFileSystem(new(gotenberg.OsMkdirAll))
|
||||||
|
timeout := time.Duration(10) * time.Second
|
||||||
|
downloadFromCfg := downloadFromConfig{
|
||||||
|
disable: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel, err := newContext(c, logger, fs, timeout, 0, downloadFromCfg, "trace", "trace")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expected no error from newContext, got: %v", err)
|
||||||
|
}
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
// Verify initial state: context SHOULD NOT be done yet.
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
t.Fatal("context should not be done immediately")
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simulate Client Disconnect
|
||||||
|
cancelReq()
|
||||||
|
|
||||||
|
// Verify Propagation
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
// Success! The context was cancelled.
|
||||||
|
if ctx.Err() != context.Canceled {
|
||||||
|
t.Errorf("expected context error to be 'context.Canceled', got: %v", ctx.Err())
|
||||||
|
}
|
||||||
|
case <-time.After(100 * time.Millisecond):
|
||||||
|
t.Fatal("expected context to be cancelled after request context cancellation, but it timed out")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user