mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-18 21:22:15 +01:00
docs(godoc): fix a bunch of typos
This commit is contained in:
@@ -51,4 +51,4 @@ Head to the [documentation](https://gotenberg.dev/docs/getting-started/introduct
|
|||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
Sponsorships help maintaining and improving Gotenberg - [become a sponsor](https://github.com/sponsors/gulien) ❤️
|
Sponsorships help maintain and improve Gotenberg - [become a sponsor](https://github.com/sponsors/gulien) ❤️
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Supported Versions
|
## Supported Versions
|
||||||
|
|
||||||
Please ensure to keep your environment up-to-date and use only the latest version of Gotenberg.
|
Please ensure to keep your environment up to date and use only the latest version of Gotenberg.
|
||||||
Security updates and patches will be applied only to the most recent version.
|
Security updates and patches will be applied only to the most recent version.
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ func (cmd *Cmd) Start() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wait waits for the command to complete. It should be called when using the
|
// Wait waits for the command to complete. It should be called when using the
|
||||||
// Start method, so that the command does not leak zombies.
|
// Start method so that the command does not leak zombies.
|
||||||
func (cmd *Cmd) Wait() error {
|
func (cmd *Cmd) Wait() error {
|
||||||
err := cmd.process.Wait()
|
err := cmd.process.Wait()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -84,7 +84,7 @@ func (cmd *Cmd) Wait() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec executes the command and wait for its completion or until the context
|
// Exec executes the command and waits for its completion or until the context
|
||||||
// is done. In any case, it kills the unix process and all its children.
|
// is done. In any case, it kills the unix process and all its children.
|
||||||
func (cmd *Cmd) Exec() (int, error) {
|
func (cmd *Cmd) Exec() (int, error) {
|
||||||
if cmd.ctx == nil {
|
if cmd.ctx == nil {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Context is a struct which helps to initialize modules. When provisioning, a
|
// Context is a struct that helps to initialize modules. When provisioning, a
|
||||||
// module may use the context to get other modules that it needs internally.
|
// module may use the context to get other modules that it needs internally.
|
||||||
type Context struct {
|
type Context struct {
|
||||||
flags ParsedFlags
|
flags ParsedFlags
|
||||||
@@ -58,7 +58,7 @@ func (ctx *Context) Module(kind interface{}) (interface{}, error) {
|
|||||||
return mods[0], nil
|
return mods[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modules returns the list of modules which satisfies the requested interface.
|
// Modules return the list of modules which satisfies the requested interface.
|
||||||
//
|
//
|
||||||
// func (m *YourModule) Provision(ctx *gotenberg.Context) error {
|
// func (m *YourModule) Provision(ctx *gotenberg.Context) error {
|
||||||
// mods, _ := ctx.Modules(new(ModuleInterface))
|
// mods, _ := ctx.Modules(new(ModuleInterface))
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ func (o *OsMkdirAll) MkdirAll(path string, perm os.FileMode) error { return os.M
|
|||||||
|
|
||||||
// PathRename defines the method signature for renaming files. Implement this
|
// PathRename defines the method signature for renaming files. Implement this
|
||||||
// interface if you don't want to rely on [os.Rename], notably for testing
|
// interface if you don't want to rely on [os.Rename], notably for testing
|
||||||
// purpose.
|
// purposes.
|
||||||
type PathRename interface {
|
type PathRename interface {
|
||||||
// Rename uses the same signature as [os.Rename].
|
// Rename uses the same signature as [os.Rename].
|
||||||
Rename(oldpath, newpath string) error
|
Rename(oldpath, newpath string) error
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// GarbageCollect scans the root path and deletes files or directories with
|
// GarbageCollect scans the root path and deletes files or directories with
|
||||||
// names containing specific substrings and before a given experiation time.
|
// names containing specific substrings and before a given expiration time.
|
||||||
func GarbageCollect(logger *zap.Logger, rootPath string, includeSubstr []string, expirationTime time.Time) error {
|
func GarbageCollect(logger *zap.Logger, rootPath string, includeSubstr []string, expirationTime time.Time) error {
|
||||||
logger = logger.Named("gc")
|
logger = logger.Named("gc")
|
||||||
|
|
||||||
|
|||||||
@@ -28,29 +28,29 @@ func TestGarbageCollect(t *testing.T) {
|
|||||||
{
|
{
|
||||||
scenario: "remove include substrings",
|
scenario: "remove include substrings",
|
||||||
rootPath: func() string {
|
rootPath: func() string {
|
||||||
path := fmt.Sprintf("%s/a_directory", os.TempDir())
|
p := fmt.Sprintf("%s/a_directory", os.TempDir())
|
||||||
|
|
||||||
err := os.MkdirAll(path, 0o755)
|
err := os.MkdirAll(p, 0o755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("expected no error but got: %v", err)
|
t.Fatalf("expected no error but got: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = os.WriteFile(fmt.Sprintf("%s/a_foo_file", path), []byte{1}, 0o755)
|
err = os.WriteFile(fmt.Sprintf("%s/a_foo_file", p), []byte{1}, 0o755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("expected no error but got: %v", err)
|
t.Fatalf("expected no error but got: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = os.WriteFile(fmt.Sprintf("%s/a_bar_file", path), []byte{1}, 0o755)
|
err = os.WriteFile(fmt.Sprintf("%s/a_bar_file", p), []byte{1}, 0o755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("expected no error but got: %v", err)
|
t.Fatalf("expected no error but got: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = os.WriteFile(fmt.Sprintf("%s/a_baz_file", path), []byte{1}, 0o755)
|
err = os.WriteFile(fmt.Sprintf("%s/a_baz_file", p), []byte{1}, 0o755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("expected no error but got: %v", err)
|
t.Fatalf("expected no error but got: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return path
|
return p
|
||||||
}(),
|
}(),
|
||||||
includeSubstr: []string{"foo", path.Join(os.TempDir(), "/a_directory/a_bar_file")},
|
includeSubstr: []string{"foo", path.Join(os.TempDir(), "/a_directory/a_bar_file")},
|
||||||
expectError: false,
|
expectError: false,
|
||||||
@@ -81,18 +81,18 @@ func TestGarbageCollect(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, name := range tc.expectNotExists {
|
for _, name := range tc.expectNotExists {
|
||||||
path := fmt.Sprintf("%s/%s", tc.rootPath, name)
|
p := fmt.Sprintf("%s/%s", tc.rootPath, name)
|
||||||
_, err = os.Stat(path)
|
_, err = os.Stat(p)
|
||||||
if !os.IsNotExist(err) {
|
if !os.IsNotExist(err) {
|
||||||
t.Errorf("expected '%s' not to exist but it does: %v", path, err)
|
t.Errorf("expected '%s' not to exist but it does: %v", p, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, name := range tc.expectExists {
|
for _, name := range tc.expectExists {
|
||||||
path := fmt.Sprintf("%s/%s", tc.rootPath, name)
|
p := fmt.Sprintf("%s/%s", tc.rootPath, name)
|
||||||
_, err = os.Stat(path)
|
_, err = os.Stat(p)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
t.Errorf("expected '%s' to exist but it does not: %v", path, err)
|
t.Errorf("expected '%s' to exist but it does not: %v", p, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ type LoggerProvider interface {
|
|||||||
Logger(mod Module) (*zap.Logger, error)
|
Logger(mod Module) (*zap.Logger, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LeveledLogger is wrapper around a [zap.Logger] so that it may be used by a
|
// LeveledLogger is a wrapper around a [zap.Logger] so that it may be used by a
|
||||||
// [retryablehttp.Client].
|
// [retryablehttp.Client].
|
||||||
type LeveledLogger struct {
|
type LeveledLogger struct {
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
@@ -31,22 +31,22 @@ func NewLeveledLogger(logger *zap.Logger) *LeveledLogger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error logs a message at error level using the wrapped zap.Logger.
|
// 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 ...interface{}) {
|
||||||
leveled.logger.Error(fmt.Sprintf("%s: %+v", msg, keysAndValues))
|
leveled.logger.Error(fmt.Sprintf("%s: %+v", msg, keysAndValues))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warn logs a message at warning level using the wrapped zap.Logger.
|
// 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 ...interface{}) {
|
||||||
leveled.logger.Warn(fmt.Sprintf("%s: %+v", msg, keysAndValues))
|
leveled.logger.Warn(fmt.Sprintf("%s: %+v", msg, keysAndValues))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info logs a message at info level using the wrapped zap.Logger.
|
// 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 ...interface{}) {
|
||||||
leveled.logger.Info(fmt.Sprintf("%s: %+v", msg, keysAndValues))
|
leveled.logger.Info(fmt.Sprintf("%s: %+v", msg, keysAndValues))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug logs a message at debug level using the wrapped zap.Logger.
|
// 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 ...interface{}) {
|
||||||
leveled.logger.Debug(fmt.Sprintf("%s: %+v", msg, keysAndValues))
|
leveled.logger.Debug(fmt.Sprintf("%s: %+v", msg, keysAndValues))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ var (
|
|||||||
ErrPdfEngineMethodNotSupported = errors.New("method not supported")
|
ErrPdfEngineMethodNotSupported = errors.New("method not supported")
|
||||||
|
|
||||||
// ErrPdfSplitModeNotSupported is returned when the Split method of the
|
// ErrPdfSplitModeNotSupported is returned when the Split method of the
|
||||||
// PdfEngine interface does not sumport a requested PDF split mode.
|
// PdfEngine interface does not support a requested PDF split mode.
|
||||||
ErrPdfSplitModeNotSupported = errors.New("split mode not supported")
|
ErrPdfSplitModeNotSupported = errors.New("split mode not supported")
|
||||||
|
|
||||||
// ErrPdfFormatNotSupported is returned when the Convert method of the
|
// ErrPdfFormatNotSupported is returned when the Convert method of the
|
||||||
@@ -86,7 +86,7 @@ type PdfFormats struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PdfEngine provides an interface for operations on PDFs. Implementations
|
// PdfEngine provides an interface for operations on PDFs. Implementations
|
||||||
// can utilize various tools like PDFtk, or implement functionality directly in
|
// can use various tools like PDFtk, or implement functionality directly in
|
||||||
// Go.
|
// Go.
|
||||||
//
|
//
|
||||||
//nolint:dupl
|
//nolint:dupl
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ func init() {
|
|||||||
gotenberg.MustRegisterModule(new(Api))
|
gotenberg.MustRegisterModule(new(Api))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Api is a module which provides an HTTP server. Other modules may add routes,
|
// Api is a module that provides an HTTP server. Other modules may add routes,
|
||||||
// middlewares or health checks.
|
// middlewares or health checks.
|
||||||
type Api struct {
|
type Api struct {
|
||||||
port int
|
port int
|
||||||
@@ -60,7 +60,7 @@ type downloadFromConfig struct {
|
|||||||
disable bool
|
disable bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Router is a module interface which adds routes to the [Api].
|
// Router is a module interface that adds routes to the [Api].
|
||||||
type Router interface {
|
type Router interface {
|
||||||
Routes() ([]Route, error)
|
Routes() ([]Route, error)
|
||||||
}
|
}
|
||||||
@@ -83,17 +83,17 @@ type Route struct {
|
|||||||
// Optional.
|
// Optional.
|
||||||
DisableLogging bool
|
DisableLogging bool
|
||||||
|
|
||||||
// Handler is the function which handles the request.
|
// Handler is the function that handles the request.
|
||||||
// Required.
|
// Required.
|
||||||
Handler echo.HandlerFunc
|
Handler echo.HandlerFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
// MiddlewareProvider is a module interface which adds middlewares to the [Api].
|
// MiddlewareProvider is a module interface that adds middlewares to the [Api].
|
||||||
type MiddlewareProvider interface {
|
type MiddlewareProvider interface {
|
||||||
Middlewares() ([]Middleware, error)
|
Middlewares() ([]Middleware, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MiddlewareStack is a type which helps to determine in which stack the
|
// MiddlewareStack is a type that helps to determine in which stack the
|
||||||
// middlewares provided by the [MiddlewareProvider] modules should be located.
|
// middlewares provided by the [MiddlewareProvider] modules should be located.
|
||||||
type MiddlewareStack uint32
|
type MiddlewareStack uint32
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ const (
|
|||||||
MultipartStack
|
MultipartStack
|
||||||
)
|
)
|
||||||
|
|
||||||
// MiddlewarePriority is a type which helps to determine the execution order of
|
// MiddlewarePriority is a type that helps to determine the execution order of
|
||||||
// middlewares provided by the [MiddlewareProvider] modules in a stack.
|
// middlewares provided by the [MiddlewareProvider] modules in a stack.
|
||||||
type MiddlewarePriority uint32
|
type MiddlewarePriority uint32
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ const (
|
|||||||
VeryHighPriority
|
VeryHighPriority
|
||||||
)
|
)
|
||||||
|
|
||||||
// Middleware is a middleware which can be added to the [Api]'s middlewares
|
// Middleware is a middleware that can be added to the [Api]'s middlewares
|
||||||
// chain.
|
// chain.
|
||||||
//
|
//
|
||||||
// middleware := Middleware{
|
// middleware := Middleware{
|
||||||
@@ -157,7 +157,7 @@ type Middleware struct {
|
|||||||
Handler echo.MiddlewareFunc
|
Handler echo.MiddlewareFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
// HealthChecker is a module interface which allows adding health checks to the
|
// HealthChecker is a module interface that allows adding health checks to the
|
||||||
// API.
|
// API.
|
||||||
//
|
//
|
||||||
// See https://github.com/alexliesenfeld/health for more details.
|
// See https://github.com/alexliesenfeld/health for more details.
|
||||||
@@ -431,7 +431,7 @@ func (a *Api) Start() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the user wish to add logging entries related to the health
|
// Check if the user wishes to add logging entries related to the health
|
||||||
// check route.
|
// check route.
|
||||||
if a.disableHealthCheckLogging {
|
if a.disableHealthCheckLogging {
|
||||||
disableLoggingForPaths = append(disableLoggingForPaths, "health")
|
disableLoggingForPaths = append(disableLoggingForPaths, "health")
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
// Package api provides a module which is an HTTP server. Other modules may
|
// Package api provides a module, which is an HTTP server. Other modules may
|
||||||
// add multipart/form-data routes, middlewares, and health checks.
|
// add multipart/form-data routes, middlewares, and health checks.
|
||||||
package api
|
package api
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ type FormData struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate returns nil or an error related to the [FormData] values, with a
|
// Validate returns nil or an error related to the [FormData] values, with a
|
||||||
// [SentinelHttpError] (status code 400, errors' details as message) wrapped
|
// [SentinelHttpError] (status code 400, errors' details as a message) wrapped
|
||||||
// inside.
|
// inside.
|
||||||
//
|
//
|
||||||
// var foo string
|
// var foo string
|
||||||
@@ -96,7 +96,7 @@ func (form *FormData) Int(key string, target *int, defaultValue int) *FormData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MandatoryInt binds a form field to an int variable. It populates an
|
// MandatoryInt binds a form field to an int variable. It populates an
|
||||||
// error if the value is not int, is empty, or the "key" does not exist.
|
// error if the value is not int, or is empty, or the "key" does not exist.
|
||||||
//
|
//
|
||||||
// var foo int
|
// var foo int
|
||||||
//
|
//
|
||||||
@@ -116,7 +116,7 @@ func (form *FormData) Float64(key string, target *float64, defaultValue float64)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MandatoryFloat64 binds a form field to a float64 variable. It populates
|
// MandatoryFloat64 binds a form field to a float64 variable. It populates
|
||||||
// an error if the is not float64, is empty, or the "key" does not exist.
|
// an error if the value is not float64, is empty, or the "key" does not exist.
|
||||||
//
|
//
|
||||||
// var foo float64
|
// var foo float64
|
||||||
//
|
//
|
||||||
@@ -136,8 +136,8 @@ func (form *FormData) Duration(key string, target *time.Duration, defaultValue t
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MandatoryDuration binds a form field to a time.Duration variable. It
|
// MandatoryDuration binds a form field to a time.Duration variable. It
|
||||||
// populates an error if the value is not time.Duration, is empty, or the "key"
|
// populates an error if the value is not time.Duration, or is empty, or the
|
||||||
// does not exist.
|
// "key" does not exist.
|
||||||
//
|
//
|
||||||
// var foo time.Duration
|
// var foo time.Duration
|
||||||
//
|
//
|
||||||
@@ -146,7 +146,7 @@ func (form *FormData) MandatoryDuration(key string, target *time.Duration) *Form
|
|||||||
return form.mustMandatoryField(key, target)
|
return form.mustMandatoryField(key, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inches binds a form field to a float64 variable. It populates an error
|
// Inches bind a form field to a float64 variable. It populates an error
|
||||||
// if the value cannot be computed back to inches.
|
// if the value cannot be computed back to inches.
|
||||||
//
|
//
|
||||||
// var foo float64
|
// var foo float64
|
||||||
@@ -303,7 +303,7 @@ func (form *FormData) Path(filename string, target *string) *FormData {
|
|||||||
return form.path(filename, target)
|
return form.path(filename, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MandatoryPath binds the absolute path ofa form data file to a string
|
// MandatoryPath binds the absolute path of a form data file to a string
|
||||||
// variable. It populates an error if the file does not exist.
|
// variable. It populates an error if the file does not exist.
|
||||||
//
|
//
|
||||||
// var path string
|
// var path string
|
||||||
@@ -348,7 +348,7 @@ func (form *FormData) MandatoryContent(filename string, target *string) *FormDat
|
|||||||
return form.readFile(path, filename, target)
|
return form.readFile(path, filename, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Paths binds the absolute paths of form data files, according to a list of
|
// Paths bind the absolute paths of form data files, according to a list of
|
||||||
// file extensions, to a string slice variable.
|
// file extensions, to a string slice variable.
|
||||||
//
|
//
|
||||||
// var paths []string
|
// var paths []string
|
||||||
@@ -379,7 +379,7 @@ func (form *FormData) MandatoryPaths(extensions []string, target *[]string) *For
|
|||||||
return form
|
return form
|
||||||
}
|
}
|
||||||
|
|
||||||
// paths binds the absolute paths of form data files, according to a list of
|
// paths bind the absolute paths of form data files, according to a list of
|
||||||
// file extensions, to a string slice variable.
|
// file extensions, to a string slice variable.
|
||||||
func (form *FormData) paths(extensions []string, target *[]string) *FormData {
|
func (form *FormData) paths(extensions []string, target *[]string) *FormData {
|
||||||
for filename, path := range form.files {
|
for filename, path := range form.files {
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ func httpErrorHandler() echo.HTTPErrorHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// latencyMiddleware sets the start time in the [echo.Context] under
|
// latencyMiddleware sets the start time in the [echo.Context] under
|
||||||
// "startTime". Its value will be used later to calculate a request latency.
|
// "startTime". Its value will be used later to calculate request latency.
|
||||||
//
|
//
|
||||||
// startTime := c.Get("startTime").(time.Time)
|
// startTime := c.Get("startTime").(time.Time)
|
||||||
func latencyMiddleware() echo.MiddlewareFunc {
|
func latencyMiddleware() echo.MiddlewareFunc {
|
||||||
@@ -109,7 +109,7 @@ func latencyMiddleware() echo.MiddlewareFunc {
|
|||||||
// rootPath := c.Get("rootPath").(string)
|
// rootPath := c.Get("rootPath").(string)
|
||||||
// healthURI := fmt.Sprintf("%s/health", rootPath)
|
// healthURI := fmt.Sprintf("%s/health", rootPath)
|
||||||
//
|
//
|
||||||
// // Skip the middleware if health check URI.
|
// // Skip the middleware if it's the health check URI.
|
||||||
// if c.Request().RequestURI == healthURI {
|
// if c.Request().RequestURI == healthURI {
|
||||||
// // Call the next middleware in the chain.
|
// // Call the next middleware in the chain.
|
||||||
// return next(c)
|
// return next(c)
|
||||||
@@ -241,7 +241,7 @@ func basicAuthMiddleware(username, password string) echo.MiddlewareFunc {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// contextMiddleware, a middleware for "multipart/form-data" requests, sets the
|
// contextMiddleware, middleware for "multipart/form-data" requests, sets the
|
||||||
// [Context] and related context.CancelFunc in the [echo.Context] under
|
// [Context] and related context.CancelFunc in the [echo.Context] under
|
||||||
// "context" and "cancel". If the process is synchronous, it also handles the
|
// "context" and "cancel". If the process is synchronous, it also handles the
|
||||||
// result of a "multipart/form-data" request.
|
// result of a "multipart/form-data" request.
|
||||||
@@ -256,7 +256,7 @@ func contextMiddleware(fs *gotenberg.FileSystem, timeout time.Duration, bodyLimi
|
|||||||
trace := c.Get("trace").(string)
|
trace := c.Get("trace").(string)
|
||||||
|
|
||||||
// We create a context with a timeout so that underlying processes are
|
// We create a context with a timeout so that underlying processes are
|
||||||
// able to stop early and handle correctly a timeout scenario.
|
// able to stop early and correctly handle a timeout scenario.
|
||||||
ctx, cancel, err := newContext(c, logger, fs, timeout, bodyLimit, downloadFromCfg, traceHeader, trace)
|
ctx, cancel, err := newContext(c, logger, fs, timeout, bodyLimit, downloadFromCfg, traceHeader, trace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cancel()
|
cancel()
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ func (ctx *ContextMock) SetFiles(files map[string]string) {
|
|||||||
ctx.files = files
|
ctx.files = files
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCancelled sets if the context is cancelled or not.
|
// SetCancelled sets if the context is canceled or not.
|
||||||
//
|
//
|
||||||
// ctx := &api.ContextMock{Context: &api.Context{}}
|
// ctx := &api.ContextMock{Context: &api.Context{}}
|
||||||
// ctx.SetCancelled(true)
|
// ctx.SetCancelled(true)
|
||||||
@@ -120,7 +120,7 @@ func (provider *MiddlewareProviderMock) Middlewares() ([]Middleware, error) {
|
|||||||
return provider.MiddlewaresMock()
|
return provider.MiddlewaresMock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// HealthCheckerMock is mock for the [HealthChecker] interface.
|
// HealthCheckerMock is a mock for the [HealthChecker] interface.
|
||||||
type HealthCheckerMock struct {
|
type HealthCheckerMock struct {
|
||||||
ChecksMock func() ([]health.CheckerOption, error)
|
ChecksMock func() ([]health.CheckerOption, error)
|
||||||
ReadyMock func() error
|
ReadyMock func() error
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ func (b *chromiumBrowser) Stop(logger *zap.Logger) error {
|
|||||||
logger.Debug(fmt.Sprintf("'%s' Chromium's user profile directory removed", userProfileDirPath))
|
logger.Debug(fmt.Sprintf("'%s' Chromium's user profile directory removed", userProfileDirPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also remove Chromium specific files in the temporary directory.
|
// Also, remove Chromium-specific files in the temporary directory.
|
||||||
err = gotenberg.GarbageCollect(logger, os.TempDir(), []string{".org.chromium.Chromium", ".com.google.Chrome"}, expirationTime)
|
err = gotenberg.GarbageCollect(logger, os.TempDir(), []string{".org.chromium.Chromium", ".com.google.Chrome"}, expirationTime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err.Error())
|
logger.Error(err.Error())
|
||||||
@@ -314,7 +314,7 @@ func (b *chromiumBrowser) do(ctx context.Context, logger *zap.Logger, url string
|
|||||||
return errors.New("context has no deadline")
|
return errors.New("context has no deadline")
|
||||||
}
|
}
|
||||||
|
|
||||||
// We validate the "main" URL against our allow / deny lists.
|
// We validate the "main" URL against our allowed / deny lists.
|
||||||
err := gotenberg.FilterDeadline(b.arguments.allowList, b.arguments.denyList, url, deadline)
|
err := gotenberg.FilterDeadline(b.arguments.allowList, b.arguments.denyList, url, deadline)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("filter URL: %w", err)
|
return fmt.Errorf("filter URL: %w", err)
|
||||||
@@ -329,7 +329,7 @@ func (b *chromiumBrowser) do(ctx context.Context, logger *zap.Logger, url string
|
|||||||
taskCtx, taskCancel := chromedp.NewContext(timeoutCtx)
|
taskCtx, taskCancel := chromedp.NewContext(timeoutCtx)
|
||||||
defer taskCancel()
|
defer taskCancel()
|
||||||
|
|
||||||
// We validate all others requests against our allow / deny lists.
|
// We validate all other requests against our allowed / deny lists.
|
||||||
// If a request does not pass the validation, we make it fail. It also set
|
// If a request does not pass the validation, we make it fail. It also set
|
||||||
// the extra HTTP headers, if any.
|
// the extra HTTP headers, if any.
|
||||||
// See https://github.com/gotenberg/gotenberg/issues/1011.
|
// See https://github.com/gotenberg/gotenberg/issues/1011.
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ func init() {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrInvalidEmulatedMediaType happens if the emulated media type is not
|
// ErrInvalidEmulatedMediaType happens if the emulated media type is not
|
||||||
// "screen" nor "print". Empty value are allowed though.
|
// "screen" nor "print". Empty value is allowed, though.
|
||||||
ErrInvalidEmulatedMediaType = errors.New("invalid emulated media type")
|
ErrInvalidEmulatedMediaType = errors.New("invalid emulated media type")
|
||||||
|
|
||||||
// ErrInvalidEvaluationExpression happens if an evaluation expression
|
// ErrInvalidEvaluationExpression happens if an evaluation expression
|
||||||
@@ -38,11 +38,11 @@ var (
|
|||||||
ErrRpccMessageTooLarge = errors.New("rpcc message too large")
|
ErrRpccMessageTooLarge = errors.New("rpcc message too large")
|
||||||
|
|
||||||
// ErrInvalidHttpStatusCode happens when the status code from the main page
|
// ErrInvalidHttpStatusCode happens when the status code from the main page
|
||||||
// matches with one of the entry in [Options.FailOnHttpStatusCodes].
|
// matches with one of the entries in [Options.FailOnHttpStatusCodes].
|
||||||
ErrInvalidHttpStatusCode = errors.New("invalid HTTP status code")
|
ErrInvalidHttpStatusCode = errors.New("invalid HTTP status code")
|
||||||
|
|
||||||
// ErrInvalidResourceHttpStatusCode happens when the status code from one
|
// ErrInvalidResourceHttpStatusCode happens when the status code from one
|
||||||
// or more resources matches with one of the entry in
|
// or more resources matches with one of the entries in
|
||||||
// [Options.FailOnResourceHttpStatusCodes].
|
// [Options.FailOnResourceHttpStatusCodes].
|
||||||
ErrInvalidResourceHttpStatusCode = errors.New("invalid resource HTTP status code")
|
ErrInvalidResourceHttpStatusCode = errors.New("invalid resource HTTP status code")
|
||||||
|
|
||||||
@@ -68,11 +68,11 @@ var (
|
|||||||
ErrInvalidPrinterSettings = errors.New("invalid printer settings")
|
ErrInvalidPrinterSettings = errors.New("invalid printer settings")
|
||||||
|
|
||||||
// ErrPageRangesSyntaxError happens if the PdfOptions have an invalid page
|
// ErrPageRangesSyntaxError happens if the PdfOptions have an invalid page
|
||||||
// ranges.
|
// range.
|
||||||
ErrPageRangesSyntaxError = errors.New("page ranges syntax error")
|
ErrPageRangesSyntaxError = errors.New("page ranges syntax error")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Chromium is a module which provides both an [Api] and routes for converting
|
// Chromium is a module that provides both an [Api] and routes for converting
|
||||||
// HTML document to PDF.
|
// HTML document to PDF.
|
||||||
type Chromium struct {
|
type Chromium struct {
|
||||||
autoStart bool
|
autoStart bool
|
||||||
@@ -128,15 +128,15 @@ type Options struct {
|
|||||||
UserAgent string
|
UserAgent string
|
||||||
|
|
||||||
// ExtraHttpHeaders are extra HTTP headers to send by Chromium while
|
// ExtraHttpHeaders are extra HTTP headers to send by Chromium while
|
||||||
// loading he HTML document.
|
// loading the HTML document.
|
||||||
ExtraHttpHeaders []ExtraHttpHeader
|
ExtraHttpHeaders []ExtraHttpHeader
|
||||||
|
|
||||||
// EmulatedMediaType is the media type to emulate, either "screen" or
|
// EmulatedMediaType is the media type to emulate, either "screen" or
|
||||||
// "print".
|
// "print".
|
||||||
EmulatedMediaType string
|
EmulatedMediaType string
|
||||||
|
|
||||||
// OmitBackground hides default white background and allows generating PDFs
|
// OmitBackground hides the default white background and allows generating
|
||||||
// with transparency.
|
// PDFs with transparency.
|
||||||
OmitBackground bool
|
OmitBackground bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,9 +197,9 @@ type PdfOptions struct {
|
|||||||
// Page ranges to print, e.g., '1-5, 8, 11-13'. Empty means all pages.
|
// Page ranges to print, e.g., '1-5, 8, 11-13'. Empty means all pages.
|
||||||
PageRanges string
|
PageRanges string
|
||||||
|
|
||||||
// HeaderTemplate is the HTML template of the header. It should be valid
|
// HeaderTemplate is the HTML template of the header. It should be a valid
|
||||||
// HTML markup with following classes used to inject printing values into
|
// HTML markup with the following classes used to inject printing values
|
||||||
// them:
|
// into them:
|
||||||
// - date: formatted print date
|
// - date: formatted print date
|
||||||
// - title: document title
|
// - title: document title
|
||||||
// - url: document location
|
// - url: document location
|
||||||
@@ -338,7 +338,7 @@ type Api interface {
|
|||||||
Screenshot(ctx context.Context, logger *zap.Logger, url, outputPath string, options ScreenshotOptions) error
|
Screenshot(ctx context.Context, logger *zap.Logger, url, outputPath string, options ScreenshotOptions) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provider is a module interface which exposes a method for creating an [Api]
|
// Provider is a module interface that exposes a method for creating an [Api]
|
||||||
// for other modules.
|
// for other modules.
|
||||||
//
|
//
|
||||||
// func (m *YourModule) Provision(ctx *gotenberg.Context) error {
|
// func (m *YourModule) Provision(ctx *gotenberg.Context) error {
|
||||||
@@ -473,8 +473,8 @@ func (mod *Chromium) StartupMessage() string {
|
|||||||
|
|
||||||
// Stop stops the current browser instance.
|
// Stop stops the current browser instance.
|
||||||
func (mod *Chromium) Stop(ctx context.Context) error {
|
func (mod *Chromium) Stop(ctx context.Context) error {
|
||||||
// Block until the context is done so that other module may gracefully stop
|
// Block until the context is done so that another module may gracefully
|
||||||
// before we do a shutdown.
|
// stop before we do a shutdown.
|
||||||
mod.logger.Debug("wait for the end of grace duration")
|
mod.logger.Debug("wait for the end of grace duration")
|
||||||
|
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
|
|||||||
@@ -72,10 +72,10 @@ func listenForEventRequestPaused(ctx context.Context, logger *zap.Logger, option
|
|||||||
|
|
||||||
var extraHttpHeadersToSet []ExtraHttpHeader
|
var extraHttpHeadersToSet []ExtraHttpHeader
|
||||||
if len(options.extraHttpHeaders) > 0 {
|
if len(options.extraHttpHeaders) > 0 {
|
||||||
// The user want to set extra HTTP headers.
|
// The user wants to set extra HTTP headers.
|
||||||
|
|
||||||
// First, we have to check if at least one header has to be
|
// First, we have to check if at least one header has to be
|
||||||
// set for current request.
|
// set for the current request.
|
||||||
for _, header := range options.extraHttpHeaders {
|
for _, header := range options.extraHttpHeaders {
|
||||||
if header.Scope == nil {
|
if header.Scope == nil {
|
||||||
// Non-scoped header.
|
// Non-scoped header.
|
||||||
@@ -147,8 +147,8 @@ type eventResponseReceivedOptions struct {
|
|||||||
invalidResourceHttpStatusCodeMu *sync.RWMutex
|
invalidResourceHttpStatusCodeMu *sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// listenForEventResponseReceived listens for an invalid HTTP status code that
|
// listenForEventResponseReceived listens for an invalid HTTP status code
|
||||||
// is returned by the main page or by one or more resources.
|
// returned by the main page or by one or more resources.
|
||||||
// See:
|
// See:
|
||||||
// https://github.com/gotenberg/gotenberg/issues/613.
|
// https://github.com/gotenberg/gotenberg/issues/613.
|
||||||
// https://github.com/gotenberg/gotenberg/issues/1021.
|
// https://github.com/gotenberg/gotenberg/issues/1021.
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// FormDataChromiumOptions creates [Options] from the form data. Fallback to
|
// FormDataChromiumOptions creates [Options] from the form data. Fallback to
|
||||||
// default value if the considered key is not present.
|
// the default value if the considered key is not present.
|
||||||
func FormDataChromiumOptions(ctx *api.Context) (*api.FormData, Options) {
|
func FormDataChromiumOptions(ctx *api.Context) (*api.FormData, Options) {
|
||||||
defaultOptions := DefaultOptions()
|
defaultOptions := DefaultOptions()
|
||||||
|
|
||||||
@@ -194,7 +194,7 @@ func FormDataChromiumOptions(ctx *api.Context) (*api.FormData, Options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FormDataChromiumPdfOptions creates [PdfOptions] from the form data. Fallback to
|
// FormDataChromiumPdfOptions creates [PdfOptions] from the form data. Fallback to
|
||||||
// default value if the considered key is not present.
|
// the default value if the considered key is not present.
|
||||||
func FormDataChromiumPdfOptions(ctx *api.Context) (*api.FormData, PdfOptions) {
|
func FormDataChromiumPdfOptions(ctx *api.Context) (*api.FormData, PdfOptions) {
|
||||||
form, options := FormDataChromiumOptions(ctx)
|
form, options := FormDataChromiumOptions(ctx)
|
||||||
defaultPdfOptions := DefaultPdfOptions()
|
defaultPdfOptions := DefaultPdfOptions()
|
||||||
@@ -249,7 +249,7 @@ func FormDataChromiumPdfOptions(ctx *api.Context) (*api.FormData, PdfOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FormDataChromiumScreenshotOptions creates [ScreenshotOptions] from the form
|
// FormDataChromiumScreenshotOptions creates [ScreenshotOptions] from the form
|
||||||
// data. Fallback to default value if the considered key is not present.
|
// data. Fallback to the default value if the considered key is not present.
|
||||||
func FormDataChromiumScreenshotOptions(ctx *api.Context) (*api.FormData, ScreenshotOptions) {
|
func FormDataChromiumScreenshotOptions(ctx *api.Context) (*api.FormData, ScreenshotOptions) {
|
||||||
form, options := FormDataChromiumOptions(ctx)
|
form, options := FormDataChromiumOptions(ctx)
|
||||||
defaultScreenshotOptions := DefaultScreenshotOptions()
|
defaultScreenshotOptions := DefaultScreenshotOptions()
|
||||||
@@ -483,7 +483,7 @@ func convertMarkdownRoute(chromium Api, engine gotenberg.PdfEngine) api.Route {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// screenshotMarkdownRoute returns an [api.Route] which can take a screenshot
|
// screenshotMarkdownRoute returns an [api.Route] which can take a screenshot
|
||||||
// from markdown files.
|
// from Markdown files.
|
||||||
func screenshotMarkdownRoute(chromium Api) api.Route {
|
func screenshotMarkdownRoute(chromium Api) api.Route {
|
||||||
return api.Route{
|
return api.Route{
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
@@ -522,7 +522,7 @@ func screenshotMarkdownRoute(chromium Api) api.Route {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func markdownToHtml(ctx *api.Context, inputPath string, markdownPaths []string) (string, error) {
|
func markdownToHtml(ctx *api.Context, inputPath string, markdownPaths []string) (string, error) {
|
||||||
// We have to convert each markdown file referenced in the HTML
|
// We have to convert each Markdown file referenced in the HTML
|
||||||
// file to... HTML. Thanks to the "html/template" package, we are
|
// file to... HTML. Thanks to the "html/template" package, we are
|
||||||
// able to provide the "toHTML" function which the user may call
|
// able to provide the "toHTML" function which the user may call
|
||||||
// directly inside the HTML file.
|
// directly inside the HTML file.
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ type streamReader struct {
|
|||||||
// Read a chunk of the stream.
|
// Read a chunk of the stream.
|
||||||
func (reader *streamReader) Read(p []byte) (n int, err error) {
|
func (reader *streamReader) Read(p []byte) (n int, err error) {
|
||||||
if reader.r != nil {
|
if reader.r != nil {
|
||||||
// Continue reading from buffer.
|
// Continue reading from the buffer.
|
||||||
return reader.read(p)
|
return reader.read(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -142,15 +142,15 @@ func (engine *ExifTool) WriteMetadata(ctx context.Context, logger *zap.Logger, m
|
|||||||
fileMetadata[0].SetStrings(key, val)
|
fileMetadata[0].SetStrings(key, val)
|
||||||
case []interface{}:
|
case []interface{}:
|
||||||
// See https://github.com/gotenberg/gotenberg/issues/1048.
|
// See https://github.com/gotenberg/gotenberg/issues/1048.
|
||||||
strings := make([]string, len(val))
|
strs := make([]string, len(val))
|
||||||
for i, entry := range val {
|
for i, entry := range val {
|
||||||
if str, ok := entry.(string); ok {
|
if str, ok := entry.(string); ok {
|
||||||
strings[i] = str
|
strs[i] = str
|
||||||
continue
|
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.TypeOf(val), gotenberg.ErrPdfEngineMetadataValueNotSupported)
|
||||||
}
|
}
|
||||||
fileMetadata[0].SetStrings(key, strings)
|
fileMetadata[0].SetStrings(key, strs)
|
||||||
case bool:
|
case bool:
|
||||||
fileMetadata[0].SetString(key, fmt.Sprintf("%t", val))
|
fileMetadata[0].SetString(key, fmt.Sprintf("%t", val))
|
||||||
case int:
|
case int:
|
||||||
|
|||||||
@@ -24,23 +24,23 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrInvalidPdfFormats happens if the PDF formats option cannot be handled
|
// ErrInvalidPdfFormats happens if LibreOffice cannot handle the PDF
|
||||||
// by LibreOffice.
|
// formats option.
|
||||||
ErrInvalidPdfFormats = errors.New("invalid PDF formats")
|
ErrInvalidPdfFormats = errors.New("invalid PDF formats")
|
||||||
|
|
||||||
// ErrUnoException happens when unoconverter returns an exit code 5.
|
// ErrUnoException happens when unoconverter returns exit code 5.
|
||||||
ErrUnoException = errors.New("uno exception")
|
ErrUnoException = errors.New("uno exception")
|
||||||
|
|
||||||
// ErrRuntimeException happens when unoconverter returns an exit code 6.
|
// ErrRuntimeException happens when unoconverter returns exit code 6.
|
||||||
ErrRuntimeException = errors.New("uno exception")
|
ErrRuntimeException = errors.New("uno exception")
|
||||||
|
|
||||||
// ErrCoreDumped happens randomly; sometime a conversion will work as
|
// ErrCoreDumped happens randomly; sometimes a conversion will work as
|
||||||
// expected, and some other time the same conversion will fail.
|
// expected, and some other time the same conversion will fail.
|
||||||
// See https://github.com/gotenberg/gotenberg/issues/639.
|
// See https://github.com/gotenberg/gotenberg/issues/639.
|
||||||
ErrCoreDumped = errors.New("core dumped")
|
ErrCoreDumped = errors.New("core dumped")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Api is a module which provides a [Uno] to interact with LibreOffice.
|
// Api is a module that provides a [Uno] to interact with LibreOffice.
|
||||||
type Api struct {
|
type Api struct {
|
||||||
autoStart bool
|
autoStart bool
|
||||||
args libreOfficeArguments
|
args libreOfficeArguments
|
||||||
@@ -56,10 +56,10 @@ type Options struct {
|
|||||||
// Password specifies the password for opening the source file.
|
// Password specifies the password for opening the source file.
|
||||||
Password string
|
Password string
|
||||||
|
|
||||||
// Landscape allows to change the orientation of the resulting PDF.
|
// Landscape allows changing the orientation of the resulting PDF.
|
||||||
Landscape bool
|
Landscape bool
|
||||||
|
|
||||||
// PageRanges allows to select the pages to convert.
|
// PageRanges allows selecting the pages to convert.
|
||||||
PageRanges string
|
PageRanges string
|
||||||
|
|
||||||
// UpdateIndexes specifies whether to update the indexes before conversion,
|
// UpdateIndexes specifies whether to update the indexes before conversion,
|
||||||
@@ -83,7 +83,7 @@ type Options struct {
|
|||||||
// Named Destination.
|
// Named Destination.
|
||||||
ExportBookmarksToPdfDestination bool
|
ExportBookmarksToPdfDestination bool
|
||||||
|
|
||||||
// ExportPlaceholders exports the placeholders fields visual markings only.
|
// ExportPlaceholders exports the placeholder fields visual markings only.
|
||||||
// The exported placeholder is ineffective.
|
// The exported placeholder is ineffective.
|
||||||
ExportPlaceholders bool
|
ExportPlaceholders bool
|
||||||
|
|
||||||
@@ -94,15 +94,16 @@ type Options struct {
|
|||||||
// Notes pages are available in Impress documents only.
|
// Notes pages are available in Impress documents only.
|
||||||
ExportNotesPages bool
|
ExportNotesPages bool
|
||||||
|
|
||||||
// ExportOnlyNotesPages specifies, if the property ExportNotesPages is set
|
// ExportOnlyNotesPages specifies if the property ExportNotesPages is set
|
||||||
// to true, if only notes pages are exported to PDF.
|
// to true if only notes pages are exported to PDF.
|
||||||
ExportOnlyNotesPages bool
|
ExportOnlyNotesPages bool
|
||||||
|
|
||||||
// ExportNotesInMargin specifies if notes in margin are exported to PDF.
|
// ExportNotesInMargin specifies if notes in the margin are exported to
|
||||||
|
// PDF.
|
||||||
ExportNotesInMargin bool
|
ExportNotesInMargin bool
|
||||||
|
|
||||||
// ConvertOooTargetToPdfTarget specifies that the target documents with
|
// ConvertOooTargetToPdfTarget specifies that the target documents with
|
||||||
// .od[tpgs] extension, will have that extension changed to .pdf when the
|
// .od[tpgs] extension will have that extension changed to .pdf when the
|
||||||
// link is exported to PDF. The source document remains untouched.
|
// link is exported to PDF. The source document remains untouched.
|
||||||
ConvertOooTargetToPdfTarget bool
|
ConvertOooTargetToPdfTarget bool
|
||||||
|
|
||||||
@@ -190,7 +191,7 @@ type Uno interface {
|
|||||||
Extensions() []string
|
Extensions() []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provider is a module interface which exposes a method for creating a
|
// Provider is a module interface that exposes a method for creating a
|
||||||
// [Uno] for other modules.
|
// [Uno] for other modules.
|
||||||
//
|
//
|
||||||
// func (m *YourModule) Provision(ctx *gotenberg.Context) error {
|
// func (m *YourModule) Provision(ctx *gotenberg.Context) error {
|
||||||
@@ -300,8 +301,8 @@ func (a *Api) StartupMessage() string {
|
|||||||
|
|
||||||
// Stop stops the current browser instance.
|
// Stop stops the current browser instance.
|
||||||
func (a *Api) Stop(ctx context.Context) error {
|
func (a *Api) Stop(ctx context.Context) error {
|
||||||
// Block until the context is done so that other module may gracefully stop
|
// Block until the context is done so that another module may gracefully
|
||||||
// before we do a shutdown.
|
// stop before we do a shutdown.
|
||||||
a.logger.Debug("wait for the end of grace duration")
|
a.logger.Debug("wait for the end of grace duration")
|
||||||
|
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ func (p *libreOfficeProcess) Stop(logger *zap.Logger) error {
|
|||||||
logger.Debug(fmt.Sprintf("'%s' LibreOffice's user profile directory removed", userProfileDirPath))
|
logger.Debug(fmt.Sprintf("'%s' LibreOffice's user profile directory removed", userProfileDirPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also remove LibreOffice specific files in the temporary directory.
|
// Also, remove LibreOffice specific files in the temporary directory.
|
||||||
err = gotenberg.GarbageCollect(logger, os.TempDir(), []string{"OSL_PIPE", ".tmp"}, expirationTime)
|
err = gotenberg.GarbageCollect(logger, os.TempDir(), []string{"OSL_PIPE", ".tmp"}, expirationTime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err.Error())
|
logger.Error(err.Error())
|
||||||
@@ -353,10 +353,10 @@ func (p *libreOfficeProcess) pdf(ctx context.Context, logger *zap.Logger, inputP
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LibreOffice's errors are not explicit.
|
// LibreOffice's errors are not explicit.
|
||||||
// For instance, an exit code 5 may be explained by a malformed page
|
// For instance, exit code 5 may be explained by a malformed page range
|
||||||
// ranges, but also by a not required password.
|
// but also by a not required password.
|
||||||
|
|
||||||
// We may want to retry in case of a core dumped event.
|
// We may want to retry in case of a core-dumped event.
|
||||||
// See https://github.com/gotenberg/gotenberg/issues/639.
|
// See https://github.com/gotenberg/gotenberg/issues/639.
|
||||||
if strings.Contains(err.Error(), "core dumped") {
|
if strings.Contains(err.Error(), "core dumped") {
|
||||||
return ErrCoreDumped
|
return ErrCoreDumped
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ func init() {
|
|||||||
gotenberg.MustRegisterModule(new(LibreOffice))
|
gotenberg.MustRegisterModule(new(LibreOffice))
|
||||||
}
|
}
|
||||||
|
|
||||||
// LibreOffice is a module which provides a route for converting documents to
|
// LibreOffice is a module that provides a route for converting documents to
|
||||||
// PDF with LibreOffice.
|
// PDF with LibreOffice.
|
||||||
type LibreOffice struct {
|
type LibreOffice struct {
|
||||||
api libeofficeapi.Uno
|
api libeofficeapi.Uno
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ func (engine *LibreOfficePdfEngine) Split(ctx context.Context, logger *zap.Logge
|
|||||||
|
|
||||||
// Flatten is not available in this implementation.
|
// Flatten is not available in this implementation.
|
||||||
func (engine *LibreOfficePdfEngine) Flatten(ctx context.Context, logger *zap.Logger, inputPath string) error {
|
func (engine *LibreOfficePdfEngine) Flatten(ctx context.Context, logger *zap.Logger, inputPath string) error {
|
||||||
return fmt.Errorf("Flatten PDF with LibreOffice: %w", gotenberg.ErrPdfEngineMethodNotSupported)
|
return fmt.Errorf("flatten PDF with LibreOffice: %w", gotenberg.ErrPdfEngineMethodNotSupported)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert converts the given PDF to a specific PDF format. Currently, only the
|
// Convert converts the given PDF to a specific PDF format. Currently, only the
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap
|
|||||||
}
|
}
|
||||||
|
|
||||||
if nativePdfFormats && splitMode == zeroValuedSplitMode {
|
if nativePdfFormats && splitMode == zeroValuedSplitMode {
|
||||||
// Only apply natively given PDF formats if we're not
|
// Only natively apply given PDF formats if we're not
|
||||||
// splitting the PDF later.
|
// splitting the PDF later.
|
||||||
options.PdfFormats = pdfFormats
|
options.PdfFormats = pdfFormats
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ const (
|
|||||||
textLoggingFormat = "text"
|
textLoggingFormat = "text"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Logging is a module which implements the [gotenberg.LoggerProvider]
|
// Logging is a module that implements the [gotenberg.LoggerProvider]
|
||||||
// interface.
|
// interface.
|
||||||
type Logging struct {
|
type Logging struct {
|
||||||
level string
|
level string
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ func (multi *multiPdfEngines) Flatten(ctx context.Context, logger *zap.Logger, i
|
|||||||
return fmt.Errorf("flatten PDF with multi PDF engines: %w", err)
|
return fmt.Errorf("flatten PDF with multi PDF engines: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert converts the given PDF to a specific PDF format. thanks to its
|
// Convert converts the given PDF to a specific PDF format, thanks to its
|
||||||
// children. If the context is done, it stops and returns an error.
|
// children. If the context is done, it stops and returns an error.
|
||||||
func (multi *multiPdfEngines) Convert(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
|
func (multi *multiPdfEngines) Convert(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
|
||||||
var err error
|
var err error
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ func (mod *PdfEngines) Provision(ctx *gotenberg.Context) error {
|
|||||||
defaultNames[i] = engine.(gotenberg.Module).Descriptor().ID
|
defaultNames[i] = engine.(gotenberg.Module).Descriptor().ID
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example in case of deprecated module name.
|
// Example in the case of deprecated module name.
|
||||||
//for i, name := range defaultNames {
|
//for i, name := range defaultNames {
|
||||||
// if name == "unoconv-pdfengine" || name == "uno-pdfengine" {
|
// if name == "unoconv-pdfengine" || name == "uno-pdfengine" {
|
||||||
// logger.Warn(fmt.Sprintf("%s is deprecated; prefer libreoffice-pdfengine instead", name))
|
// logger.Warn(fmt.Sprintf("%s is deprecated; prefer libreoffice-pdfengine instead", name))
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ func (engine *PdfTk) Descriptor() gotenberg.ModuleDescriptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provision sets the modules properties.
|
// Provision sets the module properties.
|
||||||
func (engine *PdfTk) Provision(ctx *gotenberg.Context) error {
|
func (engine *PdfTk) Provision(ctx *gotenberg.Context) error {
|
||||||
binPath, ok := os.LookupEnv("PDFTK_BIN_PATH")
|
binPath, ok := os.LookupEnv("PDFTK_BIN_PATH")
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func init() {
|
|||||||
gotenberg.MustRegisterModule(new(Prometheus))
|
gotenberg.MustRegisterModule(new(Prometheus))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prometheus is a module which collects metrics and exposes them via an HTTP
|
// Prometheus is a module that collects metrics and exposes them via an HTTP
|
||||||
// route.
|
// route.
|
||||||
type Prometheus struct {
|
type Prometheus struct {
|
||||||
namespace string
|
namespace string
|
||||||
@@ -49,7 +49,7 @@ func (mod *Prometheus) Descriptor() gotenberg.ModuleDescriptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provision sets the modules properties.
|
// Provision sets the module properties.
|
||||||
func (mod *Prometheus) Provision(ctx *gotenberg.Context) error {
|
func (mod *Prometheus) Provision(ctx *gotenberg.Context) error {
|
||||||
flags := ctx.ParsedFlags()
|
flags := ctx.ParsedFlags()
|
||||||
mod.namespace = flags.MustString("prometheus-namespace")
|
mod.namespace = flags.MustString("prometheus-namespace")
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ func (engine *QPdf) Descriptor() gotenberg.ModuleDescriptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provision sets the modules properties.
|
// Provision sets the module properties.
|
||||||
func (engine *QPdf) Provision(ctx *gotenberg.Context) error {
|
func (engine *QPdf) Provision(ctx *gotenberg.Context) error {
|
||||||
binPath, ok := os.LookupEnv("QPDF_BIN_PATH")
|
binPath, ok := os.LookupEnv("QPDF_BIN_PATH")
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|||||||
@@ -26,14 +26,14 @@ type client struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// send call the webhook either to send the success response or the error response.
|
// send call the webhook either to send the success response or the error response.
|
||||||
func (c client) send(body io.Reader, headers map[string]string, erroed bool) error {
|
func (c client) send(body io.Reader, headers map[string]string, errored bool) error {
|
||||||
url := c.url
|
url := c.url
|
||||||
if erroed {
|
if errored {
|
||||||
url = c.errorUrl
|
url = c.errorUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
method := c.method
|
method := c.method
|
||||||
if erroed {
|
if errored {
|
||||||
method = c.errorMethod
|
method = c.errorMethod
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,9 +54,9 @@ func (c client) send(body io.Reader, headers map[string]string, erroed bool) err
|
|||||||
contentLength, ok := headers[echo.HeaderContentLength]
|
contentLength, ok := headers[echo.HeaderContentLength]
|
||||||
if ok {
|
if ok {
|
||||||
// Golang "http" package should automatically calculate the size of the
|
// Golang "http" package should automatically calculate the size of the
|
||||||
// body. But, when using a buffered file reader, it does not work.
|
// body. But when using a buffered file reader, it does not work.
|
||||||
// Worse, the "Content-Length" header is also removed. Therefore, in
|
// Worse, the "Content-Length" header is also removed. Therefore,
|
||||||
// order to keep this valuable information, we have to trust the caller
|
// to keep this valuable information, we have to trust the caller
|
||||||
// by reading the value of the "Content-Length" entry and set it as the
|
// by reading the value of the "Content-Length" entry and set it as the
|
||||||
// content length of the request. It's kinda suboptimal, but hey, at
|
// content length of the request. It's kinda suboptimal, but hey, at
|
||||||
// least it works.
|
// least it works.
|
||||||
@@ -100,7 +100,7 @@ func (c client) send(body io.Reader, headers map[string]string, erroed bool) err
|
|||||||
fields[3] = zap.String("latency_human", finishTime.Sub(c.startTime).String())
|
fields[3] = zap.String("latency_human", finishTime.Sub(c.startTime).String())
|
||||||
fields[4] = zap.Int64("bytes_out", req.ContentLength)
|
fields[4] = zap.Int64("bytes_out", req.ContentLength)
|
||||||
|
|
||||||
if erroed {
|
if errored {
|
||||||
c.logger.Warn("request to webhook with error details handled", fields...)
|
c.logger.Warn("request to webhook with error details handled", fields...)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ func webhookMiddleware(w *Webhook) api.Middleware {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve values from echo.Context before it get recycled.
|
// Retrieve values from echo.Context before it gets recycled.
|
||||||
// See https://github.com/gotenberg/gotenberg/issues/1000.
|
// See https://github.com/gotenberg/gotenberg/issues/1000.
|
||||||
startTime := c.Get("startTime").(time.Time)
|
startTime := c.Get("startTime").(time.Time)
|
||||||
traceHeader := c.Get("traceHeader").(string)
|
traceHeader := c.Get("traceHeader").(string)
|
||||||
@@ -189,7 +189,7 @@ func webhookMiddleware(w *Webhook) api.Middleware {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// No error, let's get build the output file.
|
// No error, let's get to build the output file.
|
||||||
outputPath, err := ctx.BuildOutputFile()
|
outputPath, err := ctx.BuildOutputFile()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Log().Error(fmt.Sprintf("build output file: %s", err))
|
ctx.Log().Error(fmt.Sprintf("build output file: %s", err))
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ func init() {
|
|||||||
gotenberg.MustRegisterModule(new(Webhook))
|
gotenberg.MustRegisterModule(new(Webhook))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Webhook is a module which provides a middleware for uploading output files
|
// Webhook is a module that provides a middleware for uploading output files
|
||||||
// to any destinations in an asynchronous fashion.
|
// to any destinations in an asynchronous fashion.
|
||||||
type Webhook struct {
|
type Webhook struct {
|
||||||
allowList *regexp2.Regexp
|
allowList *regexp2.Regexp
|
||||||
|
|||||||
Reference in New Issue
Block a user