From 2baa59cb3a791be4ef9684244632d1ee0de49a12 Mon Sep 17 00:00:00 2001 From: Julien Neuhart Date: Fri, 20 Feb 2026 21:21:19 +0100 Subject: [PATCH] refactor(gofix): modernize --- cmd/gotenberg.go | 6 ++-- pkg/gotenberg/context.go | 12 ++++---- pkg/gotenberg/context_test.go | 12 ++++---- pkg/gotenberg/debug.go | 16 +++++----- pkg/gotenberg/debug_test.go | 8 ++--- pkg/gotenberg/logging.go | 8 ++--- pkg/gotenberg/mocks.go | 12 ++++---- pkg/gotenberg/modules.go | 2 +- pkg/gotenberg/pdfengine.go | 4 +-- pkg/gotenberg/supervisor_test.go | 30 +++++++------------ pkg/modules/api/formdata.go | 6 ++-- pkg/modules/chromium/chromium.go | 4 +-- pkg/modules/chromium/debug.go | 2 +- pkg/modules/chromium/events.go | 16 +++++----- pkg/modules/chromium/routes.go | 6 ++-- pkg/modules/chromium/stream.go | 6 ++-- pkg/modules/exiftool/exiftool.go | 12 ++++---- pkg/modules/libreoffice/api/api.go | 4 +-- .../libreoffice/pdfengine/pdfengine.go | 4 +-- pkg/modules/pdfcpu/pdfcpu.go | 16 +++++----- pkg/modules/pdfengines/multi.go | 6 ++-- pkg/modules/pdfengines/multi_test.go | 30 +++++++++---------- pkg/modules/pdfengines/pdfengines.go | 9 ++---- pkg/modules/pdfengines/routes.go | 8 ++--- pkg/modules/pdftk/pdftk.go | 8 ++--- pkg/modules/qpdf/qpdf.go | 8 ++--- test/integration/scenario/compare.go | 10 +++---- test/integration/scenario/containers.go | 2 +- test/integration/scenario/scenario.go | 13 ++++---- 29 files changed, 131 insertions(+), 149 deletions(-) diff --git a/cmd/gotenberg.go b/cmd/gotenberg.go index c7bc3a1..16a9a62 100644 --- a/cmd/gotenberg.go +++ b/cmd/gotenberg.go @@ -45,10 +45,10 @@ func Run() { fs.Bool("gotenberg-build-debug-data", true, "Set if build data is needed") descriptors := gotenberg.GetModuleDescriptors() - var modsInfo string + var modsInfo strings.Builder for _, desc := range descriptors { fs.AddFlagSet(desc.FlagSet) - modsInfo += desc.ID + " " + modsInfo.WriteString(desc.ID + " ") } // Parse the flags. @@ -94,7 +94,7 @@ func Run() { if !hideBanner { fmt.Printf(banner, Version) } - fmt.Printf("[SYSTEM] modules: %s\n", modsInfo) + fmt.Printf("[SYSTEM] modules: %s\n", modsInfo.String()) ctx := gotenberg.NewContext(parsedFlags, descriptors) diff --git a/pkg/gotenberg/context.go b/pkg/gotenberg/context.go index 507f30d..a656e13 100644 --- a/pkg/gotenberg/context.go +++ b/pkg/gotenberg/context.go @@ -10,7 +10,7 @@ import ( type Context struct { flags ParsedFlags descriptors []ModuleDescriptor - moduleInstances map[string]interface{} + moduleInstances map[string]any } // NewContext creates a [Context]. @@ -22,7 +22,7 @@ func NewContext( return &Context{ flags: flags, descriptors: descriptors, - moduleInstances: make(map[string]interface{}), + moduleInstances: make(map[string]any), } } @@ -45,7 +45,7 @@ func (ctx *Context) ParsedFlags() ParsedFlags { // // If the module has not yet been initialized, this method // initializes it. Otherwise, returns the already initialized instance. -func (ctx *Context) Module(kind interface{}) (interface{}, error) { +func (ctx *Context) Module(kind any) (any, error) { mods, err := ctx.Modules(kind) if err != nil { return nil, fmt.Errorf("get module: %w", err) @@ -70,10 +70,10 @@ func (ctx *Context) Module(kind interface{}) (interface{}, error) { // // If one or more modules have not yet been initialized, this method // initializes them. Otherwise, returns the already initialized instances. -func (ctx *Context) Modules(kind interface{}) ([]interface{}, error) { +func (ctx *Context) Modules(kind any) ([]any, error) { realKind := reflect.TypeOf(kind).Elem() - var mods []interface{} + var mods []any for _, desc := range ctx.descriptors { newInstance := desc.New() @@ -101,7 +101,7 @@ func (ctx *Context) Modules(kind interface{}) ([]interface{}, error) { // loadModule calls the Provision and/or Validate methods of the requested // module if it satisfies the [Provisioner] and/or [Validator] interfaces. -func (ctx *Context) loadModule(id string, instance interface{}) error { +func (ctx *Context) loadModule(id string, instance any) error { if prov, ok := instance.(Provisioner); ok { // The instance can be provisioned. err := prov.Provision(ctx) diff --git a/pkg/gotenberg/context_test.go b/pkg/gotenberg/context_test.go index f8bc4d6..48f6e1f 100644 --- a/pkg/gotenberg/context_test.go +++ b/pkg/gotenberg/context_test.go @@ -9,7 +9,7 @@ func TestContext_Module(t *testing.T) { for _, tc := range []struct { scenario string mods []ModuleDescriptor - kind interface{} + kind any expectError bool }{ { @@ -80,7 +80,7 @@ func TestContext_Modules(t *testing.T) { for _, tc := range []struct { scenario string mods []ModuleDescriptor - kind interface{} + kind any expectError bool }{ { @@ -151,12 +151,12 @@ func TestContext_Modules(t *testing.T) { func TestContext_loadModule(t *testing.T) { for _, tc := range []struct { scenario string - instance interface{} + instance any expectError bool }{ { scenario: "module with error on provision", - instance: func() interface{} { + instance: func() any { mod := &struct { ModuleMock ProvisionerMock @@ -171,7 +171,7 @@ func TestContext_loadModule(t *testing.T) { }, { scenario: "module with error on validation", - instance: func() interface{} { + instance: func() any { mod := &struct { ModuleMock ValidatorMock @@ -186,7 +186,7 @@ func TestContext_loadModule(t *testing.T) { }, { scenario: "success", - instance: func() interface{} { + instance: func() any { mod := &struct { ModuleMock ValidatorMock diff --git a/pkg/gotenberg/debug.go b/pkg/gotenberg/debug.go index d79e183..7c5a2c9 100644 --- a/pkg/gotenberg/debug.go +++ b/pkg/gotenberg/debug.go @@ -11,12 +11,12 @@ import ( // DebugInfo gathers data for debugging. type DebugInfo struct { - Version string `json:"version"` - Timezone string `json:"timezone"` - Architecture string `json:"architecture"` - Modules []string `json:"modules"` - ModulesAdditionalData map[string]map[string]interface{} `json:"modules_additional_data"` - Flags map[string]interface{} `json:"flags"` + Version string `json:"version"` + Timezone string `json:"timezone"` + Architecture string `json:"architecture"` + Modules []string `json:"modules"` + ModulesAdditionalData map[string]map[string]any `json:"modules_additional_data"` + Flags map[string]any `json:"flags"` } // BuildDebug builds the debug data from modules. @@ -29,8 +29,8 @@ func BuildDebug(ctx *Context) { Timezone: time.Now().Location().String(), Architecture: runtime.GOARCH, Modules: make([]string, len(ctx.moduleInstances)), - ModulesAdditionalData: make(map[string]map[string]interface{}), - Flags: make(map[string]interface{}), + ModulesAdditionalData: make(map[string]map[string]any), + Flags: make(map[string]any), } i := 0 diff --git a/pkg/gotenberg/debug_test.go b/pkg/gotenberg/debug_test.go index c31466c..268a3f4 100644 --- a/pkg/gotenberg/debug_test.go +++ b/pkg/gotenberg/debug_test.go @@ -33,8 +33,8 @@ func TestBuildDebug(t *testing.T) { mod2.DescriptorMock = func() ModuleDescriptor { return ModuleDescriptor{ID: "bar", New: func() Module { return mod2 }} } - mod2.DebugMock = func() map[string]interface{} { - return map[string]interface{}{ + mod2.DebugMock = func() map[string]any { + return map[string]any{ "foo": "bar", } } @@ -59,12 +59,12 @@ func TestBuildDebug(t *testing.T) { "bar", "foo", }, - ModulesAdditionalData: map[string]map[string]interface{}{ + ModulesAdditionalData: map[string]map[string]any{ "bar": { "foo": "bar", }, }, - Flags: map[string]interface{}{ + Flags: map[string]any{ "foo": "bar", }, } diff --git a/pkg/gotenberg/logging.go b/pkg/gotenberg/logging.go index ea0bdf4..be502c2 100644 --- a/pkg/gotenberg/logging.go +++ b/pkg/gotenberg/logging.go @@ -32,22 +32,22 @@ func NewLeveledLogger(logger *zap.Logger) *LeveledLogger { } // Error logs a message at the error level using the wrapped zap.Logger. -func (leveled LeveledLogger) Error(msg string, keysAndValues ...interface{}) { +func (leveled LeveledLogger) Error(msg string, keysAndValues ...any) { leveled.logger.Error(fmt.Sprintf("%s: %+v", msg, keysAndValues)) } // Warn logs a message at the warning level using the wrapped zap.Logger. -func (leveled LeveledLogger) Warn(msg string, keysAndValues ...interface{}) { +func (leveled LeveledLogger) Warn(msg string, keysAndValues ...any) { leveled.logger.Warn(fmt.Sprintf("%s: %+v", msg, keysAndValues)) } // Info logs a message at the info level using the wrapped zap.Logger. -func (leveled LeveledLogger) Info(msg string, keysAndValues ...interface{}) { +func (leveled LeveledLogger) Info(msg string, keysAndValues ...any) { leveled.logger.Info(fmt.Sprintf("%s: %+v", msg, keysAndValues)) } // Debug logs a message at the debug level using the wrapped zap.Logger. -func (leveled LeveledLogger) Debug(msg string, keysAndValues ...interface{}) { +func (leveled LeveledLogger) Debug(msg string, keysAndValues ...any) { leveled.logger.Debug(fmt.Sprintf("%s: %+v", msg, keysAndValues)) } diff --git a/pkg/gotenberg/mocks.go b/pkg/gotenberg/mocks.go index 4478256..6a0d503 100644 --- a/pkg/gotenberg/mocks.go +++ b/pkg/gotenberg/mocks.go @@ -35,10 +35,10 @@ func (mod *ValidatorMock) Validate() error { } type DebuggableMock struct { - DebugMock func() map[string]interface{} + DebugMock func() map[string]any } -func (mod *DebuggableMock) Debug() map[string]interface{} { +func (mod *DebuggableMock) Debug() map[string]any { return mod.DebugMock() } @@ -50,8 +50,8 @@ type PdfEngineMock struct { SplitMock func(ctx context.Context, logger *zap.Logger, mode SplitMode, inputPath, outputDirPath string) ([]string, error) FlattenMock func(ctx context.Context, logger *zap.Logger, inputPath string) error ConvertMock func(ctx context.Context, logger *zap.Logger, formats PdfFormats, inputPath, outputPath string) error - ReadMetadataMock func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) - WriteMetadataMock func(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error + ReadMetadataMock func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]any, error) + WriteMetadataMock func(ctx context.Context, logger *zap.Logger, metadata map[string]any, inputPath string) error EncryptMock func(ctx context.Context, logger *zap.Logger, inputPath, userPassword, ownerPassword string) error EmbedFilesMock func(ctx context.Context, logger *zap.Logger, filePaths []string, inputPath string) error } @@ -72,11 +72,11 @@ func (engine *PdfEngineMock) Convert(ctx context.Context, logger *zap.Logger, fo return engine.ConvertMock(ctx, logger, formats, inputPath, outputPath) } -func (engine *PdfEngineMock) ReadMetadata(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) { +func (engine *PdfEngineMock) ReadMetadata(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]any, error) { return engine.ReadMetadataMock(ctx, logger, inputPath) } -func (engine *PdfEngineMock) WriteMetadata(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error { +func (engine *PdfEngineMock) WriteMetadata(ctx context.Context, logger *zap.Logger, metadata map[string]any, inputPath string) error { return engine.WriteMetadataMock(ctx, logger, metadata, inputPath) } diff --git a/pkg/gotenberg/modules.go b/pkg/gotenberg/modules.go index 3df3145..f74a414 100644 --- a/pkg/gotenberg/modules.go +++ b/pkg/gotenberg/modules.go @@ -78,7 +78,7 @@ type SystemLogger interface { // Debuggable is a module interface for modules which want to provide // additional debug data. type Debuggable interface { - Debug() map[string]interface{} + Debug() map[string]any } // MustRegisterModule registers a module. diff --git a/pkg/gotenberg/pdfengine.go b/pkg/gotenberg/pdfengine.go index 5e9dceb..2709b43 100644 --- a/pkg/gotenberg/pdfengine.go +++ b/pkg/gotenberg/pdfengine.go @@ -133,10 +133,10 @@ type PdfEngine interface { Convert(ctx context.Context, logger *zap.Logger, formats PdfFormats, inputPath, outputPath string) error // ReadMetadata extracts the metadata of a given PDF file. - ReadMetadata(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) + ReadMetadata(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]any, error) // WriteMetadata writes the metadata into a given PDF file. - WriteMetadata(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error + WriteMetadata(ctx context.Context, logger *zap.Logger, metadata map[string]any, inputPath string) error // Encrypt adds password protection to a PDF file. // The userPassword is required to open the document. diff --git a/pkg/gotenberg/supervisor_test.go b/pkg/gotenberg/supervisor_test.go index 123a916..8b57150 100644 --- a/pkg/gotenberg/supervisor_test.go +++ b/pkg/gotenberg/supervisor_test.go @@ -409,14 +409,12 @@ func TestProcessSupervisor_Run(t *testing.T) { errorChan := make(chan error, tc.tasksToRun) for i := 0; i < tc.tasksToRun; i++ { - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := ps.Run(ctx, logger, task) if err != nil { errorChan <- err } - }() + }) } wg.Wait() @@ -522,17 +520,15 @@ func TestProcessSupervisor_ReqQueueSize(t *testing.T) { var wg sync.WaitGroup errorChan := make(chan error, 10) - for i := 0; i < 10; i++ { - wg.Add(1) - go func() { - defer wg.Done() + for range 10 { + wg.Go(func() { err := ps.Run(ctx, logger, func() error { return nil }) if err != nil { errorChan <- err } - }() + }) } // We have to wait a little bit so that the request queue size may change. @@ -652,10 +648,8 @@ func TestProcessSupervisor_ConcurrentRun(t *testing.T) { var wg sync.WaitGroup tasks := 6 - for i := 0; i < tasks; i++ { - wg.Add(1) - go func() { - defer wg.Done() + for range tasks { + wg.Go(func() { err := ps.Run(ctx, logger, func() error { cur := running.Add(1) for { @@ -671,7 +665,7 @@ func TestProcessSupervisor_ConcurrentRun(t *testing.T) { if err != nil { t.Errorf("unexpected error: %v", err) } - }() + }) } wg.Wait() @@ -714,10 +708,8 @@ func TestProcessSupervisor_RestartDrainsAllSlots(t *testing.T) { var wg sync.WaitGroup tasks := 3 - for i := 0; i < tasks; i++ { - wg.Add(1) - go func() { - defer wg.Done() + for range tasks { + wg.Go(func() { err := ps.Run(ctx, logger, func() error { time.Sleep(50 * time.Millisecond) return nil @@ -725,7 +717,7 @@ func TestProcessSupervisor_RestartDrainsAllSlots(t *testing.T) { if err != nil { t.Errorf("unexpected error: %v", err) } - }() + }) } wg.Wait() diff --git a/pkg/modules/api/formdata.go b/pkg/modules/api/formdata.go index d2d5bf7..632a67d 100644 --- a/pkg/modules/api/formdata.go +++ b/pkg/modules/api/formdata.go @@ -439,7 +439,7 @@ func (form *FormData) append(err error) { // mustValue binds the target interface with a form field. If the value is // empty or the "key" does not exist, it binds the default value. Currently, // only the string, bool, int, float64 and time.Duration types are bindable. -func (form *FormData) mustValue(key string, target interface{}, defaultValue interface{}) *FormData { +func (form *FormData) mustValue(key string, target any, defaultValue any) *FormData { val, ok := form.values[key] if !ok || val[0] == "" { @@ -468,7 +468,7 @@ func (form *FormData) mustValue(key string, target interface{}, defaultValue int // populates an error if the value is empty or the "key" does not exist. // Currently, only the string, bool, int, float64 and time.Duration types are // bindable. -func (form *FormData) mustMandatoryField(key string, target interface{}) *FormData { +func (form *FormData) mustMandatoryField(key string, target any) *FormData { val, ok := form.values[key] if !ok || val[0] == "" { @@ -487,7 +487,7 @@ func (form *FormData) mustMandatoryField(key string, target interface{}) *FormDa // mustAssign parses the string value and tries to convert it to the target // interface real type. Currently, only the string, bool, int, float64 and // time.Duration types are bindable. -func (form *FormData) mustAssign(key, value string, target interface{}) *FormData { +func (form *FormData) mustAssign(key, value string, target any) *FormData { var err error switch t := (target).(type) { diff --git a/pkg/modules/chromium/chromium.go b/pkg/modules/chromium/chromium.go index 5619756..b952a60 100644 --- a/pkg/modules/chromium/chromium.go +++ b/pkg/modules/chromium/chromium.go @@ -565,8 +565,8 @@ func (mod *Chromium) Stop(ctx context.Context) error { } // Debug returns additional debug data. -func (mod *Chromium) Debug() map[string]interface{} { - debug := make(map[string]interface{}) +func (mod *Chromium) Debug() map[string]any { + debug := make(map[string]any) cmd := exec.Command(mod.args.binPath, "--version") //nolint:gosec cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} diff --git a/pkg/modules/chromium/debug.go b/pkg/modules/chromium/debug.go index 1b5f930..1aabd0f 100644 --- a/pkg/modules/chromium/debug.go +++ b/pkg/modules/chromium/debug.go @@ -21,7 +21,7 @@ func (debug *debugLogger) Write(p []byte) (n int, err error) { } // Printf logs a debug message. -func (debug *debugLogger) Printf(format string, v ...interface{}) { +func (debug *debugLogger) Printf(format string, v ...any) { debug.logger.Debug(fmt.Sprintf(format, v...)) } diff --git a/pkg/modules/chromium/events.go b/pkg/modules/chromium/events.go index 1d77f5c..7e95c6d 100644 --- a/pkg/modules/chromium/events.go +++ b/pkg/modules/chromium/events.go @@ -39,7 +39,7 @@ func listenForEventRequestPaused(ctx context.Context, logger *zap.Logger, option logger.Debug(fmt.Sprintf("extra HTTP headers: %+v", options.extraHttpHeaders)) } - chromedp.ListenTarget(ctx, func(ev interface{}) { + chromedp.ListenTarget(ctx, func(ev any) { switch e := ev.(type) { case *fetch.EventRequestPaused: go func() { @@ -176,7 +176,7 @@ func listenForEventResponseReceived( } } - chromedp.ListenTarget(ctx, func(ev interface{}) { + chromedp.ListenTarget(ctx, func(ev any) { switch ev := ev.(type) { case *network.EventResponseReceived: if ev.Response.URL == options.mainPageUrl { @@ -299,7 +299,7 @@ type eventLoadingFailedOptions struct { // https://github.com/gotenberg/gotenberg/issues/959. // https://github.com/gotenberg/gotenberg/issues/1021. func listenForEventLoadingFailed(ctx context.Context, logger *zap.Logger, options eventLoadingFailedOptions) { - chromedp.ListenTarget(ctx, func(ev interface{}) { + chromedp.ListenTarget(ctx, func(ev any) { switch ev := ev.(type) { case *network.EventLoadingFailed: logger.Debug(fmt.Sprintf("event EventLoadingFailed fired: %+v", ev.ErrorText)) @@ -355,7 +355,7 @@ func listenForEventLoadingFailed(ctx context.Context, logger *zap.Logger, option // appends those exceptions to the given error pointer. // See https://github.com/gotenberg/gotenberg/issues/262. func listenForEventExceptionThrown(ctx context.Context, logger *zap.Logger, consoleExceptions *error, consoleExceptionsMu *sync.RWMutex) { - chromedp.ListenTarget(ctx, func(ev interface{}) { + chromedp.ListenTarget(ctx, func(ev any) { switch ev := ev.(type) { case *runtime.EventExceptionThrown: logger.Debug(fmt.Sprintf("event EventExceptionThrown fired: %+v", ev.ExceptionDetails)) @@ -374,7 +374,7 @@ func waitForEventDomContentEventFired(ctx context.Context, logger *zap.Logger) f return func() error { ch := make(chan struct{}) cctx, cancel := context.WithCancel(ctx) - chromedp.ListenTarget(cctx, func(ev interface{}) { + chromedp.ListenTarget(cctx, func(ev any) { switch ev.(type) { case *page.EventDomContentEventFired: cancel() @@ -398,7 +398,7 @@ func waitForEventLoadEventFired(ctx context.Context, logger *zap.Logger) func() return func() error { ch := make(chan struct{}) cctx, cancel := context.WithCancel(ctx) - chromedp.ListenTarget(cctx, func(ev interface{}) { + chromedp.ListenTarget(cctx, func(ev any) { switch ev.(type) { case *page.EventLoadEventFired: cancel() @@ -422,7 +422,7 @@ func waitForEventNetworkIdle(ctx context.Context, logger *zap.Logger) func() err return func() error { ch := make(chan struct{}) cctx, cancel := context.WithCancel(ctx) - chromedp.ListenTarget(cctx, func(ev interface{}) { + chromedp.ListenTarget(cctx, func(ev any) { switch e := ev.(type) { case *page.EventLifecycleEvent: if e.Name == "networkIdle" { @@ -448,7 +448,7 @@ func waitForEventLoadingFinished(ctx context.Context, logger *zap.Logger) func() return func() error { ch := make(chan struct{}) cctx, cancel := context.WithCancel(ctx) - chromedp.ListenTarget(cctx, func(ev interface{}) { + chromedp.ListenTarget(cctx, func(ev any) { switch ev.(type) { case *network.EventLoadingFinished: cancel() diff --git a/pkg/modules/chromium/routes.go b/pkg/modules/chromium/routes.go index d3ec73d..426b97a 100644 --- a/pkg/modules/chromium/routes.go +++ b/pkg/modules/chromium/routes.go @@ -172,8 +172,8 @@ func FormDataChromiumOptions(ctx *api.Context) (*api.FormData, Options) { var valueTokens []string var invalidScopeToken bool - tokens := strings.Split(v, ";") - for _, token := range tokens { + tokens := strings.SplitSeq(v, ";") + for token := range tokens { if strings.HasPrefix(strings.ToLower(strings.TrimSpace(token)), "scope") { tokenNoSpaces := strings.Join(strings.Fields(token), "") parts := strings.SplitN(tokenNoSpaces, "=", 2) @@ -686,7 +686,7 @@ func markdownToHtml(ctx *api.Context, inputPath string, markdownPaths []string) return fmt.Sprintf("file://%s", inputPath), nil } -func convertUrl(ctx *api.Context, chromium Api, engine gotenberg.PdfEngine, url string, options PdfOptions, mode gotenberg.SplitMode, pdfFormats gotenberg.PdfFormats, metadata map[string]interface{}, userPassword, ownerPassword string, embedPaths []string) error { +func convertUrl(ctx *api.Context, chromium Api, engine gotenberg.PdfEngine, url string, options PdfOptions, mode gotenberg.SplitMode, pdfFormats gotenberg.PdfFormats, metadata map[string]any, userPassword, ownerPassword string, embedPaths []string) error { outputPath := ctx.GeneratePath(".pdf") // See https://github.com/gotenberg/gotenberg/issues/1130. filename := ctx.OutputFilename(outputPath) diff --git a/pkg/modules/chromium/stream.go b/pkg/modules/chromium/stream.go index 23092a4..00b16ff 100644 --- a/pkg/modules/chromium/stream.go +++ b/pkg/modules/chromium/stream.go @@ -39,11 +39,9 @@ func (reader *streamReader) Read(p []byte) (n int, err error) { // Chromium might have an off-by-one when deciding the maximum size (at // least for base64 encoded data), usually it will overflow. We subtract // one to make sure it fits into p. - size := len(p) - 1 - if size < 1 { + size := max(len(p)-1, // Safety-check to avoid crashing Chrome (e.g. via SetSize(-1)). - size = 1 - } + 1) reply, err := reader.next(reader.pos, size) if err != nil { diff --git a/pkg/modules/exiftool/exiftool.go b/pkg/modules/exiftool/exiftool.go index 4a2ac09..a00ba65 100644 --- a/pkg/modules/exiftool/exiftool.go +++ b/pkg/modules/exiftool/exiftool.go @@ -57,8 +57,8 @@ func (engine *ExifTool) Validate() error { } // Debug returns additional debug data. -func (engine *ExifTool) Debug() map[string]interface{} { - debug := make(map[string]interface{}) +func (engine *ExifTool) Debug() map[string]any { + debug := make(map[string]any) cmd := exec.Command(engine.binPath, "-ver") //nolint:gosec cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} @@ -94,7 +94,7 @@ func (engine *ExifTool) Convert(ctx context.Context, logger *zap.Logger, formats } // ReadMetadata extracts the metadata of a given PDF file. -func (engine *ExifTool) ReadMetadata(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) { +func (engine *ExifTool) ReadMetadata(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]any, error) { exifTool, err := exiftool.NewExiftool(exiftool.SetExiftoolBinaryPath(engine.binPath)) if err != nil { return nil, fmt.Errorf("new ExifTool: %w", err) @@ -116,7 +116,7 @@ func (engine *ExifTool) ReadMetadata(ctx context.Context, logger *zap.Logger, in } // WriteMetadata writes the metadata into a given PDF file. -func (engine *ExifTool) WriteMetadata(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error { +func (engine *ExifTool) WriteMetadata(ctx context.Context, logger *zap.Logger, metadata map[string]any, inputPath string) error { exifTool, err := exiftool.NewExiftool(exiftool.SetExiftoolBinaryPath(engine.binPath)) if err != nil { return fmt.Errorf("new ExifTool: %w", err) @@ -167,7 +167,7 @@ func (engine *ExifTool) WriteMetadata(ctx context.Context, logger *zap.Logger, m fileMetadata[0].SetString(key, val) case []string: fileMetadata[0].SetStrings(key, val) - case []interface{}: + case []any: // See https://github.com/gotenberg/gotenberg/issues/1048. strs := make([]string, len(val)) for i, entry := range val { @@ -175,7 +175,7 @@ func (engine *ExifTool) WriteMetadata(ctx context.Context, logger *zap.Logger, m strs[i] = str continue } - return fmt.Errorf("write PDF metadata with ExifTool: %s %+v %s %w", key, val, reflect.TypeOf(val), gotenberg.ErrPdfEngineMetadataValueNotSupported) + return fmt.Errorf("write PDF metadata with ExifTool: %s %+v %s %w", key, val, reflect.TypeFor[[]interface{}](), gotenberg.ErrPdfEngineMetadataValueNotSupported) } fileMetadata[0].SetStrings(key, strs) case bool: diff --git a/pkg/modules/libreoffice/api/api.go b/pkg/modules/libreoffice/api/api.go index aeb6e1b..33b7106 100644 --- a/pkg/modules/libreoffice/api/api.go +++ b/pkg/modules/libreoffice/api/api.go @@ -316,8 +316,8 @@ func (a *Api) Stop(ctx context.Context) error { } // Debug returns additional debug data. -func (a *Api) Debug() map[string]interface{} { - debug := make(map[string]interface{}) +func (a *Api) Debug() map[string]any { + debug := make(map[string]any) cmd := exec.Command(a.args.binPath, "--version") //nolint:gosec cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} diff --git a/pkg/modules/libreoffice/pdfengine/pdfengine.go b/pkg/modules/libreoffice/pdfengine/pdfengine.go index e5a5c66..3fd828e 100644 --- a/pkg/modules/libreoffice/pdfengine/pdfengine.go +++ b/pkg/modules/libreoffice/pdfengine/pdfengine.go @@ -82,12 +82,12 @@ func (engine *LibreOfficePdfEngine) Convert(ctx context.Context, logger *zap.Log } // ReadMetadata is not available in this implementation. -func (engine *LibreOfficePdfEngine) ReadMetadata(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) { +func (engine *LibreOfficePdfEngine) ReadMetadata(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]any, error) { return nil, fmt.Errorf("read PDF metadata with LibreOffice: %w", gotenberg.ErrPdfEngineMethodNotSupported) } // WriteMetadata is not available in this implementation. -func (engine *LibreOfficePdfEngine) WriteMetadata(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error { +func (engine *LibreOfficePdfEngine) WriteMetadata(ctx context.Context, logger *zap.Logger, metadata map[string]any, inputPath string) error { return fmt.Errorf("write PDF metadata with LibreOffice: %w", gotenberg.ErrPdfEngineMethodNotSupported) } diff --git a/pkg/modules/pdfcpu/pdfcpu.go b/pkg/modules/pdfcpu/pdfcpu.go index 37f0d25..dff13aa 100644 --- a/pkg/modules/pdfcpu/pdfcpu.go +++ b/pkg/modules/pdfcpu/pdfcpu.go @@ -57,8 +57,8 @@ func (engine *PdfCpu) Validate() error { } // Debug returns additional debug data. -func (engine *PdfCpu) Debug() map[string]interface{} { - debug := make(map[string]interface{}) +func (engine *PdfCpu) Debug() map[string]any { + debug := make(map[string]any) cmd := exec.Command(engine.binPath, "version") //nolint:gosec cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} @@ -71,10 +71,10 @@ func (engine *PdfCpu) Debug() map[string]interface{} { debug["version"] = "Unable to determine pdfcpu version" - lines := strings.Split(string(output), "\n") - for _, line := range lines { - if strings.HasPrefix(line, "pdfcpu:") { - debug["version"] = strings.TrimSpace(strings.TrimPrefix(line, "pdfcpu:")) + lines := strings.SplitSeq(string(output), "\n") + for line := range lines { + if after, ok := strings.CutPrefix(line, "pdfcpu:"); ok { + debug["version"] = strings.TrimSpace(after) break } } @@ -162,12 +162,12 @@ func (engine *PdfCpu) Convert(ctx context.Context, logger *zap.Logger, formats g } // ReadMetadata is not available in this implementation. -func (engine *PdfCpu) ReadMetadata(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) { +func (engine *PdfCpu) ReadMetadata(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]any, error) { return nil, fmt.Errorf("read PDF metadata with pdfcpu: %w", gotenberg.ErrPdfEngineMethodNotSupported) } // WriteMetadata is not available in this implementation. -func (engine *PdfCpu) WriteMetadata(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error { +func (engine *PdfCpu) WriteMetadata(ctx context.Context, logger *zap.Logger, metadata map[string]any, inputPath string) error { return fmt.Errorf("write PDF metadata with pdfcpu: %w", gotenberg.ErrPdfEngineMethodNotSupported) } diff --git a/pkg/modules/pdfengines/multi.go b/pkg/modules/pdfengines/multi.go index 5726a2b..3ec176b 100644 --- a/pkg/modules/pdfengines/multi.go +++ b/pkg/modules/pdfengines/multi.go @@ -156,13 +156,13 @@ func (multi *multiPdfEngines) Convert(ctx context.Context, logger *zap.Logger, f } type readMetadataResult struct { - metadata map[string]interface{} + metadata map[string]any err error } // ReadMetadata extracts metadata from a PDF file using the first available // engine that supports metadata reading. -func (multi *multiPdfEngines) ReadMetadata(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) { +func (multi *multiPdfEngines) ReadMetadata(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]any, error) { var err error var mu sync.Mutex // to safely append errors. @@ -193,7 +193,7 @@ func (multi *multiPdfEngines) ReadMetadata(ctx context.Context, logger *zap.Logg // WriteMetadata embeds metadata into a PDF file using the first available // engine that supports metadata writing. -func (multi *multiPdfEngines) WriteMetadata(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error { +func (multi *multiPdfEngines) WriteMetadata(ctx context.Context, logger *zap.Logger, metadata map[string]any, inputPath string) error { var err error errChan := make(chan error, 1) diff --git a/pkg/modules/pdfengines/multi_test.go b/pkg/modules/pdfengines/multi_test.go index 496a440..61836ef 100644 --- a/pkg/modules/pdfengines/multi_test.go +++ b/pkg/modules/pdfengines/multi_test.go @@ -479,8 +479,8 @@ func TestMultiPdfEngines_ReadMetadata(t *testing.T) { engine: &multiPdfEngines{ readMetadataEngines: []gotenberg.PdfEngine{ &gotenberg.PdfEngineMock{ - ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) { - return make(map[string]interface{}), nil + ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]any, error) { + return make(map[string]any), nil }, }, }, @@ -492,13 +492,13 @@ func TestMultiPdfEngines_ReadMetadata(t *testing.T) { engine: &multiPdfEngines{ readMetadataEngines: []gotenberg.PdfEngine{ &gotenberg.PdfEngineMock{ - ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) { + ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]any, error) { return nil, errors.New("foo") }, }, &gotenberg.PdfEngineMock{ - ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) { - return make(map[string]interface{}), nil + ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]any, error) { + return make(map[string]any), nil }, }, }, @@ -510,12 +510,12 @@ func TestMultiPdfEngines_ReadMetadata(t *testing.T) { engine: &multiPdfEngines{ readMetadataEngines: []gotenberg.PdfEngine{ &gotenberg.PdfEngineMock{ - ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) { + ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]any, error) { return nil, errors.New("foo") }, }, &gotenberg.PdfEngineMock{ - ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) { + ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]any, error) { return nil, errors.New("foo") }, }, @@ -529,8 +529,8 @@ func TestMultiPdfEngines_ReadMetadata(t *testing.T) { engine: &multiPdfEngines{ readMetadataEngines: []gotenberg.PdfEngine{ &gotenberg.PdfEngineMock{ - ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) { - return make(map[string]interface{}), nil + ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]any, error) { + return make(map[string]any), nil }, }, }, @@ -570,7 +570,7 @@ func TestMultiPdfEngines_WriteMetadata(t *testing.T) { engine: &multiPdfEngines{ writeMetadataEngines: []gotenberg.PdfEngine{ &gotenberg.PdfEngineMock{ - WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error { + WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]any, inputPath string) error { return nil }, }, @@ -583,12 +583,12 @@ func TestMultiPdfEngines_WriteMetadata(t *testing.T) { engine: &multiPdfEngines{ writeMetadataEngines: []gotenberg.PdfEngine{ &gotenberg.PdfEngineMock{ - WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error { + WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]any, inputPath string) error { return errors.New("foo") }, }, &gotenberg.PdfEngineMock{ - WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error { + WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]any, inputPath string) error { return nil }, }, @@ -601,12 +601,12 @@ func TestMultiPdfEngines_WriteMetadata(t *testing.T) { engine: &multiPdfEngines{ writeMetadataEngines: []gotenberg.PdfEngine{ &gotenberg.PdfEngineMock{ - WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error { + WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]any, inputPath string) error { return errors.New("foo") }, }, &gotenberg.PdfEngineMock{ - WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error { + WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]any, inputPath string) error { return errors.New("foo") }, }, @@ -620,7 +620,7 @@ func TestMultiPdfEngines_WriteMetadata(t *testing.T) { engine: &multiPdfEngines{ writeMetadataEngines: []gotenberg.PdfEngine{ &gotenberg.PdfEngineMock{ - WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error { + WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]any, inputPath string) error { return nil }, }, diff --git a/pkg/modules/pdfengines/pdfengines.go b/pkg/modules/pdfengines/pdfengines.go index 6fd70ec..1070857 100644 --- a/pkg/modules/pdfengines/pdfengines.go +++ b/pkg/modules/pdfengines/pdfengines.go @@ -3,6 +3,7 @@ package pdfengines import ( "errors" "fmt" + "slices" "strings" flag "github.com/spf13/pflag" @@ -179,13 +180,7 @@ func (mod *PdfEngines) Validate() error { continue } - alreadyInSlice := false - for _, engine := range nonExistingEngines { - if engine == name { - alreadyInSlice = true - break - } - } + alreadyInSlice := slices.Contains(nonExistingEngines, name) if !alreadyInSlice { nonExistingEngines = append(nonExistingEngines, name) diff --git a/pkg/modules/pdfengines/routes.go b/pkg/modules/pdfengines/routes.go index 334678e..0da835e 100644 --- a/pkg/modules/pdfengines/routes.go +++ b/pkg/modules/pdfengines/routes.go @@ -102,8 +102,8 @@ func FormDataPdfFormats(form *api.FormData) gotenberg.PdfFormats { } // FormDataPdfMetadata creates metadata object from the form data. -func FormDataPdfMetadata(form *api.FormData, mandatory bool) map[string]interface{} { - var metadata map[string]interface{} +func FormDataPdfMetadata(form *api.FormData, mandatory bool) map[string]any { + var metadata map[string]any metadataFunc := func(value string) error { if len(value) > 0 { @@ -239,7 +239,7 @@ func ConvertStub(ctx *api.Context, engine gotenberg.PdfEngine, formats gotenberg // WriteMetadataStub writes the metadata into PDF files. If no metadata, it // does nothing. -func WriteMetadataStub(ctx *api.Context, engine gotenberg.PdfEngine, metadata map[string]interface{}, inputPaths []string) error { +func WriteMetadataStub(ctx *api.Context, engine gotenberg.PdfEngine, metadata map[string]any, inputPaths []string) error { if len(metadata) == 0 { return nil } @@ -558,7 +558,7 @@ func readMetadataRoute(engine gotenberg.PdfEngine) api.Route { return fmt.Errorf("validate form data: %w", err) } - res := make(map[string]map[string]interface{}, len(inputPaths)) + res := make(map[string]map[string]any, len(inputPaths)) for _, inputPath := range inputPaths { metadata, err := engine.ReadMetadata(ctx, ctx.Log(), inputPath) if err != nil { diff --git a/pkg/modules/pdftk/pdftk.go b/pkg/modules/pdftk/pdftk.go index f5c112b..68965f2 100644 --- a/pkg/modules/pdftk/pdftk.go +++ b/pkg/modules/pdftk/pdftk.go @@ -56,8 +56,8 @@ func (engine *PdfTk) Validate() error { } // Debug returns additional debug data. -func (engine *PdfTk) Debug() map[string]interface{} { - debug := make(map[string]interface{}) +func (engine *PdfTk) Debug() map[string]any { + debug := make(map[string]any) cmd := exec.Command(engine.binPath, "--version") //nolint:gosec cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} @@ -136,12 +136,12 @@ func (engine *PdfTk) Convert(ctx context.Context, logger *zap.Logger, formats go } // ReadMetadata is not available in this implementation. -func (engine *PdfTk) ReadMetadata(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) { +func (engine *PdfTk) ReadMetadata(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]any, error) { return nil, fmt.Errorf("read PDF metadata with PDFtk: %w", gotenberg.ErrPdfEngineMethodNotSupported) } // WriteMetadata is not available in this implementation. -func (engine *PdfTk) WriteMetadata(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error { +func (engine *PdfTk) WriteMetadata(ctx context.Context, logger *zap.Logger, metadata map[string]any, inputPath string) error { return fmt.Errorf("write PDF metadata with PDFtk: %w", gotenberg.ErrPdfEngineMethodNotSupported) } diff --git a/pkg/modules/qpdf/qpdf.go b/pkg/modules/qpdf/qpdf.go index c850798..64e0b61 100644 --- a/pkg/modules/qpdf/qpdf.go +++ b/pkg/modules/qpdf/qpdf.go @@ -59,8 +59,8 @@ func (engine *QPdf) Validate() error { } // Debug returns additional debug data. -func (engine *QPdf) Debug() map[string]interface{} { - debug := make(map[string]interface{}) +func (engine *QPdf) Debug() map[string]any { + debug := make(map[string]any) cmd := exec.Command(engine.binPath, "--version") //nolint:gosec cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} @@ -163,12 +163,12 @@ func (engine *QPdf) Convert(ctx context.Context, logger *zap.Logger, formats got } // ReadMetadata is not available in this implementation. -func (engine *QPdf) ReadMetadata(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) { +func (engine *QPdf) ReadMetadata(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]any, error) { return nil, fmt.Errorf("read PDF metadata with QPDF: %w", gotenberg.ErrPdfEngineMethodNotSupported) } // WriteMetadata is not available in this implementation. -func (engine *QPdf) WriteMetadata(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error { +func (engine *QPdf) WriteMetadata(ctx context.Context, logger *zap.Logger, metadata map[string]any, inputPath string) error { return fmt.Errorf("write PDF metadata with QPDF: %w", gotenberg.ErrPdfEngineMethodNotSupported) } diff --git a/test/integration/scenario/compare.go b/test/integration/scenario/compare.go index 5f61337..3236918 100644 --- a/test/integration/scenario/compare.go +++ b/test/integration/scenario/compare.go @@ -5,11 +5,11 @@ import ( "reflect" ) -func compareJson(expected, actual interface{}) error { +func compareJson(expected, actual any) error { // Handle maps (JSON objects). - expectedMap, ok := expected.(map[string]interface{}) + expectedMap, ok := expected.(map[string]any) if ok { - actualMap, ok := actual.(map[string]interface{}) + actualMap, ok := actual.(map[string]any) if !ok { return fmt.Errorf("expected an object, but actual is: %T", actual) } @@ -31,9 +31,9 @@ func compareJson(expected, actual interface{}) error { } // Handle slices (JSON arrays). - expectedSlice, ok := expected.([]interface{}) + expectedSlice, ok := expected.([]any) if ok { - actualSlice, ok := actual.([]interface{}) + actualSlice, ok := actual.([]any) if !ok { return fmt.Errorf("expected an array, but actual is: %T", actual) } diff --git a/test/integration/scenario/containers.go b/test/integration/scenario/containers.go index c4dc1a5..007eed9 100644 --- a/test/integration/scenario/containers.go +++ b/test/integration/scenario/containers.go @@ -22,7 +22,7 @@ var ( type noopLogger struct{} -func (n *noopLogger) Printf(format string, v ...interface{}) { +func (n *noopLogger) Printf(format string, v ...any) { // NOOP } diff --git a/test/integration/scenario/scenario.go b/test/integration/scenario/scenario.go index 0599bcf..2941326 100644 --- a/test/integration/scenario/scenario.go +++ b/test/integration/scenario/scenario.go @@ -327,11 +327,8 @@ func (s *scenario) iMakeConcurrentRequestsToGotenberg(ctx context.Context, count s.concurrentResps = make([]*httptest.ResponseRecorder, 0, count) errs := make([]error, 0) - for i := 0; i < count; i++ { - wg.Add(1) - go func() { - defer wg.Done() - + for range count { + wg.Go(func() { resp, reqErr := doFormDataRequest(method, fmt.Sprintf("%s%s", base, endpoint), fields, files, headers) if reqErr != nil { mu.Lock() @@ -387,7 +384,7 @@ func (s *scenario) iMakeConcurrentRequestsToGotenberg(ctx context.Context, count mu.Lock() s.concurrentResps = append(s.concurrentResps, rec) mu.Unlock() - }() + }) } wg.Wait() @@ -495,7 +492,7 @@ func (s *scenario) theGotenbergContainerShouldLogTheFollowingEntries(ctx context } var err error - for i := 0; i < 3; i++ { + for range 3 { err = check() if err != nil && !invert { // We have to retry as not all logs may have been produced. @@ -618,7 +615,7 @@ func (s *scenario) theBodyShouldMatchJSON(kind string, expectedDoc *godog.DocStr body = s.server.bodyCopy } - var expected, actual interface{} + var expected, actual any content := strings.ReplaceAll(expectedDoc.Content, "{version}", GotenbergVersion) err := json.Unmarshal([]byte(content), &expected)