Compare commits

..

11 Commits

Author SHA1 Message Date
Julien Neuhart
e50de4201d chore(deps): update Go dependencies 2024-05-22 09:44:19 +02:00
Julien Neuhart
ba2b876ee4 chore(deps): update golangci-lint 2024-05-22 09:43:41 +02:00
dependabot[bot]
9b1399c9d5 chore(deps): bump golangci/golangci-lint-action from 5 to 6
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 5 to 6.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-13 07:41:40 +02:00
Julien Neuhart
020a2f00c2 fix(pdfengine): PDFcpu -> pdfcpu 2024-05-02 10:04:25 +02:00
Julien Neuhart
8713946f35 fix(ci): codecov 2024-04-29 13:03:01 +02:00
IMATIASL\jaime.pineiro
bed8c25e40 feat(logging): Write log time in local timezone rather than UTC 2024-04-29 10:18:27 +02:00
dependabot[bot]
7c51a09068 chore(deps): bump golangci/golangci-lint-action from 4 to 5
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 4 to 5.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-29 09:48:09 +02:00
Julien Neuhart
0f0a6ce042 feat(chromium): add clip options to screenshot routes 2024-04-25 17:24:23 +02:00
Julien Neuhart
a890968ee4 chore(deps): update Go dependencies 2024-04-25 16:06:28 +02:00
Julien Neuhart
2267c5be00 feat(api): add version route 2024-04-17 09:55:38 +02:00
Julien Neuhart
e853cfb98a chore(deps): update Go dependencies 2024-04-17 09:08:43 +02:00
18 changed files with 200 additions and 65 deletions

View File

