From 410c1dfd7f4f49440fc00e07ef2b8cc0e72ca767 Mon Sep 17 00:00:00 2001 From: Julien Neuhart Date: Wed, 18 Mar 2026 23:22:31 +0100 Subject: [PATCH] fix(pdfengines): single file for watermark/stamp, and add the feature to the downloadFrom one --- .bruno/PDF Engines/Embed/Embed Files.bru | 1 + .bruno/PDF Engines/Stamp/Stamp PDF.bru | 2 + .../PDF Engines/Watermark/Watermark PDF.bru | 2 + pkg/modules/api/context.go | 17 +++++- pkg/modules/api/formdata.go | 34 +++++------ pkg/modules/chromium/routes.go | 36 ++++++------ pkg/modules/libreoffice/routes.go | 12 ++-- pkg/modules/pdfengines/routes.go | 56 +++++++++---------- .../features/pdfengines_merge.feature | 26 +++++++++ .../features/pdfengines_stamp.feature | 32 ++++++++++- .../features/pdfengines_watermark.feature | 32 ++++++++++- 11 files changed, 173 insertions(+), 77 deletions(-) diff --git a/.bruno/PDF Engines/Embed/Embed Files.bru b/.bruno/PDF Engines/Embed/Embed Files.bru index 9bc1dc2a..3af440bb 100644 --- a/.bruno/PDF Engines/Embed/Embed Files.bru +++ b/.bruno/PDF Engines/Embed/Embed Files.bru @@ -13,6 +13,7 @@ post { body:multipart-form { files: @file(../../test/integration/testdata/page_1.pdf) embeds: @file(../../test/integration/testdata/page_1.pdf) + ~downloadFrom: [{"url":"https://example.com/attachment.xml","embedded":true}] } headers { diff --git a/.bruno/PDF Engines/Stamp/Stamp PDF.bru b/.bruno/PDF Engines/Stamp/Stamp PDF.bru index feb2e0d1..a1710ab2 100644 --- a/.bruno/PDF Engines/Stamp/Stamp PDF.bru +++ b/.bruno/PDF Engines/Stamp/Stamp PDF.bru @@ -16,6 +16,8 @@ body:multipart-form { stampExpression: APPROVED ~stampPages: 1-2 ~stampOptions: {"font":"Helvetica","fontSize":"48","color":"#00FF00","opacity":"0.5","rotation":"0"} + ~stamp: @file(../../test/integration/testdata/watermark.png) + ~downloadFrom: [{"url":"https://example.com/stamp.png","field":"stamp"}] } headers { diff --git a/.bruno/PDF Engines/Watermark/Watermark PDF.bru b/.bruno/PDF Engines/Watermark/Watermark PDF.bru index 92ac67e3..4ff99dd2 100644 --- a/.bruno/PDF Engines/Watermark/Watermark PDF.bru +++ b/.bruno/PDF Engines/Watermark/Watermark PDF.bru @@ -16,6 +16,8 @@ body:multipart-form { watermarkExpression: CONFIDENTIAL ~watermarkPages: 1-2 ~watermarkOptions: {"font":"Helvetica","fontSize":"48","color":"#FF0000","opacity":"0.3","rotation":"45"} + ~watermark: @file(../../test/integration/testdata/watermark.png) + ~downloadFrom: [{"url":"https://example.com/watermark.png","field":"watermark"}] } headers { diff --git a/pkg/modules/api/context.go b/pkg/modules/api/context.go index 854ea05e..a58e13c9 100644 --- a/pkg/modules/api/context.go +++ b/pkg/modules/api/context.go @@ -81,8 +81,14 @@ type downloadFrom struct { // ExtraHttpHeaders are the HTTP headers to send alongside. ExtraHttpHeaders map[string]string `json:"extraHttpHeaders"` - // Download as embed file + // Embedded routes the downloaded file as an embed. Deprecated: use + // Field instead. Kept for backward compatibility. Embedded bool `json:"embedded"` + + // Field routes the downloaded file to a specific form field bucket. + // Supported values: "watermark", "stamp". For embeds, prefer the + // Embedded flag or set Field to "embedded". + Field string `json:"field"` } // newContext returns a [Context] by parsing a "multipart/form-data" request. @@ -323,8 +329,15 @@ func newContext(echoCtx echo.Context, logger *zap.Logger, fs *gotenberg.FileSyst } ctx.files[filename] = path - if dl.Embedded { + + // Route the downloaded file to the appropriate field bucket. + switch { + case dl.Field == "embedded" || dl.Embedded: ctx.filesByField[EmbedsFormField] = append(ctx.filesByField[EmbedsFormField], path) + case dl.Field == "watermark": + ctx.filesByField[WatermarkFormField] = append(ctx.filesByField[WatermarkFormField], path) + case dl.Field == "stamp": + ctx.filesByField[StampFormField] = append(ctx.filesByField[StampFormField], path) } return nil diff --git a/pkg/modules/api/formdata.go b/pkg/modules/api/formdata.go index 426988bd..f2eca944 100644 --- a/pkg/modules/api/formdata.go +++ b/pkg/modules/api/formdata.go @@ -21,11 +21,11 @@ const ( // EmbedsFormField represents the form field name for embedding files. EmbedsFormField string = "embeds" - // WatermarksFormField represents the form field name for watermark files. - WatermarksFormField string = "watermarks" + // WatermarkFormField represents the form field name for the watermark file. + WatermarkFormField string = "watermark" - // StampsFormField represents the form field name for stamp files. - StampsFormField string = "stamps" + // StampFormField represents the form field name for the stamp file. + StampFormField string = "stamp" ) // FormData is a helper for validating and hydrating values from a @@ -412,31 +412,31 @@ func (form *FormData) MandatoryPaths(extensions []string, target *[]string) *For return form } -// Watermarks binds the absolute paths of form data files that should be -// used as watermark sources. Only files uploaded with the "watermarks" +// Watermark binds the absolute path of the form data file that should be +// used as a watermark source. Only a file uploaded with the "watermark" // field name will be included. -func (form *FormData) Watermarks(target *[]string) *FormData { +func (form *FormData) Watermark(target *string) *FormData { if form.errors != nil { return form } - if paths, ok := form.filesByField[WatermarksFormField]; ok { - *target = append(*target, paths...) + if paths, ok := form.filesByField[WatermarkFormField]; ok && len(paths) > 0 { + *target = paths[0] } return form } -// Stamps binds the absolute paths of form data files that should be -// used as stamp sources. Only files uploaded with the "stamps" +// Stamp binds the absolute path of the form data file that should be +// used as a stamp source. Only a file uploaded with the "stamp" // field name will be included. -func (form *FormData) Stamps(target *[]string) *FormData { +func (form *FormData) Stamp(target *string) *FormData { if form.errors != nil { return form } - if paths, ok := form.filesByField[StampsFormField]; ok { - *target = append(*target, paths...) + if paths, ok := form.filesByField[StampFormField]; ok && len(paths) > 0 { + *target = paths[0] } return form @@ -444,11 +444,11 @@ func (form *FormData) Stamps(target *[]string) *FormData { // paths bind the absolute paths of form data files, according to a list of // file extensions, to a string slice variable. -// embeds, watermarks, and stamps are excluded. +// embeds, watermark, and stamp files are excluded. func (form *FormData) paths(extensions []string, target *[]string) *FormData { embeds, ok := form.filesByField[EmbedsFormField] - watermarks, wmOk := form.filesByField[WatermarksFormField] - stamps, stOk := form.filesByField[StampsFormField] + watermarks, wmOk := form.filesByField[WatermarkFormField] + stamps, stOk := form.filesByField[StampFormField] for filename, path := range form.files { if ok && slices.Contains(embeds, path) { diff --git a/pkg/modules/chromium/routes.go b/pkg/modules/chromium/routes.go index 44f1a0e1..10399593 100644 --- a/pkg/modules/chromium/routes.go +++ b/pkg/modules/chromium/routes.go @@ -416,9 +416,9 @@ func convertUrlRoute(chromium Api, engine gotenberg.PdfEngine) api.Route { userPassword, ownerPassword := pdfengines.FormDataPdfEncrypt(form) embedPaths := pdfengines.FormDataPdfEmbeds(form) watermark := pdfengines.FormDataPdfWatermark(form, false) - watermarkFiles := pdfengines.FormDataPdfWatermarkFiles(form) + watermarkFile := pdfengines.FormDataPdfWatermarkFile(form) stamp := pdfengines.FormDataPdfStamp(form, false) - stampFiles := pdfengines.FormDataPdfStampFiles(form) + stampFile := pdfengines.FormDataPdfStampFile(form) rotateAngle, rotatePages := pdfengines.FormDataPdfRotate(form, false) var url string @@ -429,11 +429,11 @@ func convertUrlRoute(chromium Api, engine gotenberg.PdfEngine) api.Route { return fmt.Errorf("validate form data: %w", err) } - if (watermark.Source == gotenberg.StampSourceImage || watermark.Source == gotenberg.StampSourcePDF) && len(watermarkFiles) > 0 { - watermark.Expression = watermarkFiles[0] + if (watermark.Source == gotenberg.StampSourceImage || watermark.Source == gotenberg.StampSourcePDF) && watermarkFile != "" { + watermark.Expression = watermarkFile } - if (stamp.Source == gotenberg.StampSourceImage || stamp.Source == gotenberg.StampSourcePDF) && len(stampFiles) > 0 { - stamp.Expression = stampFiles[0] + if (stamp.Source == gotenberg.StampSourceImage || stamp.Source == gotenberg.StampSourcePDF) && stampFile != "" { + stamp.Expression = stampFile } err = convertUrl(ctx, chromium, engine, url, options, mode, pdfFormats, metadata, userPassword, ownerPassword, embedPaths, watermark, stamp, rotateAngle, rotatePages) @@ -491,9 +491,9 @@ func convertHtmlRoute(chromium Api, engine gotenberg.PdfEngine) api.Route { userPassword, ownerPassword := pdfengines.FormDataPdfEncrypt(form) embedPaths := pdfengines.FormDataPdfEmbeds(form) watermark := pdfengines.FormDataPdfWatermark(form, false) - watermarkFiles := pdfengines.FormDataPdfWatermarkFiles(form) + watermarkFile := pdfengines.FormDataPdfWatermarkFile(form) stamp := pdfengines.FormDataPdfStamp(form, false) - stampFiles := pdfengines.FormDataPdfStampFiles(form) + stampFile := pdfengines.FormDataPdfStampFile(form) rotateAngle, rotatePages := pdfengines.FormDataPdfRotate(form, false) var inputPath string @@ -504,11 +504,11 @@ func convertHtmlRoute(chromium Api, engine gotenberg.PdfEngine) api.Route { return fmt.Errorf("validate form data: %w", err) } - if (watermark.Source == gotenberg.StampSourceImage || watermark.Source == gotenberg.StampSourcePDF) && len(watermarkFiles) > 0 { - watermark.Expression = watermarkFiles[0] + if (watermark.Source == gotenberg.StampSourceImage || watermark.Source == gotenberg.StampSourcePDF) && watermarkFile != "" { + watermark.Expression = watermarkFile } - if (stamp.Source == gotenberg.StampSourceImage || stamp.Source == gotenberg.StampSourcePDF) && len(stampFiles) > 0 { - stamp.Expression = stampFiles[0] + if (stamp.Source == gotenberg.StampSourceImage || stamp.Source == gotenberg.StampSourcePDF) && stampFile != "" { + stamp.Expression = stampFile } url := fmt.Sprintf("file://%s", inputPath) @@ -568,9 +568,9 @@ func convertMarkdownRoute(chromium Api, engine gotenberg.PdfEngine) api.Route { userPassword, ownerPassword := pdfengines.FormDataPdfEncrypt(form) embedPaths := pdfengines.FormDataPdfEmbeds(form) watermark := pdfengines.FormDataPdfWatermark(form, false) - watermarkFiles := pdfengines.FormDataPdfWatermarkFiles(form) + watermarkFile := pdfengines.FormDataPdfWatermarkFile(form) stamp := pdfengines.FormDataPdfStamp(form, false) - stampFiles := pdfengines.FormDataPdfStampFiles(form) + stampFile := pdfengines.FormDataPdfStampFile(form) rotateAngle, rotatePages := pdfengines.FormDataPdfRotate(form, false) var ( @@ -586,11 +586,11 @@ func convertMarkdownRoute(chromium Api, engine gotenberg.PdfEngine) api.Route { return fmt.Errorf("validate form data: %w", err) } - if (watermark.Source == gotenberg.StampSourceImage || watermark.Source == gotenberg.StampSourcePDF) && len(watermarkFiles) > 0 { - watermark.Expression = watermarkFiles[0] + if (watermark.Source == gotenberg.StampSourceImage || watermark.Source == gotenberg.StampSourcePDF) && watermarkFile != "" { + watermark.Expression = watermarkFile } - if (stamp.Source == gotenberg.StampSourceImage || stamp.Source == gotenberg.StampSourcePDF) && len(stampFiles) > 0 { - stamp.Expression = stampFiles[0] + if (stamp.Source == gotenberg.StampSourceImage || stamp.Source == gotenberg.StampSourcePDF) && stampFile != "" { + stamp.Expression = stampFile } url, err := markdownToHtml(ctx, inputPath, markdownPaths) diff --git a/pkg/modules/libreoffice/routes.go b/pkg/modules/libreoffice/routes.go index ab57f865..5fc20bf3 100644 --- a/pkg/modules/libreoffice/routes.go +++ b/pkg/modules/libreoffice/routes.go @@ -33,9 +33,9 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap userPassword, ownerPassword := pdfengines.FormDataPdfEncrypt(form) embedPaths := pdfengines.FormDataPdfEmbeds(form) watermark := pdfengines.FormDataPdfWatermark(form, false) - watermarkFiles := pdfengines.FormDataPdfWatermarkFiles(form) + watermarkFile := pdfengines.FormDataPdfWatermarkFile(form) stamp := pdfengines.FormDataPdfStamp(form, false) - stampFiles := pdfengines.FormDataPdfStampFiles(form) + stampFile := pdfengines.FormDataPdfStampFile(form) angle, rotatePages := pdfengines.FormDataPdfRotate(form, false) zeroValuedSplitMode := gotenberg.SplitMode{} @@ -189,11 +189,11 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap return fmt.Errorf("validate form data: %w", err) } - if (watermark.Source == gotenberg.StampSourceImage || watermark.Source == gotenberg.StampSourcePDF) && len(watermarkFiles) > 0 { - watermark.Expression = watermarkFiles[0] + if (watermark.Source == gotenberg.StampSourceImage || watermark.Source == gotenberg.StampSourcePDF) && watermarkFile != "" { + watermark.Expression = watermarkFile } - if (stamp.Source == gotenberg.StampSourceImage || stamp.Source == gotenberg.StampSourcePDF) && len(stampFiles) > 0 { - stamp.Expression = stampFiles[0] + if (stamp.Source == gotenberg.StampSourceImage || stamp.Source == gotenberg.StampSourcePDF) && stampFile != "" { + stamp.Expression = stampFile } err = pdfengines.ValidatePdfFormatsCompat(pdfFormats, userPassword, embedPaths) diff --git a/pkg/modules/pdfengines/routes.go b/pkg/modules/pdfengines/routes.go index 81db75d1..bdac91e7 100644 --- a/pkg/modules/pdfengines/routes.go +++ b/pkg/modules/pdfengines/routes.go @@ -544,18 +544,18 @@ func formDataPdfStampOrWatermark(form *api.FormData, prefix string, mandatory bo } } -// FormDataPdfWatermarkFiles extracts watermark file paths from form data. -func FormDataPdfWatermarkFiles(form *api.FormData) []string { - var paths []string - form.Watermarks(&paths) - return paths +// FormDataPdfWatermarkFile extracts the watermark file path from form data. +func FormDataPdfWatermarkFile(form *api.FormData) string { + var path string + form.Watermark(&path) + return path } -// FormDataPdfStampFiles extracts stamp file paths from form data. -func FormDataPdfStampFiles(form *api.FormData) []string { - var paths []string - form.Stamps(&paths) - return paths +// FormDataPdfStampFile extracts the stamp file path from form data. +func FormDataPdfStampFile(form *api.FormData) string { + var path string + form.Stamp(&path) + return path } // WatermarkStub applies a watermark to a list of PDF files. If the stamp has @@ -608,9 +608,9 @@ func mergeRoute(engine gotenberg.PdfEngine) api.Route { userPassword, ownerPassword := FormDataPdfEncrypt(form) embedPaths := FormDataPdfEmbeds(form) watermark := FormDataPdfWatermark(form, false) - watermarkFiles := FormDataPdfWatermarkFiles(form) + watermarkFile := FormDataPdfWatermarkFile(form) stamp := FormDataPdfStamp(form, false) - stampFiles := FormDataPdfStampFiles(form) + stampFile := FormDataPdfStampFile(form) angle, rotatePages := FormDataPdfRotate(form, false) var inputPaths []string @@ -625,11 +625,11 @@ func mergeRoute(engine gotenberg.PdfEngine) api.Route { return fmt.Errorf("validate form data: %w", err) } - if (watermark.Source == gotenberg.StampSourceImage || watermark.Source == gotenberg.StampSourcePDF) && len(watermarkFiles) > 0 { - watermark.Expression = watermarkFiles[0] + if (watermark.Source == gotenberg.StampSourceImage || watermark.Source == gotenberg.StampSourcePDF) && watermarkFile != "" { + watermark.Expression = watermarkFile } - if (stamp.Source == gotenberg.StampSourceImage || stamp.Source == gotenberg.StampSourcePDF) && len(stampFiles) > 0 { - stamp.Expression = stampFiles[0] + if (stamp.Source == gotenberg.StampSourceImage || stamp.Source == gotenberg.StampSourcePDF) && stampFile != "" { + stamp.Expression = stampFile } err = ValidatePdfFormatsCompat(pdfFormats, userPassword, embedPaths) @@ -759,9 +759,9 @@ func splitRoute(engine gotenberg.PdfEngine) api.Route { userPassword, ownerPassword := FormDataPdfEncrypt(form) embedPaths := FormDataPdfEmbeds(form) watermark := FormDataPdfWatermark(form, false) - watermarkFiles := FormDataPdfWatermarkFiles(form) + watermarkFile := FormDataPdfWatermarkFile(form) stamp := FormDataPdfStamp(form, false) - stampFiles := FormDataPdfStampFiles(form) + stampFile := FormDataPdfStampFile(form) angle, rotatePages := FormDataPdfRotate(form, false) var inputPaths []string @@ -774,11 +774,11 @@ func splitRoute(engine gotenberg.PdfEngine) api.Route { return fmt.Errorf("validate form data: %w", err) } - if (watermark.Source == gotenberg.StampSourceImage || watermark.Source == gotenberg.StampSourcePDF) && len(watermarkFiles) > 0 { - watermark.Expression = watermarkFiles[0] + if (watermark.Source == gotenberg.StampSourceImage || watermark.Source == gotenberg.StampSourcePDF) && watermarkFile != "" { + watermark.Expression = watermarkFile } - if (stamp.Source == gotenberg.StampSourceImage || stamp.Source == gotenberg.StampSourcePDF) && len(stampFiles) > 0 { - stamp.Expression = stampFiles[0] + if (stamp.Source == gotenberg.StampSourceImage || stamp.Source == gotenberg.StampSourcePDF) && stampFile != "" { + stamp.Expression = stampFile } err = ValidatePdfFormatsCompat(pdfFormats, userPassword, embedPaths) @@ -1190,7 +1190,7 @@ func watermarkRoute(engine gotenberg.PdfEngine) api.Route { form := ctx.FormData() stamp := FormDataPdfWatermark(form, true) - watermarkFiles := FormDataPdfWatermarkFiles(form) + watermarkFile := FormDataPdfWatermarkFile(form) var inputPaths []string err := form. @@ -1201,7 +1201,7 @@ func watermarkRoute(engine gotenberg.PdfEngine) api.Route { } if stamp.Source == gotenberg.StampSourceImage || stamp.Source == gotenberg.StampSourcePDF { - if len(watermarkFiles) == 0 { + if watermarkFile == "" { return api.WrapError( errors.New("no watermark file provided"), api.NewSentinelHttpError( @@ -1210,7 +1210,7 @@ func watermarkRoute(engine gotenberg.PdfEngine) api.Route { ), ) } - stamp.Expression = watermarkFiles[0] + stamp.Expression = watermarkFile } err = WatermarkStub(ctx, engine, stamp, inputPaths) @@ -1241,7 +1241,7 @@ func stampRoute(engine gotenberg.PdfEngine) api.Route { form := ctx.FormData() stamp := FormDataPdfStamp(form, true) - stampFiles := FormDataPdfStampFiles(form) + stampFile := FormDataPdfStampFile(form) var inputPaths []string err := form. @@ -1252,7 +1252,7 @@ func stampRoute(engine gotenberg.PdfEngine) api.Route { } if stamp.Source == gotenberg.StampSourceImage || stamp.Source == gotenberg.StampSourcePDF { - if len(stampFiles) == 0 { + if stampFile == "" { return api.WrapError( errors.New("no stamp file provided"), api.NewSentinelHttpError( @@ -1261,7 +1261,7 @@ func stampRoute(engine gotenberg.PdfEngine) api.Route { ), ) } - stamp.Expression = stampFiles[0] + stamp.Expression = stampFile } err = StampStub(ctx, engine, stamp, inputPaths) diff --git a/test/integration/features/pdfengines_merge.feature b/test/integration/features/pdfengines_merge.feature index 34b14976..663dbd61 100644 --- a/test/integration/features/pdfengines_merge.feature +++ b/test/integration/features/pdfengines_merge.feature @@ -560,6 +560,32 @@ Feature: /forms/pdfengines/merge Then the response status code should be 200 Then the response header "Content-Type" should be "application/pdf" + @download-from + Scenario: POST /forms/pdfengines/merge (Watermark via Download From) + Given I have a Gotenberg container with the following environment variable(s): + | PDFENGINES_WATERMARK_ENGINES | pdfcpu | + Given I have a static server + When I make a "POST" request to Gotenberg at the "/forms/pdfengines/merge" endpoint with the following form data and header(s): + | files | testdata/page_1.pdf | file | + | files | testdata/page_2.pdf | file | + | downloadFrom | [{"url":"http://host.docker.internal:%d/static/testdata/watermark.png","field":"watermark"}] | field | + | watermarkSource | image | field | + Then the response status code should be 200 + Then the response header "Content-Type" should be "application/pdf" + + @download-from + Scenario: POST /forms/pdfengines/merge (Stamp via Download From) + Given I have a Gotenberg container with the following environment variable(s): + | PDFENGINES_STAMP_ENGINES | pdfcpu | + Given I have a static server + When I make a "POST" request to Gotenberg at the "/forms/pdfengines/merge" endpoint with the following form data and header(s): + | files | testdata/page_1.pdf | file | + | files | testdata/page_2.pdf | file | + | downloadFrom | [{"url":"http://host.docker.internal:%d/static/testdata/page_2.pdf","field":"stamp"}] | field | + | stampSource | pdf | field | + Then the response status code should be 200 + Then the response header "Content-Type" should be "application/pdf" + @webhook Scenario: POST /forms/pdfengines/merge (Webhook) Given I have a default Gotenberg container diff --git a/test/integration/features/pdfengines_stamp.feature b/test/integration/features/pdfengines_stamp.feature index b5649cc9..c9f288d8 100644 --- a/test/integration/features/pdfengines_stamp.feature +++ b/test/integration/features/pdfengines_stamp.feature @@ -45,7 +45,7 @@ Feature: /forms/pdfengines/stamp | PDFENGINES_STAMP_ENGINES | pdfcpu | When I make a "POST" request to Gotenberg at the "/forms/pdfengines/stamp" endpoint with the following form data and header(s): | files | testdata/page_1.pdf | file | - | stamps | testdata/watermark.png | file | + | stamp | testdata/watermark.png | file | | stampSource | image | field | Then the response status code should be 200 Then the response header "Content-Type" should be "application/pdf" @@ -56,7 +56,7 @@ Feature: /forms/pdfengines/stamp | PDFENGINES_STAMP_ENGINES | pdfcpu | When I make a "POST" request to Gotenberg at the "/forms/pdfengines/stamp" endpoint with the following form data and header(s): | files | testdata/page_1.pdf | file | - | stamps | testdata/page_2.pdf | file | + | stamp | testdata/page_2.pdf | file | | stampSource | pdf | field | Then the response status code should be 200 Then the response header "Content-Type" should be "application/pdf" @@ -67,7 +67,7 @@ Feature: /forms/pdfengines/stamp | PDFENGINES_STAMP_ENGINES | pdftk | When I make a "POST" request to Gotenberg at the "/forms/pdfengines/stamp" endpoint with the following form data and header(s): | files | testdata/page_1.pdf | file | - | stamps | testdata/page_2.pdf | file | + | stamp | testdata/page_2.pdf | file | | stampSource | pdf | field | Then the response status code should be 200 Then the response header "Content-Type" should be "application/pdf" @@ -86,6 +86,32 @@ Feature: /forms/pdfengines/stamp At least one PDF engine cannot process the requested stamp source type, while others may have failed due to different issues """ + @download-from + Scenario: POST /forms/pdfengines/stamp (Image via Download From) + Given I have a Gotenberg container with the following environment variable(s): + | PDFENGINES_STAMP_ENGINES | pdfcpu | + Given I have a static server + When I make a "POST" request to Gotenberg at the "/forms/pdfengines/stamp" endpoint with the following form data and header(s): + | files | testdata/page_1.pdf | file | + | downloadFrom | [{"url":"http://host.docker.internal:%d/static/testdata/watermark.png","field":"stamp"}] | field | + | stampSource | image | field | + Then the response status code should be 200 + Then the response header "Content-Type" should be "application/pdf" + Then there should be 1 PDF(s) in the response + + @download-from + Scenario: POST /forms/pdfengines/stamp (PDF via Download From) + Given I have a Gotenberg container with the following environment variable(s): + | PDFENGINES_STAMP_ENGINES | pdfcpu | + Given I have a static server + When I make a "POST" request to Gotenberg at the "/forms/pdfengines/stamp" endpoint with the following form data and header(s): + | files | testdata/page_1.pdf | file | + | downloadFrom | [{"url":"http://host.docker.internal:%d/static/testdata/page_2.pdf","field":"stamp"}] | field | + | stampSource | pdf | field | + Then the response status code should be 200 + Then the response header "Content-Type" should be "application/pdf" + Then there should be 1 PDF(s) in the response + Scenario: POST /forms/pdfengines/stamp (Many PDFs) Given I have a default Gotenberg container When I make a "POST" request to Gotenberg at the "/forms/pdfengines/stamp" endpoint with the following form data and header(s): diff --git a/test/integration/features/pdfengines_watermark.feature b/test/integration/features/pdfengines_watermark.feature index fc546f2b..95292f60 100644 --- a/test/integration/features/pdfengines_watermark.feature +++ b/test/integration/features/pdfengines_watermark.feature @@ -45,7 +45,7 @@ Feature: /forms/pdfengines/watermark | PDFENGINES_WATERMARK_ENGINES | pdfcpu | When I make a "POST" request to Gotenberg at the "/forms/pdfengines/watermark" endpoint with the following form data and header(s): | files | testdata/page_1.pdf | file | - | watermarks | testdata/watermark.png | file | + | watermark | testdata/watermark.png | file | | watermarkSource | image | field | Then the response status code should be 200 Then the response header "Content-Type" should be "application/pdf" @@ -56,7 +56,7 @@ Feature: /forms/pdfengines/watermark | PDFENGINES_WATERMARK_ENGINES | pdfcpu | When I make a "POST" request to Gotenberg at the "/forms/pdfengines/watermark" endpoint with the following form data and header(s): | files | testdata/page_1.pdf | file | - | watermarks | testdata/page_2.pdf | file | + | watermark | testdata/page_2.pdf | file | | watermarkSource | pdf | field | Then the response status code should be 200 Then the response header "Content-Type" should be "application/pdf" @@ -67,7 +67,7 @@ Feature: /forms/pdfengines/watermark | PDFENGINES_WATERMARK_ENGINES | pdftk | When I make a "POST" request to Gotenberg at the "/forms/pdfengines/watermark" endpoint with the following form data and header(s): | files | testdata/page_1.pdf | file | - | watermarks | testdata/page_2.pdf | file | + | watermark | testdata/page_2.pdf | file | | watermarkSource | pdf | field | Then the response status code should be 200 Then the response header "Content-Type" should be "application/pdf" @@ -86,6 +86,32 @@ Feature: /forms/pdfengines/watermark At least one PDF engine cannot process the requested stamp source type, while others may have failed due to different issues """ + @download-from + Scenario: POST /forms/pdfengines/watermark (Image via Download From) + Given I have a Gotenberg container with the following environment variable(s): + | PDFENGINES_WATERMARK_ENGINES | pdfcpu | + Given I have a static server + When I make a "POST" request to Gotenberg at the "/forms/pdfengines/watermark" endpoint with the following form data and header(s): + | files | testdata/page_1.pdf | file | + | downloadFrom | [{"url":"http://host.docker.internal:%d/static/testdata/watermark.png","field":"watermark"}] | field | + | watermarkSource | image | field | + Then the response status code should be 200 + Then the response header "Content-Type" should be "application/pdf" + Then there should be 1 PDF(s) in the response + + @download-from + Scenario: POST /forms/pdfengines/watermark (PDF via Download From) + Given I have a Gotenberg container with the following environment variable(s): + | PDFENGINES_WATERMARK_ENGINES | pdfcpu | + Given I have a static server + When I make a "POST" request to Gotenberg at the "/forms/pdfengines/watermark" endpoint with the following form data and header(s): + | files | testdata/page_1.pdf | file | + | downloadFrom | [{"url":"http://host.docker.internal:%d/static/testdata/page_2.pdf","field":"watermark"}] | field | + | watermarkSource | pdf | field | + Then the response status code should be 200 + Then the response header "Content-Type" should be "application/pdf" + Then there should be 1 PDF(s) in the response + Scenario: POST /forms/pdfengines/watermark (Many PDFs) Given I have a default Gotenberg container When I make a "POST" request to Gotenberg at the "/forms/pdfengines/watermark" endpoint with the following form data and header(s):