mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-18 05:02:15 +01:00
feat(pdfengines): add write metadata option on merge route
This commit is contained in:
@@ -27,12 +27,22 @@ func mergeRoute(engine gotenberg.PdfEngine) api.Route {
|
|||||||
inputPaths []string
|
inputPaths []string
|
||||||
pdfa string
|
pdfa string
|
||||||
pdfua bool
|
pdfua bool
|
||||||
|
metadata map[string]interface{}
|
||||||
)
|
)
|
||||||
|
|
||||||
err := ctx.FormData().
|
err := ctx.FormData().
|
||||||
MandatoryPaths([]string{".pdf"}, &inputPaths).
|
MandatoryPaths([]string{".pdf"}, &inputPaths).
|
||||||
String("pdfa", &pdfa, "").
|
String("pdfa", &pdfa, "").
|
||||||
Bool("pdfua", &pdfua, false).
|
Bool("pdfua", &pdfua, false).
|
||||||
|
Custom("metadata", func(value string) error {
|
||||||
|
if len(value) > 0 {
|
||||||
|
err := json.Unmarshal([]byte(value), &metadata)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unmarshal metadata: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}).
|
||||||
Validate()
|
Validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("validate form data: %w", err)
|
return fmt.Errorf("validate form data: %w", err)
|
||||||
@@ -68,6 +78,14 @@ func mergeRoute(engine gotenberg.PdfEngine) api.Route {
|
|||||||
outputPath = convertOutputPath
|
outputPath = convertOutputPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Writes and potentially overrides metadata entries, if any.
|
||||||
|
if len(metadata) > 0 {
|
||||||
|
err = engine.WriteMetadata(ctx, ctx.Log(), metadata, outputPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("write metadata: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Last but not least, add the output path to the context so that
|
// Last but not least, add the output path to the context so that
|
||||||
// the API is able to send it as a response to the client.
|
// the API is able to send it as a response to the client.
|
||||||
err = ctx.AddOutputPaths(outputPath)
|
err = ctx.AddOutputPaths(outputPath)
|
||||||
|
|||||||
@@ -35,7 +35,27 @@ func TestMergeHandler(t *testing.T) {
|
|||||||
expectOutputPathsCount: 0,
|
expectOutputPathsCount: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
scenario: "error from PDF engine",
|
scenario: "invalid metadata form field",
|
||||||
|
ctx: func() *api.ContextMock {
|
||||||
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
|
ctx.SetFiles(map[string]string{
|
||||||
|
"file.pdf": "/file.pdf",
|
||||||
|
"file2.pdf": "/file2.pdf",
|
||||||
|
})
|
||||||
|
ctx.SetValues(map[string][]string{
|
||||||
|
"metadata": {
|
||||||
|
"foo",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return ctx
|
||||||
|
}(),
|
||||||
|
expectError: true,
|
||||||
|
expectHttpError: true,
|
||||||
|
expectHttpStatus: http.StatusBadRequest,
|
||||||
|
expectOutputPathsCount: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: "PDF engine merge error",
|
||||||
ctx: func() *api.ContextMock {
|
ctx: func() *api.ContextMock {
|
||||||
ctx := &api.ContextMock{Context: new(api.Context)}
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
ctx.SetFiles(map[string]string{
|
ctx.SetFiles(map[string]string{
|
||||||
@@ -53,6 +73,60 @@ func TestMergeHandler(t *testing.T) {
|
|||||||
expectHttpError: false,
|
expectHttpError: false,
|
||||||
expectOutputPathsCount: 0,
|
expectOutputPathsCount: 0,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
scenario: "PDF engine convert error",
|
||||||
|
ctx: func() *api.ContextMock {
|
||||||
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
|
ctx.SetFiles(map[string]string{
|
||||||
|
"file.pdf": "/file.pdf",
|
||||||
|
"file2.pdf": "/file2.pdf",
|
||||||
|
})
|
||||||
|
ctx.SetValues(map[string][]string{
|
||||||
|
"pdfa": {
|
||||||
|
gotenberg.PdfA1b,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return ctx
|
||||||
|
}(),
|
||||||
|
engine: &gotenberg.PdfEngineMock{
|
||||||
|
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
|
||||||
|
return errors.New("foo")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectError: true,
|
||||||
|
expectHttpError: false,
|
||||||
|
expectOutputPathsCount: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: "PDF engine write metadata error",
|
||||||
|
ctx: func() *api.ContextMock {
|
||||||
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
|
ctx.SetFiles(map[string]string{
|
||||||
|
"file.pdf": "/file.pdf",
|
||||||
|
"file2.pdf": "/file2.pdf",
|
||||||
|
})
|
||||||
|
ctx.SetValues(map[string][]string{
|
||||||
|
"metadata": {
|
||||||
|
"{\"Creator\": \"foo\", \"Producer\": \"bar\" }",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return ctx
|
||||||
|
}(),
|
||||||
|
engine: &gotenberg.PdfEngineMock{
|
||||||
|
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error {
|
||||||
|
return errors.New("foo")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectError: true,
|
||||||
|
expectHttpError: false,
|
||||||
|
expectOutputPathsCount: 0,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
scenario: "cannot add output paths",
|
scenario: "cannot add output paths",
|
||||||
ctx: func() *api.ContextMock {
|
ctx: func() *api.ContextMock {
|
||||||
@@ -75,25 +149,6 @@ func TestMergeHandler(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
scenario: "success",
|
scenario: "success",
|
||||||
ctx: func() *api.ContextMock {
|
|
||||||
ctx := &api.ContextMock{Context: new(api.Context)}
|
|
||||||
ctx.SetFiles(map[string]string{
|
|
||||||
"file.pdf": "/file.pdf",
|
|
||||||
"file2.pdf": "/file2.pdf",
|
|
||||||
})
|
|
||||||
return ctx
|
|
||||||
}(),
|
|
||||||
engine: &gotenberg.PdfEngineMock{
|
|
||||||
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectError: false,
|
|
||||||
expectHttpError: false,
|
|
||||||
expectOutputPathsCount: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scenario: "error from PDF engine (convert)",
|
|
||||||
ctx: func() *api.ContextMock {
|
ctx: func() *api.ContextMock {
|
||||||
ctx := &api.ContextMock{Context: new(api.Context)}
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
ctx.SetFiles(map[string]string{
|
ctx.SetFiles(map[string]string{
|
||||||
@@ -104,6 +159,9 @@ func TestMergeHandler(t *testing.T) {
|
|||||||
"pdfa": {
|
"pdfa": {
|
||||||
gotenberg.PdfA1b,
|
gotenberg.PdfA1b,
|
||||||
},
|
},
|
||||||
|
"metadata": {
|
||||||
|
"{\"Creator\": \"foo\", \"Producer\": \"bar\" }",
|
||||||
|
},
|
||||||
})
|
})
|
||||||
return ctx
|
return ctx
|
||||||
}(),
|
}(),
|
||||||
@@ -112,36 +170,9 @@ func TestMergeHandler(t *testing.T) {
|
|||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
|
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
|
||||||
return errors.New("foo")
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectError: true,
|
|
||||||
expectHttpError: false,
|
|
||||||
expectOutputPathsCount: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scenario: "success with PDF/A & PDF/UA form fields",
|
|
||||||
ctx: func() *api.ContextMock {
|
|
||||||
ctx := &api.ContextMock{Context: new(api.Context)}
|
|
||||||
ctx.SetFiles(map[string]string{
|
|
||||||
"file.pdf": "/file.pdf",
|
|
||||||
"file2.pdf": "/file2.pdf",
|
|
||||||
})
|
|
||||||
ctx.SetValues(map[string][]string{
|
|
||||||
"pdfa": {
|
|
||||||
gotenberg.PdfA1b,
|
|
||||||
},
|
|
||||||
"pdfua": {
|
|
||||||
"true",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return ctx
|
|
||||||
}(),
|
|
||||||
engine: &gotenberg.PdfEngineMock{
|
|
||||||
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
|
WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error {
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user