@@ -22,9 +22,9 @@ jobs:
- name: Checkout source code
uses: actions/checkout@v4
- name: Run linters
uses: golangci/golangci-lint-action@v4
uses: golangci/golangci-lint-action@v6
with:
version: v1.56.2
version: v1.58.2
tests:
needs:
@@ -43,9 +43,12 @@ jobs:
- name: Build testing environment
run: make build build-tests
- name: Run tests
run: |
make tests-once
bash <(curl -s https://codecov.io/bash)
run: make tests-once
- name: Upload to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
multiarch_build:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'

View File

@@ -12,7 +12,7 @@ GOTENBERG_USER_GID=1001
GOTENBERG_USER_UID=1001
NOTO_COLOR_EMOJI_VERSION=v2.042 # See https://github.com/googlefonts/noto-emoji/releases.
PDFTK_VERSION=v3.3.3 # See https://gitlab.com/pdftk-java/pdftk/-/releases - Binary package.
GOLANGCI_LINT_VERSION=v1.56.2 # See https://github.com/golangci/golangci-lint/releases.
GOLANGCI_LINT_VERSION=v1.58.2 # See https://github.com/golangci/golangci-lint/releases.
.PHONY: build
build: ## Build the Gotenberg's Docker image

View File

@@ -35,6 +35,7 @@ var Version = "snapshot"
// Run starts the Gotenberg application. Call this in the main of your program.
func Run() {
fmt.Printf(banner, Version)
gotenberg.Version = Version
// Create the root FlagSet and adds the modules flags to it.
fs := flag.NewFlagSet("gotenberg", flag.ExitOnError)

30
go.mod
View File

@@ -6,35 +6,35 @@ require (
github.com/alexliesenfeld/health v0.8.0
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/barasher/go-exiftool v1.10.0
github.com/chromedp/cdproto v0.0.0-20240328024531-fe04f09ede24
github.com/chromedp/cdproto v0.0.0-20240519224452-66462be74baa
github.com/chromedp/chromedp v0.9.5
github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.6.0
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.5
github.com/hashicorp/go-retryablehttp v0.7.6
github.com/klauspost/compress v1.17.8 // 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/mattn/go-isatty v0.0.20 // indirect
github.com/mholt/archiver/v3 v3.5.1
github.com/microcosm-cc/bluemonday v1.0.26
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/prometheus/client_golang v1.19.0
github.com/prometheus/client_golang v1.19.1
github.com/russross/blackfriday/v2 v2.1.0
github.com/spf13/pflag v1.0.5
github.com/ulikunitz/xz v0.5.12 // indirect
go.uber.org/multierr v1.11.0
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/image v0.15.0 // indirect
golang.org/x/net v0.24.0
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/image v0.16.0 // indirect
golang.org/x/net v0.25.0
golang.org/x/sync v0.7.0
golang.org/x/sys v0.19.0 // indirect
golang.org/x/term v0.19.0
golang.org/x/text v0.14.0
golang.org/x/sys v0.20.0 // indirect
golang.org/x/term v0.20.0
golang.org/x/text v0.15.0
)
require github.com/dlclark/regexp2 v1.11.0
@@ -47,7 +47,7 @@ require (
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
github.com/gobwas/ws v1.3.2 // indirect
github.com/gobwas/ws v1.4.0 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/hhrutter/lzw v1.0.0 // indirect
@@ -58,13 +58,13 @@ require (
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.52.3 // indirect
github.com/prometheus/procfs v0.13.0 // indirect
github.com/prometheus/common v0.53.0 // indirect
github.com/prometheus/procfs v0.15.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
google.golang.org/protobuf v1.34.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)

66
go.sum
View File

@@ -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/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-20240328024531-fe04f09ede24 h1:XLG3KlHtG6Wg75ed/daLltJtcj8VXjw7F9mzYenzFL0=
github.com/chromedp/cdproto v0.0.0-20240328024531-fe04f09ede24/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
github.com/chromedp/cdproto v0.0.0-20240519224452-66462be74baa h1:T3Ho4BWIkoEoMPCj90W2HIPF/k56qk4JWzTs6JUBxVw=
github.com/chromedp/cdproto v0.0.0-20240519224452-66462be74baa/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
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/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic=
@@ -26,12 +26,15 @@ github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cn
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.3.2 h1:zlnbNHxumkRvfPWgfXu8RBwyNR1x8wh9cf5PTOCqs9Q=
github.com/gobwas/ws v1.3.2/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
github.com/gobwas/ws v1.4.0 h1:CTaoG1tojrh4ucGPcoJFiAQUAsEWekEWvLy7GsVNqGs=
github.com/gobwas/ws v1.4.0/go.mod h1:G3gNqMNtPppf5XUz7O4shetPpcZ1VJ7zt18dlUeakrc=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@@ -46,10 +49,10 @@ github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M=
github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-retryablehttp v0.7.6 h1:TwRYfx2z2C4cLbXmT8I5PgP/xmuqASDyiVuGYfs9GZM=
github.com/hashicorp/go-retryablehttp v0.7.6/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hhrutter/lzw v1.0.0 h1:laL89Llp86W3rRs83LvKbwYRx6INE8gDn0XNb1oXtm0=
github.com/hhrutter/lzw v1.0.0/go.mod h1:2HC6DJSn/n6iAZfgM3Pg+cP1KxeWc3ezG8bBqW5+WEo=
github.com/hhrutter/tiff v1.0.1 h1:MIus8caHU5U6823gx7C6jrfoEvfSTGtEFRiM8/LOzC0=
@@ -68,8 +71,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
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/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8=
github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8=
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
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/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo=
@@ -92,8 +95,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/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/pdfcpu/pdfcpu v0.7.0 h1:cd7/z7hAyyDuzdciKfNZyQ3TYreJza2DsuPdIHYURcA=
github.com/pdfcpu/pdfcpu v0.7.0/go.mod h1:kmpD0rk8YnZj0l3qSeGBlAB+XszHUgNv//ORH/E7EYo=
github.com/pdfcpu/pdfcpu v0.8.0 h1:SuEB4uVsPFz1nb802r38YpFpj9TtZh/oB0bGG34IRZw=
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.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
@@ -101,14 +104,14 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
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/common v0.52.3 h1:5f8uj6ZwHSscOGNdIQg6OiZv/ybiK2CO2q2drVZAQSA=
github.com/prometheus/common v0.52.3/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U=
github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o=
github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g=
github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE=
github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U=
github.com/prometheus/procfs v0.15.0 h1:A82kmvXJq2jTu5YUhSGNlYoxh85zLnKgPz4bMZgI5Ek=
github.com/prometheus/procfs v0.15.0/go.mod h1:Y0RJ/Y5g5wJpkTisOtqwDSo4HwhGmLB4VQSw2sQJLHk=
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/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
@@ -121,7 +124,6 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
@@ -141,28 +143,28 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8=
golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/image v0.16.0 h1:9kloLAKhUufZhA12l5fwnx2NZW39/we1UhBesW433jw=
golang.org/x/image v0.16.0/go.mod h1:ugSZItdV4nOxyqp56HmXwH0Ry0nBCpjnZdpDaIHdoPs=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

4
pkg/gotenberg/version.go Normal file
View File

@@ -0,0 +1,4 @@
package gotenberg
// Version is the... version of the Gotenberg application.
var Version = "snapshot"

View File

@@ -323,8 +323,9 @@ func (a *Api) Validate() error {
return err
}
routesMap := make(map[string]string, len(a.routes)+1)
routesMap := make(map[string]string, len(a.routes)+2)
routesMap["/health"] = "/health"
routesMap["/version"] = "/version"
for _, route := range a.routes {
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(
fmt.Sprintf("%s%s", a.rootPath, "health"),
func() echo.HandlerFunc {
@@ -453,6 +454,14 @@ func (a *Api) Start() error {
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.
ctx, cancel := context.WithTimeout(context.Background(), a.startTimeout)
defer cancel()

View File

@@ -790,6 +790,15 @@ func TestApi_Start(t *testing.T) {
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.
multipartRequest := func(url string) *http.Request {
body := &bytes.Buffer{}

View File

@@ -258,6 +258,7 @@ func (b *chromiumBrowser) screenshot(ctx context.Context, logger *zap.Logger, ur
waitDelayBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitDelay),
waitForExpressionBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitForExpression),
// Screenshot specific.
setDeviceMetricsOverride(logger, options.Width, options.Height),
captureScreenshotActionFunc(logger, outputPath, options),
})
}

View File

@@ -1996,6 +1996,54 @@ func TestChromiumBrowser_screenshot(t *testing.T) {
"no emulated media type",
"no wait delay",
"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 wait delay",
"no wait expression",
"set device metrics override",
},
},
} {

View File

@@ -239,6 +239,19 @@ func DefaultPdfOptions() PdfOptions {
type ScreenshotOptions struct {
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
// "webp".
// Optional.
@@ -258,6 +271,9 @@ type ScreenshotOptions struct {
func DefaultScreenshotOptions() ScreenshotOptions {
return ScreenshotOptions{
Options: DefaultOptions(),
Width: 800,
Height: 600,
Clip: false,
Format: "png",
Quality: 100,
OptimizeForSpeed: false,

View File

@@ -182,12 +182,17 @@ func FormDataChromiumScreenshotOptions(ctx *api.Context) (*api.FormData, Screens
defaultScreenshotOptions := DefaultScreenshotOptions()
var (
width, height int
clip bool
format string
quality int
optimizeForSpeed bool
)
form.
Int("width", &width, defaultScreenshotOptions.Width).
Int("height", &height, defaultScreenshotOptions.Height).
Bool("clip", &clip, defaultScreenshotOptions.Clip).
Custom("format", func(value string) error {
if value == "" {
format = defaultScreenshotOptions.Format
@@ -228,6 +233,9 @@ func FormDataChromiumScreenshotOptions(ctx *api.Context) (*api.FormData, Screens
screenshotOptions := ScreenshotOptions{
Options: options,
Width: width,
Height: height,
Clip: clip,
Format: format,
Quality: quality,
OptimizeForSpeed: optimizeForSpeed,

View File

@@ -385,6 +385,15 @@ func TestFormDataChromiumScreenshotOptions(t *testing.T) {
ctx: func() *api.ContextMock {
ctx := &api.ContextMock{Context: new(api.Context)}
ctx.SetValues(map[string][]string{
"width": {
"1280",
},
"height": {
"800",
},
"clip": {
"true",
},
"optimizeForSpeed": {
"true",
},
@@ -396,6 +405,9 @@ func TestFormDataChromiumScreenshotOptions(t *testing.T) {
}(),
expectedOptions: func() ScreenshotOptions {
options := DefaultScreenshotOptions()
options.Width = 1280
options.Height = 800
options.Clip = true
options.OptimizeForSpeed = true
options.EmulatedMediaType = "screen"
return options

View File

@@ -121,6 +121,14 @@ func captureScreenshotActionFunc(logger *zap.Logger, outputPath string, options
WithOptimizeForSpeed(options.OptimizeForSpeed).
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" {
captureScreenshot = captureScreenshot.
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 {
return func(ctx context.Context) error {
// See https://github.com/gotenberg/gotenberg/issues/753.

View File

@@ -174,7 +174,7 @@ func newLogEncoder(format string) (zapcore.Encoder, error) {
// If interactive terminal, make output more human-readable by default.
// Credits: https://github.com/caddyserver/caddy/blob/v2.1.1/logging.go#L671.
encCfg.EncodeTime = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) {
encoder.AppendString(ts.UTC().Format("2006/01/02 15:04:05.000"))
encoder.AppendString(ts.Local().Format("2006/01/02 15:04:05.000"))
}
if format == textLoggingFormat || format == autoLoggingFormat {

View File

@@ -46,22 +46,22 @@ func (engine *PdfCpu) Merge(ctx context.Context, logger *zap.Logger, inputPaths
return nil
}
return fmt.Errorf("merge PDFs with PDFcpu: %w", err)
return fmt.Errorf("merge PDFs with pdfcpu: %w", err)
}
// Convert is not available in this implementation.
func (engine *PdfCpu) Convert(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
return fmt.Errorf("convert PDF to '%+v' with PDFcpu: %w", formats, gotenberg.ErrPdfEngineMethodNotSupported)
return fmt.Errorf("convert PDF to '%+v' with pdfcpu: %w", formats, gotenberg.ErrPdfEngineMethodNotSupported)
}
// ReadMetadata is not available in this implementation.
func (engine *PdfCpu) ReadMetadata(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) {
return nil, fmt.Errorf("read PDF metadata with PDFcpu: %w", gotenberg.ErrPdfEngineMethodNotSupported)
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 {
return fmt.Errorf("write PDF metadata with PDFcpu: %w", gotenberg.ErrPdfEngineMethodNotSupported)
return fmt.Errorf("write PDF metadata with pdfcpu: %w", gotenberg.ErrPdfEngineMethodNotSupported)
}
// Interface guards.

View File

@@ -159,7 +159,7 @@ func webhookMiddleware(w *Webhook) api.Middleware {
}
headers := map[string]string{
echo.HeaderContentType: echo.MIMEApplicationJSONCharsetUTF8,
echo.HeaderContentType: echo.MIMEApplicationJSON,
c.Get("traceHeader").(string): c.Get("trace").(string),
}

View File

@@ -376,7 +376,7 @@ func TestWebhookMiddlewareAsynchronousProcess(t *testing.T) {
return errors.New("foo")
}
}(),
expectWebhookContentType: echo.MIMEApplicationJSONCharsetUTF8,
expectWebhookContentType: echo.MIMEApplicationJSON,
expectWebhookMethod: http.MethodPost,
expectWebhookErrorStatus: 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))
}
}(),
expectWebhookContentType: echo.MIMEApplicationJSONCharsetUTF8,
expectWebhookContentType: echo.MIMEApplicationJSON,
expectWebhookMethod: http.MethodPost,
expectWebhookErrorStatus: http.StatusBadRequest,
expectWebhookErrorMessage: http.StatusText(http.StatusBadRequest),
@@ -430,7 +430,7 @@ func TestWebhookMiddlewareAsynchronousProcess(t *testing.T) {
}
}(),
returnedError: echo.ErrInternalServerError,
expectWebhookContentType: echo.MIMEApplicationJSONCharsetUTF8,
expectWebhookContentType: echo.MIMEApplicationJSON,
expectWebhookMethod: http.MethodPost,
expectWebhookErrorStatus: 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)
if err != nil {
errChan <- err