mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-14 11:22:15 +01:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f0a6ce042 | ||
|
|
a890968ee4 | ||
|
|
2267c5be00 | ||
|
|
e853cfb98a |
@@ -35,6 +35,7 @@ var Version = "snapshot"
|
|||||||
// Run starts the Gotenberg application. Call this in the main of your program.
|
// Run starts the Gotenberg application. Call this in the main of your program.
|
||||||
func Run() {
|
func Run() {
|
||||||
fmt.Printf(banner, Version)
|
fmt.Printf(banner, Version)
|
||||||
|
gotenberg.Version = Version
|
||||||
|
|
||||||
// Create the root FlagSet and adds the modules flags to it.
|
// Create the root FlagSet and adds the modules flags to it.
|
||||||
fs := flag.NewFlagSet("gotenberg", flag.ExitOnError)
|
fs := flag.NewFlagSet("gotenberg", flag.ExitOnError)
|
||||||
|
|||||||
10
go.mod
10
go.mod
@@ -6,7 +6,7 @@ require (
|
|||||||
github.com/alexliesenfeld/health v0.8.0
|
github.com/alexliesenfeld/health v0.8.0
|
||||||
github.com/andybalholm/brotli v1.1.0 // indirect
|
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||||
github.com/barasher/go-exiftool v1.10.0
|
github.com/barasher/go-exiftool v1.10.0
|
||||||
github.com/chromedp/cdproto v0.0.0-20240328024531-fe04f09ede24
|
github.com/chromedp/cdproto v0.0.0-20240421230201-ab917191657d
|
||||||
github.com/chromedp/chromedp v0.9.5
|
github.com/chromedp/chromedp v0.9.5
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
@@ -14,13 +14,13 @@ require (
|
|||||||
github.com/hashicorp/go-retryablehttp v0.7.5
|
github.com/hashicorp/go-retryablehttp v0.7.5
|
||||||
github.com/klauspost/compress v1.17.8 // indirect
|
github.com/klauspost/compress v1.17.8 // indirect
|
||||||
github.com/klauspost/pgzip v1.2.6 // indirect
|
github.com/klauspost/pgzip v1.2.6 // indirect
|
||||||
github.com/labstack/echo/v4 v4.11.4
|
github.com/labstack/echo/v4 v4.12.0
|
||||||
github.com/labstack/gommon v0.4.2
|
github.com/labstack/gommon v0.4.2
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mholt/archiver/v3 v3.5.1
|
github.com/mholt/archiver/v3 v3.5.1
|
||||||
github.com/microcosm-cc/bluemonday v1.0.26
|
github.com/microcosm-cc/bluemonday v1.0.26
|
||||||
github.com/nwaples/rardecode v1.1.3 // indirect
|
github.com/nwaples/rardecode v1.1.3 // indirect
|
||||||
github.com/pdfcpu/pdfcpu v0.7.0
|
github.com/pdfcpu/pdfcpu v0.8.0
|
||||||
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
||||||
github.com/prometheus/client_golang v1.19.0
|
github.com/prometheus/client_golang v1.19.0
|
||||||
github.com/russross/blackfriday/v2 v2.1.0
|
github.com/russross/blackfriday/v2 v2.1.0
|
||||||
@@ -58,8 +58,8 @@ require (
|
|||||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/prometheus/client_model v0.6.1 // indirect
|
github.com/prometheus/client_model v0.6.1 // indirect
|
||||||
github.com/prometheus/common v0.52.3 // indirect
|
github.com/prometheus/common v0.53.0 // indirect
|
||||||
github.com/prometheus/procfs v0.13.0 // indirect
|
github.com/prometheus/procfs v0.14.0 // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||||
|
|||||||
20
go.sum
20
go.sum
@@ -12,8 +12,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/chromedp/cdproto v0.0.0-20240202021202-6d0b6a386732/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
|
github.com/chromedp/cdproto v0.0.0-20240202021202-6d0b6a386732/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
|
||||||
github.com/chromedp/cdproto v0.0.0-20240328024531-fe04f09ede24 h1:XLG3KlHtG6Wg75ed/daLltJtcj8VXjw7F9mzYenzFL0=
|
github.com/chromedp/cdproto v0.0.0-20240421230201-ab917191657d h1:x9d0XwRV3aWw1gAZtv0LrI39U+Efjp0mtyXRyikGb9Y=
|
||||||
github.com/chromedp/cdproto v0.0.0-20240328024531-fe04f09ede24/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
|
github.com/chromedp/cdproto v0.0.0-20240421230201-ab917191657d/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
|
||||||
github.com/chromedp/chromedp v0.9.5 h1:viASzruPJOiThk7c5bueOUY91jGLJVximoEMGoH93rg=
|
github.com/chromedp/chromedp v0.9.5 h1:viASzruPJOiThk7c5bueOUY91jGLJVximoEMGoH93rg=
|
||||||
github.com/chromedp/chromedp v0.9.5/go.mod h1:D4I2qONslauw/C7INoCir1BJkSwBYMyZgx8X276z3+Y=
|
github.com/chromedp/chromedp v0.9.5/go.mod h1:D4I2qONslauw/C7INoCir1BJkSwBYMyZgx8X276z3+Y=
|
||||||
github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic=
|
github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic=
|
||||||
@@ -68,8 +68,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
|||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8=
|
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
|
||||||
github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8=
|
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
|
||||||
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
||||||
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
|
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
|
||||||
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo=
|
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo=
|
||||||
@@ -92,8 +92,8 @@ github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9l
|
|||||||
github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
||||||
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw=
|
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw=
|
||||||
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
||||||
github.com/pdfcpu/pdfcpu v0.7.0 h1:cd7/z7hAyyDuzdciKfNZyQ3TYreJza2DsuPdIHYURcA=
|
github.com/pdfcpu/pdfcpu v0.8.0 h1:SuEB4uVsPFz1nb802r38YpFpj9TtZh/oB0bGG34IRZw=
|
||||||
github.com/pdfcpu/pdfcpu v0.7.0/go.mod h1:kmpD0rk8YnZj0l3qSeGBlAB+XszHUgNv//ORH/E7EYo=
|
github.com/pdfcpu/pdfcpu v0.8.0/go.mod h1:jj03y/KKrwigt5xCi8t7px2mATcKuOzkIOoCX62yMho=
|
||||||
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||||
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
||||||
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||||
@@ -105,10 +105,10 @@ github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7km
|
|||||||
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
||||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||||
github.com/prometheus/common v0.52.3 h1:5f8uj6ZwHSscOGNdIQg6OiZv/ybiK2CO2q2drVZAQSA=
|
github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE=
|
||||||
github.com/prometheus/common v0.52.3/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U=
|
github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U=
|
||||||
github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o=
|
github.com/prometheus/procfs v0.14.0 h1:Lw4VdGGoKEZilJsayHf0B+9YgLGREba2C6xr+Fdfq6s=
|
||||||
github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g=
|
github.com/prometheus/procfs v0.14.0/go.mod h1:XL+Iwz8k8ZabyZfMFHPiilCniixqQarAy5Mu67pHlNQ=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
|
|||||||
4
pkg/gotenberg/version.go
Normal file
4
pkg/gotenberg/version.go
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
package gotenberg
|
||||||
|
|
||||||
|
// Version is the... version of the Gotenberg application.
|
||||||
|
var Version = "snapshot"
|
||||||
@@ -323,8 +323,9 @@ func (a *Api) Validate() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
routesMap := make(map[string]string, len(a.routes)+1)
|
routesMap := make(map[string]string, len(a.routes)+2)
|
||||||
routesMap["/health"] = "/health"
|
routesMap["/health"] = "/health"
|
||||||
|
routesMap["/version"] = "/version"
|
||||||
|
|
||||||
for _, route := range a.routes {
|
for _, route := range a.routes {
|
||||||
if route.Path == "" {
|
if route.Path == "" {
|
||||||
@@ -442,7 +443,7 @@ func (a *Api) Start() error {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's not forget the health check route.
|
// Let's not forget the health check route...
|
||||||
a.srv.GET(
|
a.srv.GET(
|
||||||
fmt.Sprintf("%s%s", a.rootPath, "health"),
|
fmt.Sprintf("%s%s", a.rootPath, "health"),
|
||||||
func() echo.HandlerFunc {
|
func() echo.HandlerFunc {
|
||||||
@@ -453,6 +454,14 @@ func (a *Api) Start() error {
|
|||||||
hardTimeoutMiddleware(hardTimeout),
|
hardTimeoutMiddleware(hardTimeout),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ...and the version route.
|
||||||
|
a.srv.GET(
|
||||||
|
fmt.Sprintf("%s%s", a.rootPath, "version"),
|
||||||
|
func(c echo.Context) error {
|
||||||
|
return c.String(http.StatusOK, gotenberg.Version)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
// Wait for all modules to be ready.
|
// Wait for all modules to be ready.
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), a.startTimeout)
|
ctx, cancel := context.WithTimeout(context.Background(), a.startTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|||||||
@@ -790,6 +790,15 @@ func TestApi_Start(t *testing.T) {
|
|||||||
t.Errorf("expected %d status code but got %d", http.StatusOK, recorder.Code)
|
t.Errorf("expected %d status code but got %d", http.StatusOK, recorder.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// version request.
|
||||||
|
versionRequest := httptest.NewRequest(http.MethodGet, "/version", nil)
|
||||||
|
versionRequest.SetBasicAuth(mod.basicAuthUsername, mod.basicAuthPassword)
|
||||||
|
|
||||||
|
mod.srv.ServeHTTP(recorder, versionRequest)
|
||||||
|
if recorder.Code != http.StatusOK {
|
||||||
|
t.Errorf("expected %d status code but got %d", http.StatusOK, recorder.Code)
|
||||||
|
}
|
||||||
|
|
||||||
// "multipart/form-data" request.
|
// "multipart/form-data" request.
|
||||||
multipartRequest := func(url string) *http.Request {
|
multipartRequest := func(url string) *http.Request {
|
||||||
body := &bytes.Buffer{}
|
body := &bytes.Buffer{}
|
||||||
|
|||||||
@@ -258,6 +258,7 @@ func (b *chromiumBrowser) screenshot(ctx context.Context, logger *zap.Logger, ur
|
|||||||
waitDelayBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitDelay),
|
waitDelayBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitDelay),
|
||||||
waitForExpressionBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitForExpression),
|
waitForExpressionBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitForExpression),
|
||||||
// Screenshot specific.
|
// Screenshot specific.
|
||||||
|
setDeviceMetricsOverride(logger, options.Width, options.Height),
|
||||||
captureScreenshotActionFunc(logger, outputPath, options),
|
captureScreenshotActionFunc(logger, outputPath, options),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1996,6 +1996,54 @@ func TestChromiumBrowser_screenshot(t *testing.T) {
|
|||||||
"no emulated media type",
|
"no emulated media type",
|
||||||
"no wait delay",
|
"no wait delay",
|
||||||
"no wait expression",
|
"no wait expression",
|
||||||
|
"set device metrics override",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: "success (clip)",
|
||||||
|
browser: newChromiumBrowser(
|
||||||
|
browserArguments{
|
||||||
|
binPath: os.Getenv("CHROMIUM_BIN_PATH"),
|
||||||
|
wsUrlReadTimeout: 5 * time.Second,
|
||||||
|
allowList: regexp2.MustCompile("", 0),
|
||||||
|
denyList: regexp2.MustCompile("", 0),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
fs: func() *gotenberg.FileSystem {
|
||||||
|
fs := gotenberg.NewFileSystem()
|
||||||
|
|
||||||
|
err := os.MkdirAll(fs.WorkingDirPath(), 0o755)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf(fmt.Sprintf("expected no error but got: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.WriteFile(fmt.Sprintf("%s/index.html", fs.WorkingDirPath()), []byte("<h1>Default options</h1>"), 0o755)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expected no error but got: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fs
|
||||||
|
}(),
|
||||||
|
options: func() ScreenshotOptions {
|
||||||
|
options := DefaultScreenshotOptions()
|
||||||
|
options.Clip = true
|
||||||
|
return options
|
||||||
|
}(),
|
||||||
|
noDeadline: false,
|
||||||
|
start: true,
|
||||||
|
expectError: false,
|
||||||
|
expectedLogEntries: []string{
|
||||||
|
"cache not cleared",
|
||||||
|
"cookies not cleared",
|
||||||
|
"JavaScript not disabled",
|
||||||
|
"no cookies to set",
|
||||||
|
"no extra HTTP headers",
|
||||||
|
"navigate to",
|
||||||
|
"default white background not hidden",
|
||||||
|
"no emulated media type",
|
||||||
|
"no wait delay",
|
||||||
|
"no wait expression",
|
||||||
|
"set device metrics override",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2042,6 +2090,7 @@ func TestChromiumBrowser_screenshot(t *testing.T) {
|
|||||||
"no emulated media type",
|
"no emulated media type",
|
||||||
"no wait delay",
|
"no wait delay",
|
||||||
"no wait expression",
|
"no wait expression",
|
||||||
|
"set device metrics override",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
|
|||||||
@@ -239,6 +239,19 @@ func DefaultPdfOptions() PdfOptions {
|
|||||||
type ScreenshotOptions struct {
|
type ScreenshotOptions struct {
|
||||||
Options
|
Options
|
||||||
|
|
||||||
|
// Width is the device screen width in pixels.
|
||||||
|
// Optional.
|
||||||
|
Width int
|
||||||
|
|
||||||
|
// Height is the device screen height in pixels.
|
||||||
|
// Optional.
|
||||||
|
Height int
|
||||||
|
|
||||||
|
// Clip defines whether to clip the screenshot according to the device
|
||||||
|
// dimensions.
|
||||||
|
// Optional.
|
||||||
|
Clip bool
|
||||||
|
|
||||||
// Format is the image compression format, either "png" or "jpeg" or
|
// Format is the image compression format, either "png" or "jpeg" or
|
||||||
// "webp".
|
// "webp".
|
||||||
// Optional.
|
// Optional.
|
||||||
@@ -258,6 +271,9 @@ type ScreenshotOptions struct {
|
|||||||
func DefaultScreenshotOptions() ScreenshotOptions {
|
func DefaultScreenshotOptions() ScreenshotOptions {
|
||||||
return ScreenshotOptions{
|
return ScreenshotOptions{
|
||||||
Options: DefaultOptions(),
|
Options: DefaultOptions(),
|
||||||
|
Width: 800,
|
||||||
|
Height: 600,
|
||||||
|
Clip: false,
|
||||||
Format: "png",
|
Format: "png",
|
||||||
Quality: 100,
|
Quality: 100,
|
||||||
OptimizeForSpeed: false,
|
OptimizeForSpeed: false,
|
||||||
|
|||||||
@@ -182,12 +182,17 @@ func FormDataChromiumScreenshotOptions(ctx *api.Context) (*api.FormData, Screens
|
|||||||
defaultScreenshotOptions := DefaultScreenshotOptions()
|
defaultScreenshotOptions := DefaultScreenshotOptions()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
width, height int
|
||||||
|
clip bool
|
||||||
format string
|
format string
|
||||||
quality int
|
quality int
|
||||||
optimizeForSpeed bool
|
optimizeForSpeed bool
|
||||||
)
|
)
|
||||||
|
|
||||||
form.
|
form.
|
||||||
|
Int("width", &width, defaultScreenshotOptions.Width).
|
||||||
|
Int("height", &height, defaultScreenshotOptions.Height).
|
||||||
|
Bool("clip", &clip, defaultScreenshotOptions.Clip).
|
||||||
Custom("format", func(value string) error {
|
Custom("format", func(value string) error {
|
||||||
if value == "" {
|
if value == "" {
|
||||||
format = defaultScreenshotOptions.Format
|
format = defaultScreenshotOptions.Format
|
||||||
@@ -228,6 +233,9 @@ func FormDataChromiumScreenshotOptions(ctx *api.Context) (*api.FormData, Screens
|
|||||||
|
|
||||||
screenshotOptions := ScreenshotOptions{
|
screenshotOptions := ScreenshotOptions{
|
||||||
Options: options,
|
Options: options,
|
||||||
|
Width: width,
|
||||||
|
Height: height,
|
||||||
|
Clip: clip,
|
||||||
Format: format,
|
Format: format,
|
||||||
Quality: quality,
|
Quality: quality,
|
||||||
OptimizeForSpeed: optimizeForSpeed,
|
OptimizeForSpeed: optimizeForSpeed,
|
||||||
|
|||||||
@@ -385,6 +385,15 @@ func TestFormDataChromiumScreenshotOptions(t *testing.T) {
|
|||||||
ctx: func() *api.ContextMock {
|
ctx: func() *api.ContextMock {
|
||||||
ctx := &api.ContextMock{Context: new(api.Context)}
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
ctx.SetValues(map[string][]string{
|
ctx.SetValues(map[string][]string{
|
||||||
|
"width": {
|
||||||
|
"1280",
|
||||||
|
},
|
||||||
|
"height": {
|
||||||
|
"800",
|
||||||
|
},
|
||||||
|
"clip": {
|
||||||
|
"true",
|
||||||
|
},
|
||||||
"optimizeForSpeed": {
|
"optimizeForSpeed": {
|
||||||
"true",
|
"true",
|
||||||
},
|
},
|
||||||
@@ -396,6 +405,9 @@ func TestFormDataChromiumScreenshotOptions(t *testing.T) {
|
|||||||
}(),
|
}(),
|
||||||
expectedOptions: func() ScreenshotOptions {
|
expectedOptions: func() ScreenshotOptions {
|
||||||
options := DefaultScreenshotOptions()
|
options := DefaultScreenshotOptions()
|
||||||
|
options.Width = 1280
|
||||||
|
options.Height = 800
|
||||||
|
options.Clip = true
|
||||||
options.OptimizeForSpeed = true
|
options.OptimizeForSpeed = true
|
||||||
options.EmulatedMediaType = "screen"
|
options.EmulatedMediaType = "screen"
|
||||||
return options
|
return options
|
||||||
|
|||||||
@@ -121,6 +121,14 @@ func captureScreenshotActionFunc(logger *zap.Logger, outputPath string, options
|
|||||||
WithOptimizeForSpeed(options.OptimizeForSpeed).
|
WithOptimizeForSpeed(options.OptimizeForSpeed).
|
||||||
WithFormat(page.CaptureScreenshotFormat(options.Format))
|
WithFormat(page.CaptureScreenshotFormat(options.Format))
|
||||||
|
|
||||||
|
if options.Clip {
|
||||||
|
captureScreenshot = captureScreenshot.WithClip(&page.Viewport{
|
||||||
|
Width: float64(options.Width),
|
||||||
|
Height: float64(options.Height),
|
||||||
|
Scale: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if options.Format == "jpeg" {
|
if options.Format == "jpeg" {
|
||||||
captureScreenshot = captureScreenshot.
|
captureScreenshot = captureScreenshot.
|
||||||
WithQuality(int64(options.Quality))
|
WithQuality(int64(options.Quality))
|
||||||
@@ -154,6 +162,19 @@ func captureScreenshotActionFunc(logger *zap.Logger, outputPath string, options
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setDeviceMetricsOverride(logger *zap.Logger, width, height int) chromedp.ActionFunc {
|
||||||
|
return func(ctx context.Context) error {
|
||||||
|
logger.Debug("set device metrics override")
|
||||||
|
|
||||||
|
err := emulation.SetDeviceMetricsOverride(int64(width), int64(height), 1.0, false).Do(ctx)
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("set device metrics override: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func clearCacheActionFunc(logger *zap.Logger, clear bool) chromedp.ActionFunc {
|
func clearCacheActionFunc(logger *zap.Logger, clear bool) chromedp.ActionFunc {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
// See https://github.com/gotenberg/gotenberg/issues/753.
|
// See https://github.com/gotenberg/gotenberg/issues/753.
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ func webhookMiddleware(w *Webhook) api.Middleware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
headers := map[string]string{
|
headers := map[string]string{
|
||||||
echo.HeaderContentType: echo.MIMEApplicationJSONCharsetUTF8,
|
echo.HeaderContentType: echo.MIMEApplicationJSON,
|
||||||
c.Get("traceHeader").(string): c.Get("trace").(string),
|
c.Get("traceHeader").(string): c.Get("trace").(string),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -376,7 +376,7 @@ func TestWebhookMiddlewareAsynchronousProcess(t *testing.T) {
|
|||||||
return errors.New("foo")
|
return errors.New("foo")
|
||||||
}
|
}
|
||||||
}(),
|
}(),
|
||||||
expectWebhookContentType: echo.MIMEApplicationJSONCharsetUTF8,
|
expectWebhookContentType: echo.MIMEApplicationJSON,
|
||||||
expectWebhookMethod: http.MethodPost,
|
expectWebhookMethod: http.MethodPost,
|
||||||
expectWebhookErrorStatus: http.StatusInternalServerError,
|
expectWebhookErrorStatus: http.StatusInternalServerError,
|
||||||
expectWebhookErrorMessage: http.StatusText(http.StatusInternalServerError),
|
expectWebhookErrorMessage: http.StatusText(http.StatusInternalServerError),
|
||||||
@@ -390,7 +390,7 @@ func TestWebhookMiddlewareAsynchronousProcess(t *testing.T) {
|
|||||||
return api.NewSentinelHttpError(http.StatusBadRequest, http.StatusText(http.StatusBadRequest))
|
return api.NewSentinelHttpError(http.StatusBadRequest, http.StatusText(http.StatusBadRequest))
|
||||||
}
|
}
|
||||||
}(),
|
}(),
|
||||||
expectWebhookContentType: echo.MIMEApplicationJSONCharsetUTF8,
|
expectWebhookContentType: echo.MIMEApplicationJSON,
|
||||||
expectWebhookMethod: http.MethodPost,
|
expectWebhookMethod: http.MethodPost,
|
||||||
expectWebhookErrorStatus: http.StatusBadRequest,
|
expectWebhookErrorStatus: http.StatusBadRequest,
|
||||||
expectWebhookErrorMessage: http.StatusText(http.StatusBadRequest),
|
expectWebhookErrorMessage: http.StatusText(http.StatusBadRequest),
|
||||||
@@ -430,7 +430,7 @@ func TestWebhookMiddlewareAsynchronousProcess(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}(),
|
}(),
|
||||||
returnedError: echo.ErrInternalServerError,
|
returnedError: echo.ErrInternalServerError,
|
||||||
expectWebhookContentType: echo.MIMEApplicationJSONCharsetUTF8,
|
expectWebhookContentType: echo.MIMEApplicationJSON,
|
||||||
expectWebhookMethod: http.MethodPost,
|
expectWebhookMethod: http.MethodPost,
|
||||||
expectWebhookErrorStatus: http.StatusInternalServerError,
|
expectWebhookErrorStatus: http.StatusInternalServerError,
|
||||||
expectWebhookErrorMessage: http.StatusText(http.StatusInternalServerError),
|
expectWebhookErrorMessage: http.StatusText(http.StatusInternalServerError),
|
||||||
@@ -493,7 +493,7 @@ func TestWebhookMiddlewareAsynchronousProcess(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if contentType == echo.MIMEApplicationJSONCharsetUTF8 {
|
if contentType == echo.MIMEApplicationJSON {
|
||||||
body, err := io.ReadAll(c.Request().Body)
|
body, err := io.ReadAll(c.Request().Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errChan <- err
|
errChan <- err
|
||||||
|
|||||||
Reference in New Issue
Block a user