mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-14 11:22:15 +01:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43354cafb1 | ||
|
|
b2c3187690 | ||
|
|
4a788ce9d8 | ||
|
|
f9ad8bd2d5 | ||
|
|
4429aea8a4 | ||
|
|
7a60e82d03 | ||
|
|
3544e9c355 | ||
|
|
ca4f0141c6 | ||
|
|
fcaa26a84d | ||
|
|
ea103d3070 | ||
|
|
286efbe548 | ||
|
|
a0ee800002 | ||
|
|
f4d3fba306 | ||
|
|
d5a58cfcb5 | ||
|
|
0e6bb27ecf | ||
|
|
83fdc01df1 | ||
|
|
c7ccabc6cb | ||
|
|
3eefe33e64 | ||
|
|
c44dc7f0ab | ||
|
|
1639d82348 | ||
|
|
b31e520731 | ||
|
|
e85d4143c0 | ||
|
|
da20f04e25 | ||
|
|
9a49ea426e | ||
|
|
c0c4c21682 | ||
|
|
c7424dfcb3 | ||
|
|
e33ca6af12 | ||
|
|
9dc6e308b6 | ||
|
|
4fe2ff5553 | ||
|
|
e5ccb82db8 | ||
|
|
63ae987010 | ||
|
|
efa0d3fd75 | ||
|
|
fd5930bc56 |
2
.github/actions/build-test-push/action.yml
vendored
2
.github/actions/build-test-push/action.yml
vendored
@@ -14,7 +14,7 @@ inputs:
|
|||||||
description: The Docker Hub password
|
description: The Docker Hub password
|
||||||
required: true
|
required: true
|
||||||
platform:
|
platform:
|
||||||
description: linux/amd64, linux/386, linux/arm64, linux/arm/v7
|
description: linux/amd64, linux/ppc64le, linux/386, linux/arm64, linux/arm/v7
|
||||||
required: true
|
required: true
|
||||||
version:
|
version:
|
||||||
description: Gotenberg version
|
description: Gotenberg version
|
||||||
|
|||||||
1
.github/actions/merge/merge.sh
vendored
1
.github/actions/merge/merge.sh
vendored
@@ -56,6 +56,7 @@ declare -A merge_map
|
|||||||
|
|
||||||
for tag in "${tags_to_merge[@]}"; do
|
for tag in "${tags_to_merge[@]}"; do
|
||||||
target_tag="${tag//-amd64/}"
|
target_tag="${tag//-amd64/}"
|
||||||
|
target_tag="${target_tag//-ppc64le/}"
|
||||||
target_tag="${target_tag//-arm64/}"
|
target_tag="${target_tag//-arm64/}"
|
||||||
target_tag="${target_tag//-arm/}"
|
target_tag="${target_tag//-arm/}"
|
||||||
target_tag="${target_tag//-386/}"
|
target_tag="${target_tag//-386/}"
|
||||||
|
|||||||
28
.github/workflows/continuous-delivery.yml
vendored
28
.github/workflows/continuous-delivery.yml
vendored
@@ -34,6 +34,8 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
tags: ${{ steps.build_push.outputs.tags }}
|
tags: ${{ steps.build_push.outputs.tags }}
|
||||||
|
tags_cloud_run: ${{ steps.build_push.outputs.tags_cloud_run }}
|
||||||
|
tags_aws_lambda: ${{ steps.build_push.outputs.tags_aws_lambda }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout source code
|
- name: Checkout source code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
@@ -48,6 +50,27 @@ jobs:
|
|||||||
platform: linux/386
|
platform: linux/386
|
||||||
skip_integrations_tests: true
|
skip_integrations_tests: true
|
||||||
|
|
||||||
|
release_ppc64le:
|
||||||
|
name: Release linux/ppc64le
|
||||||
|
runs-on: ubuntu-24.04-ppc64le
|
||||||
|
outputs:
|
||||||
|
tags: ${{ steps.build_push.outputs.tags }}
|
||||||
|
tags_cloud_run: ${{ steps.build_push.outputs.tags_cloud_run }}
|
||||||
|
tags_aws_lambda: ${{ steps.build_push.outputs.tags_aws_lambda }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
id: build_push
|
||||||
|
uses: ./.github/actions/build-test-push
|
||||||
|
with:
|
||||||
|
docker_hub_username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
docker_hub_password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
version: ${{ github.event.release.tag_name }}
|
||||||
|
platform: linux/ppc64le
|
||||||
|
skip_integrations_tests: true
|
||||||
|
|
||||||
release_arm64:
|
release_arm64:
|
||||||
name: Release linux/arm64
|
name: Release linux/arm64
|
||||||
runs-on: ubuntu-24.04-arm
|
runs-on: ubuntu-24.04-arm
|
||||||
@@ -94,6 +117,7 @@ jobs:
|
|||||||
needs:
|
needs:
|
||||||
- release_amd64
|
- release_amd64
|
||||||
- release_386
|
- release_386
|
||||||
|
- release_ppc64le
|
||||||
- release_arm64
|
- release_arm64
|
||||||
- release_arm_v7
|
- release_arm_v7
|
||||||
name: Merge and clean release tags
|
name: Merge and clean release tags
|
||||||
@@ -107,7 +131,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
docker_hub_username: ${{ secrets.DOCKERHUB_USERNAME }}
|
docker_hub_username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
docker_hub_password: ${{ secrets.DOCKERHUB_TOKEN }}
|
docker_hub_password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
tags: "${{ needs.release_amd64.outputs.tags }},${{ needs.release_386.outputs.tags }},${{ needs.release_arm64.outputs.tags }},${{ needs.release_arm_v7.outputs.tags }}"
|
tags: "${{ needs.release_amd64.outputs.tags }},${{ needs.release_386.outputs.tags }},${{ needs.release_ppc64le.outputs.tags }},${{ needs.release_arm64.outputs.tags }},${{ needs.release_arm_v7.outputs.tags }}"
|
||||||
alternate_registry: thecodingmachine
|
alternate_registry: thecodingmachine
|
||||||
|
|
||||||
- name: Merge AWS Lambda
|
- name: Merge AWS Lambda
|
||||||
@@ -123,4 +147,4 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
docker_hub_username: ${{ secrets.DOCKERHUB_USERNAME }}
|
docker_hub_username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
docker_hub_password: ${{ secrets.DOCKERHUB_TOKEN }}
|
docker_hub_password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
tags: "${{ needs.release_amd64.outputs.tags }},${{ needs.release_386.outputs.tags }},${{ needs.release_arm64.outputs.tags }},${{ needs.release_arm_v7.outputs.tags }},${{ needs.release_amd64.outputs.tags_aws_lambda }},${{ needs.release_arm64.outputs.tags_aws_lambda }}"
|
tags: "${{ needs.release_amd64.outputs.tags }},${{ needs.release_386.outputs.tags }},${{ needs.release_ppc64le.outputs.tags }},${{ needs.release_arm64.outputs.tags }},${{ needs.release_arm_v7.outputs.tags }},${{ needs.release_amd64.outputs.tags_aws_lambda }},${{ needs.release_arm64.outputs.tags_aws_lambda }}"
|
||||||
|
|||||||
64
.github/workflows/continuous-integration.yml
vendored
64
.github/workflows/continuous-integration.yml
vendored
@@ -29,9 +29,9 @@ jobs:
|
|||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
|
|
||||||
- name: Run linters
|
- name: Run linters
|
||||||
uses: golangci/golangci-lint-action@v8
|
uses: golangci/golangci-lint-action@v9
|
||||||
with:
|
with:
|
||||||
version: v2.4.0
|
version: v2.5.0
|
||||||
|
|
||||||
lint-prettier:
|
lint-prettier:
|
||||||
name: Lint non-Golang codebase
|
name: Lint non-Golang codebase
|
||||||
@@ -41,7 +41,7 @@ jobs:
|
|||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v5
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
|
|
||||||
@@ -93,6 +93,30 @@ jobs:
|
|||||||
platform: linux/amd64
|
platform: linux/amd64
|
||||||
alternate_repository: snapshot
|
alternate_repository: snapshot
|
||||||
|
|
||||||
|
snapshot_ppc64le:
|
||||||
|
if: github.event_name == 'pull_request'
|
||||||
|
needs:
|
||||||
|
- test-unit
|
||||||
|
name: Snapshot linux/ppc64le
|
||||||
|
runs-on: ubuntu-24.04-ppc64le
|
||||||
|
outputs:
|
||||||
|
tags: ${{ steps.build_test_push.outputs.tags }}
|
||||||
|
tags_cloud_run: ${{ steps.build_test_push.outputs.tags_cloud_run }}
|
||||||
|
tags_aws_lambda: ${{ steps.build_test_push.outputs.tags_aws_lambda }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Build, test and push
|
||||||
|
id: build_test_push
|
||||||
|
uses: ./.github/actions/build-test-push
|
||||||
|
with:
|
||||||
|
docker_hub_username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
docker_hub_password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
version: pr-${{ github.event.pull_request.number }}
|
||||||
|
platform: linux/ppc64le
|
||||||
|
alternate_repository: snapshot
|
||||||
|
|
||||||
snapshot_386:
|
snapshot_386:
|
||||||
if: github.event_name == 'pull_request'
|
if: github.event_name == 'pull_request'
|
||||||
needs:
|
needs:
|
||||||
@@ -169,6 +193,7 @@ jobs:
|
|||||||
needs:
|
needs:
|
||||||
- snapshot_amd64
|
- snapshot_amd64
|
||||||
- snapshot_386
|
- snapshot_386
|
||||||
|
- snapshot_ppc64le
|
||||||
- snapshot_arm64
|
- snapshot_arm64
|
||||||
- snapshot_arm_v7
|
- snapshot_arm_v7
|
||||||
name: Secrets access check
|
name: Secrets access check
|
||||||
@@ -191,6 +216,7 @@ jobs:
|
|||||||
- merge_clean_snapshot_guard
|
- merge_clean_snapshot_guard
|
||||||
- snapshot_amd64
|
- snapshot_amd64
|
||||||
- snapshot_386
|
- snapshot_386
|
||||||
|
- snapshot_ppc64le
|
||||||
- snapshot_arm64
|
- snapshot_arm64
|
||||||
- snapshot_arm_v7
|
- snapshot_arm_v7
|
||||||
name: Merge and clean snapshot tags
|
name: Merge and clean snapshot tags
|
||||||
@@ -204,7 +230,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
docker_hub_username: ${{ secrets.DOCKERHUB_USERNAME }}
|
docker_hub_username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
docker_hub_password: ${{ secrets.DOCKERHUB_TOKEN }}
|
docker_hub_password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
tags: "${{ needs.snapshot_amd64.outputs.tags }},${{ needs.snapshot_386.outputs.tags }},${{ needs.snapshot_arm64.outputs.tags }},${{ needs.snapshot_arm_v7.outputs.tags }}"
|
tags: "${{ needs.snapshot_amd64.outputs.tags }},${{ needs.snapshot_386.outputs.tags }},${{ needs.snapshot_ppc64le.outputs.tags }},${{ needs.snapshot_arm64.outputs.tags }},${{ needs.snapshot_arm_v7.outputs.tags }}"
|
||||||
|
|
||||||
- name: Merge AWS Lambda
|
- name: Merge AWS Lambda
|
||||||
uses: ./.github/actions/merge
|
uses: ./.github/actions/merge
|
||||||
@@ -218,7 +244,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
docker_hub_username: ${{ secrets.DOCKERHUB_USERNAME }}
|
docker_hub_username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
docker_hub_password: ${{ secrets.DOCKERHUB_TOKEN }}
|
docker_hub_password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
tags: "${{ needs.snapshot_amd64.outputs.tags }},${{ needs.snapshot_386.outputs.tags }},${{ needs.snapshot_arm64.outputs.tags }},${{ needs.snapshot_arm_v7.outputs.tags }},${{ needs.snapshot_amd64.outputs.tags_aws_lambda }},${{ needs.snapshot_arm64.outputs.tags_aws_lambda }}"
|
tags: "${{ needs.snapshot_amd64.outputs.tags }},${{ needs.snapshot_386.outputs.tags }},${{ needs.snapshot_ppc64le.outputs.tags }},${{ needs.snapshot_arm64.outputs.tags }},${{ needs.snapshot_arm_v7.outputs.tags }},${{ needs.snapshot_amd64.outputs.tags_aws_lambda }},${{ needs.snapshot_arm64.outputs.tags_aws_lambda }}"
|
||||||
|
|
||||||
edge_amd64:
|
edge_amd64:
|
||||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||||
@@ -266,6 +292,29 @@ jobs:
|
|||||||
version: edge
|
version: edge
|
||||||
platform: linux/386
|
platform: linux/386
|
||||||
|
|
||||||
|
edge_ppc64le:
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||||
|
needs:
|
||||||
|
- test-unit
|
||||||
|
name: Edge linux/ppc64le
|
||||||
|
runs-on: ubuntu-24.04-ppc64le
|
||||||
|
outputs:
|
||||||
|
tags: ${{ steps.build_test_push.outputs.tags }}
|
||||||
|
tags_cloud_run: ${{ steps.build_test_push.outputs.tags_cloud_run }}
|
||||||
|
tags_aws_lambda: ${{ steps.build_test_push.outputs.tags_aws_lambda }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Build, test and push
|
||||||
|
id: build_test_push
|
||||||
|
uses: ./.github/actions/build-test-push
|
||||||
|
with:
|
||||||
|
docker_hub_username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
docker_hub_password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
version: edge
|
||||||
|
platform: linux/ppc64le
|
||||||
|
|
||||||
edge_arm64:
|
edge_arm64:
|
||||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||||
needs:
|
needs:
|
||||||
@@ -316,6 +365,7 @@ jobs:
|
|||||||
needs:
|
needs:
|
||||||
- edge_amd64
|
- edge_amd64
|
||||||
- edge_386
|
- edge_386
|
||||||
|
- edge_ppc64le
|
||||||
- edge_arm64
|
- edge_arm64
|
||||||
- edge_arm_v7
|
- edge_arm_v7
|
||||||
name: Merge and clean edge tags
|
name: Merge and clean edge tags
|
||||||
@@ -329,7 +379,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
docker_hub_username: ${{ secrets.DOCKERHUB_USERNAME }}
|
docker_hub_username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
docker_hub_password: ${{ secrets.DOCKERHUB_TOKEN }}
|
docker_hub_password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
tags: "${{ needs.edge_amd64.outputs.tags }},${{ needs.edge_386.outputs.tags }},${{ needs.edge_arm64.outputs.tags }},${{ needs.edge_arm_v7.outputs.tags }}"
|
tags: "${{ needs.edge_amd64.outputs.tags }},${{ needs.edge_386.outputs.tags }},${{ needs.edge_ppc64le.outputs.tags }},${{ needs.edge_arm64.outputs.tags }},${{ needs.edge_arm_v7.outputs.tags }}"
|
||||||
alternate_registry: thecodingmachine
|
alternate_registry: thecodingmachine
|
||||||
|
|
||||||
- name: Merge AWS Lambda
|
- name: Merge AWS Lambda
|
||||||
@@ -345,4 +395,4 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
docker_hub_username: ${{ secrets.DOCKERHUB_USERNAME }}
|
docker_hub_username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
docker_hub_password: ${{ secrets.DOCKERHUB_TOKEN }}
|
docker_hub_password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
tags: "${{ needs.edge_amd64.outputs.tags }},${{ needs.edge_386.outputs.tags }},${{ needs.edge_arm64.outputs.tags }},${{ needs.edge_arm_v7.outputs.tags }},${{ needs.edge_amd64.outputs.tags_aws_lambda }},${{ needs.edge_arm64.outputs.tags_aws_lambda }}"
|
tags: "${{ needs.edge_amd64.outputs.tags }},${{ needs.edge_386.outputs.tags }},${{ needs.edge_ppc64le.outputs.tags }},${{ needs.edge_arm64.outputs.tags }},${{ needs.edge_arm_v7.outputs.tags }},${{ needs.edge_amd64.outputs.tags_aws_lambda }},${{ needs.edge_arm64.outputs.tags_aws_lambda }}"
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
23.9.0
|
24.11.0
|
||||||
|
|||||||
39
Makefile
39
Makefile
@@ -34,7 +34,6 @@ CHROMIUM_RESTART_AFTER=10
|
|||||||
CHROMIUM_MAX_QUEUE_SIZE=0
|
CHROMIUM_MAX_QUEUE_SIZE=0
|
||||||
CHROMIUM_AUTO_START=false
|
CHROMIUM_AUTO_START=false
|
||||||
CHROMIUM_START_TIMEOUT=20s
|
CHROMIUM_START_TIMEOUT=20s
|
||||||
CHROMIUM_INCOGNITO=false
|
|
||||||
CHROMIUM_ALLOW_INSECURE_LOCALHOST=false
|
CHROMIUM_ALLOW_INSECURE_LOCALHOST=false
|
||||||
CHROMIUM_IGNORE_CERTIFICATE_ERRORS=false
|
CHROMIUM_IGNORE_CERTIFICATE_ERRORS=false
|
||||||
CHROMIUM_DISABLE_WEB_SECURITY=false
|
CHROMIUM_DISABLE_WEB_SECURITY=false
|
||||||
@@ -64,6 +63,7 @@ PDFENGINES_READ_METADATA_ENGINES=exiftool
|
|||||||
PDFENGINES_WRITE_METADATA_ENGINES=exiftool
|
PDFENGINES_WRITE_METADATA_ENGINES=exiftool
|
||||||
PDFENGINES_ENCRYPT_ENGINES=qpdf,pdfcpu,pdftk
|
PDFENGINES_ENCRYPT_ENGINES=qpdf,pdfcpu,pdftk
|
||||||
PDFENGINES_DISABLE_ROUTES=false
|
PDFENGINES_DISABLE_ROUTES=false
|
||||||
|
PDFENGINES_EMBED_ENGINES=pdfcpu
|
||||||
PROMETHEUS_NAMESPACE=gotenberg
|
PROMETHEUS_NAMESPACE=gotenberg
|
||||||
PROMETHEUS_COLLECT_INTERVAL=1s
|
PROMETHEUS_COLLECT_INTERVAL=1s
|
||||||
PROMETHEUS_DISABLE_ROUTE_LOGGING=false
|
PROMETHEUS_DISABLE_ROUTE_LOGGING=false
|
||||||
@@ -109,7 +109,6 @@ run: ## Start a Gotenberg container
|
|||||||
--chromium-auto-start=$(CHROMIUM_AUTO_START) \
|
--chromium-auto-start=$(CHROMIUM_AUTO_START) \
|
||||||
--chromium-max-queue-size=$(CHROMIUM_MAX_QUEUE_SIZE) \
|
--chromium-max-queue-size=$(CHROMIUM_MAX_QUEUE_SIZE) \
|
||||||
--chromium-start-timeout=$(CHROMIUM_START_TIMEOUT) \
|
--chromium-start-timeout=$(CHROMIUM_START_TIMEOUT) \
|
||||||
--chromium-incognito=$(CHROMIUM_INCOGNITO) \
|
|
||||||
--chromium-allow-insecure-localhost=$(CHROMIUM_ALLOW_INSECURE_LOCALHOST) \
|
--chromium-allow-insecure-localhost=$(CHROMIUM_ALLOW_INSECURE_LOCALHOST) \
|
||||||
--chromium-ignore-certificate-errors=$(CHROMIUM_IGNORE_CERTIFICATE_ERRORS) \
|
--chromium-ignore-certificate-errors=$(CHROMIUM_IGNORE_CERTIFICATE_ERRORS) \
|
||||||
--chromium-disable-web-security=$(CHROMIUM_DISABLE_WEB_SECURITY) \
|
--chromium-disable-web-security=$(CHROMIUM_DISABLE_WEB_SECURITY) \
|
||||||
@@ -139,6 +138,7 @@ run: ## Start a Gotenberg container
|
|||||||
--pdfengines-write-metadata-engines=$(PDFENGINES_WRITE_METADATA_ENGINES) \
|
--pdfengines-write-metadata-engines=$(PDFENGINES_WRITE_METADATA_ENGINES) \
|
||||||
--pdfengines-encrypt-engines=$(PDFENGINES_ENCRYPT_ENGINES) \
|
--pdfengines-encrypt-engines=$(PDFENGINES_ENCRYPT_ENGINES) \
|
||||||
--pdfengines-disable-routes=$(PDFENGINES_DISABLE_ROUTES) \
|
--pdfengines-disable-routes=$(PDFENGINES_DISABLE_ROUTES) \
|
||||||
|
--pdfengines-embed-engines=$(PDFENGINES_EMBED_ENGINES) \
|
||||||
--prometheus-namespace=$(PROMETHEUS_NAMESPACE) \
|
--prometheus-namespace=$(PROMETHEUS_NAMESPACE) \
|
||||||
--prometheus-collect-interval=$(PROMETHEUS_COLLECT_INTERVAL) \
|
--prometheus-collect-interval=$(PROMETHEUS_COLLECT_INTERVAL) \
|
||||||
--prometheus-disable-route-logging=$(PROMETHEUS_DISABLE_ROUTE_LOGGING) \
|
--prometheus-disable-route-logging=$(PROMETHEUS_DISABLE_ROUTE_LOGGING) \
|
||||||
@@ -160,14 +160,45 @@ test-unit: ## Run unit tests
|
|||||||
|
|
||||||
PLATFORM=
|
PLATFORM=
|
||||||
NO_CONCURRENCY=false
|
NO_CONCURRENCY=false
|
||||||
|
# Available tags:
|
||||||
|
# chromium
|
||||||
|
# chromium-convert-html
|
||||||
|
# chromium-convert-markdown
|
||||||
|
# chromium-convert-url
|
||||||
|
# debug
|
||||||
|
# health
|
||||||
|
# libreoffice
|
||||||
|
# libreoffice-convert
|
||||||
|
# output-filename
|
||||||
|
# pdfengines
|
||||||
|
# pdfengines-convert
|
||||||
|
# pdfengines-embed
|
||||||
|
# embed
|
||||||
|
# pdfengines-encrypt
|
||||||
|
# encrypt
|
||||||
|
# pdfengines-flatten
|
||||||
|
# flatten
|
||||||
|
# pdfengines-merge
|
||||||
|
# merge
|
||||||
|
# pdfengines-metadata
|
||||||
|
# metadata
|
||||||
|
# pdfengines-split
|
||||||
|
# split
|
||||||
|
# prometheus-metrics
|
||||||
|
# root
|
||||||
|
# version
|
||||||
|
# webhook
|
||||||
|
# download-from
|
||||||
|
TAGS=
|
||||||
|
|
||||||
.PHONY: test-integration
|
.PHONY: test-integration
|
||||||
test-integration: ## Run integration tests
|
test-integration: ## Run integration tests
|
||||||
go test -timeout 20m -tags=integration -v github.com/gotenberg/gotenberg/v8/test/integration -args \
|
go test -timeout 40m -tags=integration -v github.com/gotenberg/gotenberg/v8/test/integration -args \
|
||||||
--gotenberg-docker-repository=$(DOCKER_REPOSITORY) \
|
--gotenberg-docker-repository=$(DOCKER_REPOSITORY) \
|
||||||
--gotenberg-version=$(GOTENBERG_VERSION) \
|
--gotenberg-version=$(GOTENBERG_VERSION) \
|
||||||
--gotenberg-container-platform=$(PLATFORM) \
|
--gotenberg-container-platform=$(PLATFORM) \
|
||||||
--no-concurrency=$(NO_CONCURRENCY)
|
--no-concurrency=$(NO_CONCURRENCY) \
|
||||||
|
--tags="$(TAGS)"
|
||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint: ## Lint Golang codebase
|
lint: ## Lint Golang codebase
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# ARG instructions do not create additional layers. Instead, next layers will
|
# ARG instructions do not create additional layers. Instead, next layers will
|
||||||
# concatenate them. Also, we have to repeat ARG instructions in each build
|
# concatenate them. Also, we have to repeat ARG instructions in each build
|
||||||
# stage that uses them.
|
# stage that uses them.
|
||||||
ARG GOLANG_VERSION=1.25.0
|
ARG GOLANG_VERSION=1.25.4
|
||||||
|
|
||||||
# ----------------------------------------------
|
# ----------------------------------------------
|
||||||
# pdfcpu binary build stage
|
# pdfcpu binary build stage
|
||||||
@@ -11,7 +11,7 @@ ARG GOLANG_VERSION=1.25.0
|
|||||||
FROM golang:$GOLANG_VERSION AS pdfcpu-binary-stage
|
FROM golang:$GOLANG_VERSION AS pdfcpu-binary-stage
|
||||||
|
|
||||||
# See https://github.com/pdfcpu/pdfcpu/releases.
|
# See https://github.com/pdfcpu/pdfcpu/releases.
|
||||||
ARG PDFCPU_VERSION=v0.11.0
|
ARG PDFCPU_VERSION=v0.11.1
|
||||||
ENV CGO_ENABLED=0
|
ENV CGO_ENABLED=0
|
||||||
|
|
||||||
# Define the working directory outside of $GOPATH (we're using go modules).
|
# Define the working directory outside of $GOPATH (we're using go modules).
|
||||||
@@ -92,7 +92,7 @@ ARG GOTENBERG_VERSION=snapshot
|
|||||||
ARG GOTENBERG_USER_GID=1001
|
ARG GOTENBERG_USER_GID=1001
|
||||||
ARG GOTENBERG_USER_UID=1001
|
ARG GOTENBERG_USER_UID=1001
|
||||||
# See https://github.com/googlefonts/noto-emoji/releases.
|
# See https://github.com/googlefonts/noto-emoji/releases.
|
||||||
ARG NOTO_COLOR_EMOJI_VERSION=v2.048
|
ARG NOTO_COLOR_EMOJI_VERSION=v2.051
|
||||||
# See https://gitlab.com/pdftk-java/pdftk/-/releases - Binary package.
|
# See https://gitlab.com/pdftk-java/pdftk/-/releases - Binary package.
|
||||||
ARG PDFTK_VERSION=v3.3.3
|
ARG PDFTK_VERSION=v3.3.3
|
||||||
|
|
||||||
@@ -175,6 +175,20 @@ RUN \
|
|||||||
# Cleanup.
|
# Cleanup.
|
||||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||||
|
|
||||||
|
RUN \
|
||||||
|
# Install Hyphenation for LibreOffice.
|
||||||
|
# Credits: https://wiki.archlinux.org/title/LibreOffice.
|
||||||
|
apt-get update -qq &&\
|
||||||
|
apt-get upgrade -yqq &&\
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends \
|
||||||
|
hyphen-af hyphen-as hyphen-be hyphen-bg hyphen-bn hyphen-ca hyphen-cs hyphen-da hyphen-de hyphen-el \
|
||||||
|
hyphen-en-gb hyphen-en-us hyphen-eo hyphen-es hyphen-fr hyphen-gl hyphen-gu hyphen-hi hyphen-hr hyphen-hu \
|
||||||
|
hyphen-id hyphen-is hyphen-it hyphen-kn hyphen-lt hyphen-lv hyphen-ml hyphen-mn hyphen-mr hyphen-nl \
|
||||||
|
hyphen-no hyphen-or hyphen-pa hyphen-pl hyphen-pt-br hyphen-pt-pt hyphen-ro hyphen-ru hyphen-sk hyphen-sl \
|
||||||
|
hyphen-sr hyphen-sv hyphen-ta hyphen-te hyphen-th hyphen-uk hyphen-zu &&\
|
||||||
|
# Cleanup.
|
||||||
|
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
# Install Chromium.
|
# Install Chromium.
|
||||||
apt-get update -qq &&\
|
apt-get update -qq &&\
|
||||||
|
|||||||
46
go.mod
46
go.mod
@@ -1,33 +1,33 @@
|
|||||||
module github.com/gotenberg/gotenberg/v8
|
module github.com/gotenberg/gotenberg/v8
|
||||||
|
|
||||||
go 1.25.0
|
go 1.25.4
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/alexliesenfeld/health v0.8.1
|
github.com/alexliesenfeld/health v0.8.1
|
||||||
github.com/barasher/go-exiftool v1.10.0
|
github.com/barasher/go-exiftool v1.10.0
|
||||||
github.com/chromedp/cdproto v0.0.0-20250803210736-d308e07a266d
|
github.com/chromedp/cdproto v0.0.0-20250803210736-d308e07a266d
|
||||||
github.com/chromedp/chromedp v0.14.1
|
github.com/chromedp/chromedp v0.14.2
|
||||||
github.com/cucumber/godog v0.15.1
|
github.com/cucumber/godog v0.15.1
|
||||||
github.com/dlclark/regexp2 v1.11.5
|
github.com/dlclark/regexp2 v1.11.5
|
||||||
github.com/docker/docker v28.4.0+incompatible
|
github.com/docker/docker v28.5.2+incompatible
|
||||||
github.com/docker/go-connections v0.6.0
|
github.com/docker/go-connections v0.6.0
|
||||||
github.com/gomarkdown/markdown v0.0.0-20250810172220-2e2c11897d1a
|
github.com/gomarkdown/markdown v0.0.0-20250810172220-2e2c11897d1a
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.8
|
github.com/hashicorp/go-retryablehttp v0.7.8
|
||||||
github.com/labstack/echo/v4 v4.13.4
|
github.com/labstack/echo/v4 v4.13.4
|
||||||
github.com/labstack/gommon v0.4.2
|
github.com/labstack/gommon v0.4.2
|
||||||
github.com/mholt/archives v0.1.4
|
github.com/mholt/archives v0.1.5
|
||||||
github.com/microcosm-cc/bluemonday v1.0.27
|
github.com/microcosm-cc/bluemonday v1.0.27
|
||||||
github.com/prometheus/client_golang v1.23.2
|
github.com/prometheus/client_golang v1.23.2
|
||||||
github.com/shirou/gopsutil/v4 v4.25.8
|
github.com/shirou/gopsutil/v4 v4.25.10
|
||||||
github.com/spf13/pflag v1.0.10
|
github.com/spf13/pflag v1.0.10
|
||||||
github.com/testcontainers/testcontainers-go v0.39.0
|
github.com/testcontainers/testcontainers-go v0.40.0
|
||||||
go.uber.org/multierr v1.11.0
|
go.uber.org/multierr v1.11.0
|
||||||
go.uber.org/zap v1.27.0
|
go.uber.org/zap v1.27.0
|
||||||
golang.org/x/net v0.44.0
|
golang.org/x/net v0.47.0
|
||||||
golang.org/x/sync v0.17.0
|
golang.org/x/sync v0.18.0
|
||||||
golang.org/x/term v0.35.0
|
golang.org/x/term v0.37.0
|
||||||
golang.org/x/text v0.29.0
|
golang.org/x/text v0.31.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -55,9 +55,9 @@ require (
|
|||||||
github.com/distribution/reference v0.6.0 // indirect
|
github.com/distribution/reference v0.6.0 // indirect
|
||||||
github.com/docker/go-units v0.5.0 // indirect
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect
|
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect
|
||||||
github.com/ebitengine/purego v0.9.0 // indirect
|
github.com/ebitengine/purego v0.9.1 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
github.com/go-json-experiment/json v0.0.0-20250910080747-cc2cfa0554c3 // indirect
|
github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e // indirect
|
||||||
github.com/go-logr/logr v1.4.3 // indirect
|
github.com/go-logr/logr v1.4.3 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||||
@@ -71,9 +71,9 @@ require (
|
|||||||
github.com/hashicorp/go-memdb v1.3.5 // indirect
|
github.com/hashicorp/go-memdb v1.3.5 // indirect
|
||||||
github.com/hashicorp/golang-lru v1.0.2 // indirect
|
github.com/hashicorp/golang-lru v1.0.2 // indirect
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||||
github.com/klauspost/compress v1.18.0 // indirect
|
github.com/klauspost/compress v1.18.1 // indirect
|
||||||
github.com/klauspost/pgzip v1.2.6 // indirect
|
github.com/klauspost/pgzip v1.2.6 // indirect
|
||||||
github.com/lufia/plan9stats v0.0.0-20250827001030-24949be3fa54 // indirect
|
github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3 // indirect
|
||||||
github.com/magiconair/properties v1.8.10 // indirect
|
github.com/magiconair/properties v1.8.10 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
@@ -88,7 +88,7 @@ require (
|
|||||||
github.com/moby/term v0.5.2 // indirect
|
github.com/moby/term v0.5.2 // indirect
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/nwaples/rardecode/v2 v2.1.1 // indirect
|
github.com/nwaples/rardecode/v2 v2.2.1 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||||
github.com/pierrec/lz4/v4 v4.1.22 // indirect
|
github.com/pierrec/lz4/v4 v4.1.22 // indirect
|
||||||
@@ -96,14 +96,14 @@ require (
|
|||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||||
github.com/prometheus/client_model v0.6.2 // indirect
|
github.com/prometheus/client_model v0.6.2 // indirect
|
||||||
github.com/prometheus/common v0.66.1 // indirect
|
github.com/prometheus/common v0.67.2 // indirect
|
||||||
github.com/prometheus/procfs v0.17.0 // indirect
|
github.com/prometheus/procfs v0.19.2 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
github.com/sorairolake/lzip-go v0.3.8 // indirect
|
github.com/sorairolake/lzip-go v0.3.8 // indirect
|
||||||
github.com/spf13/afero v1.15.0 // indirect
|
github.com/spf13/afero v1.15.0 // indirect
|
||||||
github.com/stretchr/testify v1.11.1 // indirect
|
github.com/stretchr/testify v1.11.1 // indirect
|
||||||
github.com/tklauser/go-sysconf v0.3.15 // indirect
|
github.com/tklauser/go-sysconf v0.3.16 // indirect
|
||||||
github.com/tklauser/numcpus v0.10.0 // indirect
|
github.com/tklauser/numcpus v0.11.0 // indirect
|
||||||
github.com/ulikunitz/xz v0.5.15 // indirect
|
github.com/ulikunitz/xz v0.5.15 // 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
|
||||||
@@ -117,11 +117,11 @@ require (
|
|||||||
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
|
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
|
||||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||||
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
|
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
|
||||||
golang.org/x/crypto v0.42.0 // indirect
|
golang.org/x/crypto v0.44.0 // indirect
|
||||||
golang.org/x/sys v0.36.0 // indirect
|
golang.org/x/sys v0.38.0 // indirect
|
||||||
golang.org/x/time v0.13.0 // indirect
|
golang.org/x/time v0.14.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250728155136-f173205681a0 // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20250728155136-f173205681a0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0 // indirect
|
||||||
google.golang.org/protobuf v1.36.9 // indirect
|
google.golang.org/protobuf v1.36.10 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
88
go.sum
88
go.sum
@@ -50,8 +50,8 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
|
|||||||
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-20250803210736-d308e07a266d h1:ZtA1sedVbEW7EW80Iz2GR3Ye6PwbJAJXjv7D74xG6HU=
|
github.com/chromedp/cdproto v0.0.0-20250803210736-d308e07a266d h1:ZtA1sedVbEW7EW80Iz2GR3Ye6PwbJAJXjv7D74xG6HU=
|
||||||
github.com/chromedp/cdproto v0.0.0-20250803210736-d308e07a266d/go.mod h1:NItd7aLkcfOA/dcMXvl8p1u+lQqioRMq/SqDp71Pb/k=
|
github.com/chromedp/cdproto v0.0.0-20250803210736-d308e07a266d/go.mod h1:NItd7aLkcfOA/dcMXvl8p1u+lQqioRMq/SqDp71Pb/k=
|
||||||
github.com/chromedp/chromedp v0.14.1 h1:0uAbnxewy/Q+Bg7oafVePE/6EXEho9hnaC38f+TTENg=
|
github.com/chromedp/chromedp v0.14.2 h1:r3b/WtwM50RsBZHMUm9fsNhhzRStTHrKdr2zmwbZSzM=
|
||||||
github.com/chromedp/chromedp v0.14.1/go.mod h1:rHzAv60xDE7VNy/MYtTUrYreSc0ujt2O1/C3bzctYBo=
|
github.com/chromedp/chromedp v0.14.2/go.mod h1:rHzAv60xDE7VNy/MYtTUrYreSc0ujt2O1/C3bzctYBo=
|
||||||
github.com/chromedp/sysutil v1.1.0 h1:PUFNv5EcprjqXZD9nJb9b/c9ibAbxiYo4exNWZyipwM=
|
github.com/chromedp/sysutil v1.1.0 h1:PUFNv5EcprjqXZD9nJb9b/c9ibAbxiYo4exNWZyipwM=
|
||||||
github.com/chromedp/sysutil v1.1.0/go.mod h1:WiThHUdltqCNKGc4gaU50XgYjwjYIhKWoHGPTUfWTJ8=
|
github.com/chromedp/sysutil v1.1.0/go.mod h1:WiThHUdltqCNKGc4gaU50XgYjwjYIhKWoHGPTUfWTJ8=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
@@ -85,8 +85,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr
|
|||||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||||
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
|
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
|
||||||
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||||
github.com/docker/docker v28.4.0+incompatible h1:KVC7bz5zJY/4AZe/78BIvCnPsLaC9T/zh72xnlrTTOk=
|
github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM=
|
||||||
github.com/docker/docker v28.4.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
|
github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
|
||||||
github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
|
github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
|
||||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||||
@@ -94,8 +94,8 @@ github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
|
|||||||
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4=
|
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4=
|
||||||
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
|
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
|
||||||
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
|
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
|
||||||
github.com/ebitengine/purego v0.9.0 h1:mh0zpKBIXDceC63hpvPuGLiJ8ZAa3DfrFTudmfi8A4k=
|
github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A=
|
||||||
github.com/ebitengine/purego v0.9.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||||
@@ -104,8 +104,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
|
|||||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-json-experiment/json v0.0.0-20250910080747-cc2cfa0554c3 h1:02WINGfSX5w0Mn+F28UyRoSt9uvMhKguwWMlOAh6U/0=
|
github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e h1:Lf/gRkoycfOBPa42vU2bbgPurFong6zXeFtPoxholzU=
|
||||||
github.com/go-json-experiment/json v0.0.0-20250910080747-cc2cfa0554c3/go.mod h1:uNVvRXArCGbZ508SxYYTC5v1JWoz2voff5pm25jU1Ok=
|
github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e/go.mod h1:uNVvRXArCGbZ508SxYYTC5v1JWoz2voff5pm25jU1Ok=
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
@@ -188,8 +188,8 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
|
|||||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
|
||||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
|
||||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||||
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
|
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
|
||||||
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||||
@@ -209,16 +209,16 @@ 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=
|
||||||
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
|
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
|
||||||
github.com/lufia/plan9stats v0.0.0-20250827001030-24949be3fa54 h1:mFWunSatvkQQDhpdyuFAYwyAan3hzCuma+Pz8sqvOfg=
|
github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3 h1:PwQumkgq4/acIiZhtifTV5OUqqiP82UAl0h87xj/l9k=
|
||||||
github.com/lufia/plan9stats v0.0.0-20250827001030-24949be3fa54/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
|
github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
|
||||||
github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
|
github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
|
||||||
github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mholt/archives v0.1.4 h1:sU+/lLNgafUontWFv3AVwO8VUWye3rrtN6hgC2dU11c=
|
github.com/mholt/archives v0.1.5 h1:Fh2hl1j7VEhc6DZs2DLMgiBNChUux154a1G+2esNvzQ=
|
||||||
github.com/mholt/archives v0.1.4/go.mod h1:I2ia+SQTtQHej9w1GZM/mz7qfdgQv+BHr3hEKqDcGuk=
|
github.com/mholt/archives v0.1.5/go.mod h1:3TPMmBLPsgszL+1As5zECTuKwKvIfj6YcwWPpeTAXF4=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
|
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
|
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
|
||||||
github.com/mikelolasagasti/xz v1.0.1 h1:Q2F2jX0RYJUG3+WsM+FJknv+6eVjsjXNDV0KJXZzkD0=
|
github.com/mikelolasagasti/xz v1.0.1 h1:Q2F2jX0RYJUG3+WsM+FJknv+6eVjsjXNDV0KJXZzkD0=
|
||||||
@@ -245,8 +245,8 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
|||||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
github.com/nwaples/rardecode/v2 v2.1.1 h1:OJaYalXdliBUXPmC8CZGQ7oZDxzX1/5mQmgn0/GASew=
|
github.com/nwaples/rardecode/v2 v2.2.1 h1:DgHK/O/fkTQEKBJxBMC5d9IU8IgauifbpG78+rZJMnI=
|
||||||
github.com/nwaples/rardecode/v2 v2.1.1/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw=
|
github.com/nwaples/rardecode/v2 v2.2.1/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw=
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||||
@@ -266,17 +266,17 @@ github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UH
|
|||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||||
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
|
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||||
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
|
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||||
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
|
github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
|
||||||
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
|
github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
|
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
|
||||||
github.com/shirou/gopsutil/v4 v4.25.8 h1:NnAsw9lN7587WHxjJA9ryDnqhJpFH6A+wagYWTOH970=
|
github.com/shirou/gopsutil/v4 v4.25.10 h1:at8lk/5T1OgtuCp+AwrDofFRjnvosn0nkN2OLQ6g8tA=
|
||||||
github.com/shirou/gopsutil/v4 v4.25.8/go.mod h1:q9QdMmfAOVIw7a+eF86P7ISEU6ka+NLgkUxlopV4RwI=
|
github.com/shirou/gopsutil/v4 v4.25.10/go.mod h1:+kSwyC8DRUD9XXEHCAFjK+0nuArFJM0lva+StQAcskM=
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/sorairolake/lzip-go v0.3.8 h1:j5Q2313INdTA80ureWYRhX+1K78mUXfMoPZCw/ivWik=
|
github.com/sorairolake/lzip-go v0.3.8 h1:j5Q2313INdTA80ureWYRhX+1K78mUXfMoPZCw/ivWik=
|
||||||
@@ -302,12 +302,12 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
|
|||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
github.com/testcontainers/testcontainers-go v0.39.0 h1:uCUJ5tA+fcxbFAB0uP3pIK3EJ2IjjDUHFSZ1H1UxAts=
|
github.com/testcontainers/testcontainers-go v0.40.0 h1:pSdJYLOVgLE8YdUY2FHQ1Fxu+aMnb6JfVz1mxk7OeMU=
|
||||||
github.com/testcontainers/testcontainers-go v0.39.0/go.mod h1:qmHpkG7H5uPf/EvOORKvS6EuDkBUPE3zpVGaH9NL7f8=
|
github.com/testcontainers/testcontainers-go v0.40.0/go.mod h1:FSXV5KQtX2HAMlm7U3APNyLkkap35zNLxukw9oBi/MY=
|
||||||
github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4=
|
github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA=
|
||||||
github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4=
|
github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI=
|
||||||
github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso=
|
github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw=
|
||||||
github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ=
|
github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ=
|
||||||
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||||
github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY=
|
github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY=
|
||||||
github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||||
@@ -359,8 +359,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
|
|||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
|
golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU=
|
||||||
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
|
golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@@ -403,8 +403,8 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
|
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||||
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@@ -417,8 +417,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
||||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -442,13 +442,13 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||||
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
|
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
|
||||||
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
|
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@@ -456,12 +456,12 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
|||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
||||||
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI=
|
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
|
||||||
golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
@@ -529,8 +529,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
|
|||||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
|
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
|
||||||
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
|
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
|
||||||
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
|
||||||
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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 h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
|||||||
85
package-lock.json
generated
85
package-lock.json
generated
@@ -6,61 +6,31 @@
|
|||||||
"": {
|
"": {
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"prettier": "3.6.2",
|
"prettier": "3.6.2",
|
||||||
"prettier-plugin-gherkin": "^3.1.2",
|
"prettier-plugin-gherkin": "^3.1.3",
|
||||||
"prettier-plugin-sh": "^0.18.0"
|
"prettier-plugin-sh": "^0.18.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@cucumber/gherkin": {
|
"node_modules/@cucumber/gherkin": {
|
||||||
"version": "27.0.0",
|
"version": "32.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@cucumber/gherkin/-/gherkin-27.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@cucumber/gherkin/-/gherkin-32.2.0.tgz",
|
||||||
"integrity": "sha512-j5rCsjqzRiC3iVTier3sa0kzyNbkcAmF7xr7jKnyO7qDeK3Z8Ye1P3KSVpeQRMY+KCDJ3WbTDdyxH0FwfA/fIw==",
|
"integrity": "sha512-X8xuVhSIqlUjxSRifRJ7t0TycVWyX58fygJH3wDNmHINLg9sYEkvQT0SO2G5YlRZnYc11TIFr4YPenscvdlBIw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cucumber/messages": ">=19.1.4 <=22"
|
"@cucumber/messages": ">=19.1.4 <28"
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@cucumber/gherkin/node_modules/@cucumber/messages": {
|
|
||||||
"version": "22.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-22.0.0.tgz",
|
|
||||||
"integrity": "sha512-EuaUtYte9ilkxcKmfqGF9pJsHRUU0jwie5ukuZ/1NPTuHS1LxHPsGEODK17RPRbZHOFhqybNzG2rHAwThxEymg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/uuid": "9.0.1",
|
|
||||||
"class-transformer": "0.5.1",
|
|
||||||
"reflect-metadata": "0.1.13",
|
|
||||||
"uuid": "9.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@cucumber/gherkin/node_modules/@types/uuid": {
|
|
||||||
"version": "9.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.1.tgz",
|
|
||||||
"integrity": "sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/@cucumber/gherkin/node_modules/uuid": {
|
|
||||||
"version": "9.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
|
|
||||||
"integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"bin": {
|
|
||||||
"uuid": "dist/bin/uuid"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@cucumber/messages": {
|
"node_modules/@cucumber/messages": {
|
||||||
"version": "23.0.0",
|
"version": "27.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-23.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-27.2.0.tgz",
|
||||||
"integrity": "sha512-2ZWKNnikNMBnle3P3cgy+fgzhABrY4oBbiWp9wcI8ANdT4LlYRN6jQ6j/9CQGTDGRfkyRtr/5VkYq7q24XCsuA==",
|
"integrity": "sha512-f2o/HqKHgsqzFLdq6fAhfG1FNOQPdBdyMGpKwhb7hZqg0yZtx9BVqkTyuoNk83Fcvk3wjMVfouFXXHNEk4nddA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/uuid": "9.0.6",
|
"@types/uuid": "10.0.0",
|
||||||
"class-transformer": "0.5.1",
|
"class-transformer": "0.5.1",
|
||||||
"reflect-metadata": "0.1.13",
|
"reflect-metadata": "0.2.2",
|
||||||
"uuid": "9.0.1"
|
"uuid": "11.0.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@reteps/dockerfmt": {
|
"node_modules/@reteps/dockerfmt": {
|
||||||
@@ -74,9 +44,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/uuid": {
|
"node_modules/@types/uuid": {
|
||||||
"version": "9.0.6",
|
"version": "10.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
|
||||||
"integrity": "sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==",
|
"integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
@@ -93,6 +63,7 @@
|
|||||||
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
|
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"prettier": "bin/prettier.cjs"
|
"prettier": "bin/prettier.cjs"
|
||||||
},
|
},
|
||||||
@@ -104,15 +75,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/prettier-plugin-gherkin": {
|
"node_modules/prettier-plugin-gherkin": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/prettier-plugin-gherkin/-/prettier-plugin-gherkin-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/prettier-plugin-gherkin/-/prettier-plugin-gherkin-3.1.3.tgz",
|
||||||
"integrity": "sha512-LgehRNKCAqZsoE/yblmqXYfMpEK2mhVWQKNj/TFzeLR+0rhFGHqq3RlYcYhPgzbr0n6w2Bv+0Gm1yxNdzkdacw==",
|
"integrity": "sha512-w9uB413NlSi8ZQwpexyu+ttriJJ88eZLV0x88ZTkzkLZyHYEX5wrNtaCx/yFYviIu/tuwsBqDPM47VODnIV/hw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cucumber/gherkin": "^27.0.0",
|
"@cucumber/gherkin": "^32.0.0",
|
||||||
"@cucumber/messages": "^23.0.0",
|
"@cucumber/messages": "^27.2.0",
|
||||||
"prettier": "^3.0.0"
|
"prettier": "^3.5.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/prettier-plugin-sh": {
|
"node_modules/prettier-plugin-sh": {
|
||||||
@@ -136,9 +107,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/reflect-metadata": {
|
"node_modules/reflect-metadata": {
|
||||||
"version": "0.1.13",
|
"version": "0.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
|
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz",
|
||||||
"integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==",
|
"integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
@@ -166,9 +137,9 @@
|
|||||||
"license": "0BSD"
|
"license": "0BSD"
|
||||||
},
|
},
|
||||||
"node_modules/uuid": {
|
"node_modules/uuid": {
|
||||||
"version": "9.0.1",
|
"version": "11.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.5.tgz",
|
||||||
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
|
"integrity": "sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
"https://github.com/sponsors/broofa",
|
"https://github.com/sponsors/broofa",
|
||||||
@@ -176,7 +147,7 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
"uuid": "dist/bin/uuid"
|
"uuid": "dist/esm/bin/uuid"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"prettier": "3.6.2",
|
"prettier": "3.6.2",
|
||||||
"prettier-plugin-gherkin": "^3.1.2",
|
"prettier-plugin-gherkin": "^3.1.3",
|
||||||
"prettier-plugin-sh": "^0.18.0"
|
"prettier-plugin-sh": "^0.18.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ type PdfEngineMock struct {
|
|||||||
ReadMetadataMock func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error)
|
ReadMetadataMock func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error)
|
||||||
WriteMetadataMock func(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error
|
WriteMetadataMock func(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error
|
||||||
EncryptMock func(ctx context.Context, logger *zap.Logger, inputPath, userPassword, ownerPassword string) error
|
EncryptMock func(ctx context.Context, logger *zap.Logger, inputPath, userPassword, ownerPassword string) error
|
||||||
|
EmbedFilesMock func(ctx context.Context, logger *zap.Logger, filePaths []string, inputPath string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (engine *PdfEngineMock) Merge(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
|
func (engine *PdfEngineMock) Merge(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
|
||||||
@@ -83,6 +84,10 @@ func (engine *PdfEngineMock) Encrypt(ctx context.Context, logger *zap.Logger, in
|
|||||||
return engine.EncryptMock(ctx, logger, inputPath, userPassword, ownerPassword)
|
return engine.EncryptMock(ctx, logger, inputPath, userPassword, ownerPassword)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (engine *PdfEngineMock) EmbedFiles(ctx context.Context, logger *zap.Logger, filePaths []string, inputPath string) error {
|
||||||
|
return engine.EmbedFilesMock(ctx, logger, filePaths, inputPath)
|
||||||
|
}
|
||||||
|
|
||||||
// PdfEngineProviderMock is a mock for the [PdfEngineProvider] interface.
|
// PdfEngineProviderMock is a mock for the [PdfEngineProvider] interface.
|
||||||
type PdfEngineProviderMock struct {
|
type PdfEngineProviderMock struct {
|
||||||
PdfEngineMock func() (PdfEngine, error)
|
PdfEngineMock func() (PdfEngine, error)
|
||||||
|
|||||||
@@ -143,6 +143,10 @@ type PdfEngine interface {
|
|||||||
// The ownerPassword provides full access to the document.
|
// The ownerPassword provides full access to the document.
|
||||||
// If the ownerPassword is empty, it defaults to the userPassword.
|
// If the ownerPassword is empty, it defaults to the userPassword.
|
||||||
Encrypt(ctx context.Context, logger *zap.Logger, inputPath, userPassword, ownerPassword string) error
|
Encrypt(ctx context.Context, logger *zap.Logger, inputPath, userPassword, ownerPassword string) error
|
||||||
|
|
||||||
|
// EmbedFiles embeds files into a PDF. All files are embedded as file attachments
|
||||||
|
// without modifying the main PDF content.
|
||||||
|
EmbedFiles(ctx context.Context, logger *zap.Logger, filePaths []string, inputPath string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// PdfEngineProvider offers an interface to instantiate a [PdfEngine].
|
// PdfEngineProvider offers an interface to instantiate a [PdfEngine].
|
||||||
|
|||||||
@@ -38,11 +38,12 @@ var (
|
|||||||
|
|
||||||
// Context is the request context for a "multipart/form-data" requests.
|
// Context is the request context for a "multipart/form-data" requests.
|
||||||
type Context struct {
|
type Context struct {
|
||||||
dirPath string
|
dirPath string
|
||||||
values map[string][]string
|
values map[string][]string
|
||||||
files map[string]string
|
files map[string]string
|
||||||
outputPaths []string
|
filesByField map[string][]string
|
||||||
cancelled bool
|
outputPaths []string
|
||||||
|
cancelled bool
|
||||||
|
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
echoCtx echo.Context
|
echoCtx echo.Context
|
||||||
@@ -79,6 +80,9 @@ type downloadFrom struct {
|
|||||||
|
|
||||||
// ExtraHttpHeaders are the HTTP headers to send alongside.
|
// ExtraHttpHeaders are the HTTP headers to send alongside.
|
||||||
ExtraHttpHeaders map[string]string `json:"extraHttpHeaders"`
|
ExtraHttpHeaders map[string]string `json:"extraHttpHeaders"`
|
||||||
|
|
||||||
|
// Download as embed file
|
||||||
|
Embedded bool `json:"embedded"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// newContext returns a [Context] by parsing a "multipart/form-data" request.
|
// newContext returns a [Context] by parsing a "multipart/form-data" request.
|
||||||
@@ -184,6 +188,7 @@ func newContext(echoCtx echo.Context, logger *zap.Logger, fs *gotenberg.FileSyst
|
|||||||
ctx.dirPath = dirPath
|
ctx.dirPath = dirPath
|
||||||
ctx.values = form.Value
|
ctx.values = form.Value
|
||||||
ctx.files = make(map[string]string)
|
ctx.files = make(map[string]string)
|
||||||
|
ctx.filesByField = make(map[string][]string)
|
||||||
|
|
||||||
// First, try to download files listed in the "downloadFrom" form field, if
|
// First, try to download files listed in the "downloadFrom" form field, if
|
||||||
// any.
|
// any.
|
||||||
@@ -318,6 +323,9 @@ func newContext(echoCtx echo.Context, logger *zap.Logger, fs *gotenberg.FileSyst
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.files[filename] = path
|
ctx.files[filename] = path
|
||||||
|
if dl.Embedded {
|
||||||
|
ctx.filesByField[EmbedsFormField] = append(ctx.filesByField[EmbedsFormField], path)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@@ -373,17 +381,22 @@ func newContext(echoCtx echo.Context, logger *zap.Logger, fs *gotenberg.FileSyst
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Then, copy the form files, if any.
|
// Then, copy the form files, if any.
|
||||||
for _, files := range form.File {
|
for fieldName, files := range form.File {
|
||||||
for _, fh := range files {
|
for _, fh := range files {
|
||||||
err = copyToDisk(fh)
|
err = copyToDisk(fh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctx, cancel, fmt.Errorf("copy to disk: %w", err)
|
return ctx, cancel, fmt.Errorf("copy to disk: %w", err)
|
||||||
}
|
}
|
||||||
|
// Track files by field name
|
||||||
|
filename := norm.NFC.String(filepath.Base(fh.Filename))
|
||||||
|
filePath := ctx.files[filename]
|
||||||
|
ctx.filesByField[fieldName] = append(ctx.filesByField[fieldName], filePath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Log().Debug(fmt.Sprintf("form fields: %+v", ctx.values))
|
ctx.Log().Debug(fmt.Sprintf("form fields: %+v", ctx.values))
|
||||||
ctx.Log().Debug(fmt.Sprintf("form files: %+v", ctx.files))
|
ctx.Log().Debug(fmt.Sprintf("form files: %+v", ctx.files))
|
||||||
|
ctx.Log().Debug(fmt.Sprintf("form files by field: %+v", ctx.filesByField))
|
||||||
ctx.Log().Debug(fmt.Sprintf("total bytes: %d", totalBytesRead.Load()))
|
ctx.Log().Debug(fmt.Sprintf("total bytes: %d", totalBytesRead.Load()))
|
||||||
|
|
||||||
return ctx, cancel, err
|
return ctx, cancel, err
|
||||||
@@ -397,9 +410,10 @@ func (ctx *Context) Request() *http.Request {
|
|||||||
// FormData return a [FormData].
|
// FormData return a [FormData].
|
||||||
func (ctx *Context) FormData() *FormData {
|
func (ctx *Context) FormData() *FormData {
|
||||||
return &FormData{
|
return &FormData{
|
||||||
values: ctx.values,
|
values: ctx.values,
|
||||||
files: ctx.files,
|
files: ctx.files,
|
||||||
errors: nil,
|
filesByField: ctx.filesByField,
|
||||||
|
errors: nil,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -16,14 +17,20 @@ import (
|
|||||||
"github.com/gotenberg/gotenberg/v8/pkg/gotenberg"
|
"github.com/gotenberg/gotenberg/v8/pkg/gotenberg"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// EmbedsFormField represents the form field name for embedding files.
|
||||||
|
const (
|
||||||
|
EmbedsFormField string = "embeds"
|
||||||
|
)
|
||||||
|
|
||||||
// FormData is a helper for validating and hydrating values from a
|
// FormData is a helper for validating and hydrating values from a
|
||||||
// "multipart/form-data" request.
|
// "multipart/form-data" request.
|
||||||
//
|
//
|
||||||
// form := ctx.FormData()
|
// form := ctx.FormData()
|
||||||
type FormData struct {
|
type FormData struct {
|
||||||
values map[string][]string
|
values map[string][]string
|
||||||
files map[string]string
|
files map[string]string
|
||||||
errors error
|
filesByField map[string][]string
|
||||||
|
errors error
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
@@ -358,6 +365,26 @@ func (form *FormData) Paths(extensions []string, target *[]string) *FormData {
|
|||||||
return form.paths(extensions, target)
|
return form.paths(extensions, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Embeds binds the absolute paths of form data files that should be
|
||||||
|
// embedded in the PDF. Only files uploaded with the "embeds" field name
|
||||||
|
// will be included.
|
||||||
|
//
|
||||||
|
// var embeds []string
|
||||||
|
//
|
||||||
|
// ctx.FormData().Embeds(&embeds)
|
||||||
|
func (form *FormData) Embeds(target *[]string) *FormData {
|
||||||
|
if form.errors != nil {
|
||||||
|
return form
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get files from the "embeds" field
|
||||||
|
if paths, ok := form.filesByField[EmbedsFormField]; ok {
|
||||||
|
*target = append(*target, paths...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return form
|
||||||
|
}
|
||||||
|
|
||||||
// MandatoryPaths binds the absolute paths of form data files, according to a
|
// MandatoryPaths binds the absolute paths of form data files, according to a
|
||||||
// list of file extensions, to a string slice variable. It populates an error
|
// list of file extensions, to a string slice variable. It populates an error
|
||||||
// if there is no file for given file extensions.
|
// if there is no file for given file extensions.
|
||||||
@@ -381,8 +408,15 @@ func (form *FormData) MandatoryPaths(extensions []string, target *[]string) *For
|
|||||||
|
|
||||||
// paths bind 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.
|
||||||
|
// embeds are excluded.
|
||||||
func (form *FormData) paths(extensions []string, target *[]string) *FormData {
|
func (form *FormData) paths(extensions []string, target *[]string) *FormData {
|
||||||
|
embeds, ok := form.filesByField[EmbedsFormField]
|
||||||
|
|
||||||
for filename, path := range form.files {
|
for filename, path := range form.files {
|
||||||
|
if ok && slices.Contains(embeds, path) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
for _, ext := range extensions {
|
for _, ext := range extensions {
|
||||||
// See https://github.com/gotenberg/gotenberg/issues/228.
|
// See https://github.com/gotenberg/gotenberg/issues/228.
|
||||||
if strings.ToLower(filepath.Ext(filename)) == ext {
|
if strings.ToLower(filepath.Ext(filename)) == ext {
|
||||||
|
|||||||
@@ -1612,6 +1612,24 @@ func TestFormData_Paths(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expectCount: 2,
|
expectCount: 2,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
scenario: "files except embeds",
|
||||||
|
form: &FormData{
|
||||||
|
files: map[string]string{
|
||||||
|
"foo.pdf": "/foo.pdf",
|
||||||
|
"embed_1.pdf": "/embed_1.pdf",
|
||||||
|
"embed_2.xml": "/embed_2.xml",
|
||||||
|
},
|
||||||
|
filesByField: map[string][]string{
|
||||||
|
"embeds": {"/embed_1.pdf", "/embed_2.xml"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
extensions: []string{".pdf"},
|
||||||
|
expect: []string{
|
||||||
|
"/foo.pdf",
|
||||||
|
},
|
||||||
|
expectCount: 1,
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(tc.scenario, func(t *testing.T) {
|
t.Run(tc.scenario, func(t *testing.T) {
|
||||||
var actual []string
|
var actual []string
|
||||||
@@ -1740,3 +1758,28 @@ func TestFormData_mustAssign(t *testing.T) {
|
|||||||
var target []string
|
var target []string
|
||||||
form.mustAssign("foo", "foo", &target)
|
form.mustAssign("foo", "foo", &target)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFormData_Embeds(t *testing.T) {
|
||||||
|
expected := []string{"/bar.xml", "/baz.xml"}
|
||||||
|
|
||||||
|
var actual []string
|
||||||
|
form := &FormData{
|
||||||
|
files: map[string]string{
|
||||||
|
"foo.pdf": "/foo.pdf",
|
||||||
|
"bar.xml": "/bar.xml",
|
||||||
|
"baz.xml": "/baz.xml",
|
||||||
|
},
|
||||||
|
filesByField: map[string][]string{
|
||||||
|
"embeds": {"/bar.xml", "/baz.xml"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
form.Embeds(&actual)
|
||||||
|
|
||||||
|
if len(actual) != len(expected) {
|
||||||
|
t.Errorf("expected %d embeds but got %d", len(expected), len(actual))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, expected) {
|
||||||
|
t.Errorf("expected %v but got %v", expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ type browser interface {
|
|||||||
type browserArguments struct {
|
type browserArguments struct {
|
||||||
// Executor args.
|
// Executor args.
|
||||||
binPath string
|
binPath string
|
||||||
incognito bool
|
|
||||||
allowInsecureLocalhost bool
|
allowInsecureLocalhost bool
|
||||||
ignoreCertificateErrors bool
|
ignoreCertificateErrors bool
|
||||||
disableWebSecurity bool
|
disableWebSecurity bool
|
||||||
@@ -108,10 +107,6 @@ func (b *chromiumBrowser) Start(logger *zap.Logger) error {
|
|||||||
chromedp.Flag("disable-component-update", false),
|
chromedp.Flag("disable-component-update", false),
|
||||||
)
|
)
|
||||||
|
|
||||||
if b.arguments.incognito {
|
|
||||||
opts = append(opts, chromedp.Flag("incognito", b.arguments.incognito))
|
|
||||||
}
|
|
||||||
|
|
||||||
if b.arguments.allowInsecureLocalhost {
|
if b.arguments.allowInsecureLocalhost {
|
||||||
// See https://github.com/gotenberg/gotenberg/issues/488.
|
// See https://github.com/gotenberg/gotenberg/issues/488.
|
||||||
opts = append(opts, chromedp.Flag("allow-insecure-localhost", true))
|
opts = append(opts, chromedp.Flag("allow-insecure-localhost", true))
|
||||||
@@ -410,6 +405,10 @@ func (b *chromiumBrowser) do(ctx context.Context, logger *zap.Logger, url string
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
errMessage := err.Error()
|
errMessage := err.Error()
|
||||||
|
|
||||||
|
if strings.Contains(errMessage, "Printing failed (-32000)") {
|
||||||
|
return ErrPrintingFailed
|
||||||
|
}
|
||||||
|
|
||||||
if strings.Contains(errMessage, "Show invalid printer settings error (-32000)") || strings.Contains(errMessage, "content area is empty (-32602)") {
|
if strings.Contains(errMessage, "Show invalid printer settings error (-32000)") || strings.Contains(errMessage, "content area is empty (-32602)") {
|
||||||
return ErrInvalidPrinterSettings
|
return ErrInvalidPrinterSettings
|
||||||
}
|
}
|
||||||
@@ -418,6 +417,10 @@ func (b *chromiumBrowser) do(ctx context.Context, logger *zap.Logger, url string
|
|||||||
return ErrPageRangesSyntaxError
|
return ErrPageRangesSyntaxError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if strings.Contains(errMessage, "Page range exceeds page count (-32000)") {
|
||||||
|
return ErrPageRangesExceedsPageCount
|
||||||
|
}
|
||||||
|
|
||||||
if strings.Contains(errMessage, "rpcc: message too large") {
|
if strings.Contains(errMessage, "rpcc: message too large") {
|
||||||
return ErrRpccMessageTooLarge
|
return ErrRpccMessageTooLarge
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,13 +63,20 @@ var (
|
|||||||
// PdfOptions.OmitBackground is set to true but not PdfOptions.PrintBackground.
|
// PdfOptions.OmitBackground is set to true but not PdfOptions.PrintBackground.
|
||||||
ErrOmitBackgroundWithoutPrintBackground = errors.New("omit background without print background")
|
ErrOmitBackgroundWithoutPrintBackground = errors.New("omit background without print background")
|
||||||
|
|
||||||
|
// ErrPrintingFailed happens if the printing failed for an unknown reason.
|
||||||
|
ErrPrintingFailed = errors.New("printing failed")
|
||||||
|
|
||||||
// ErrInvalidPrinterSettings happens if the PdfOptions have one or more
|
// ErrInvalidPrinterSettings happens if the PdfOptions have one or more
|
||||||
// aberrant values.
|
// aberrant values.
|
||||||
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 page
|
||||||
// range.
|
// range syntax is invalid.
|
||||||
ErrPageRangesSyntaxError = errors.New("page ranges syntax error")
|
ErrPageRangesSyntaxError = errors.New("page ranges syntax error")
|
||||||
|
|
||||||
|
// ErrPageRangesExceedsPageCount happens if the PdfOptions have an invalid
|
||||||
|
// page range.
|
||||||
|
ErrPageRangesExceedsPageCount = errors.New("page ranges exceeds page count")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Chromium is a module that provides both an [Api] and routes for converting
|
// Chromium is a module that provides both an [Api] and routes for converting
|
||||||
@@ -364,7 +371,6 @@ func (mod *Chromium) Descriptor() gotenberg.ModuleDescriptor {
|
|||||||
fs.Int64("chromium-max-queue-size", 0, "Maximum request queue size for Chromium. Set to 0 to disable this feature")
|
fs.Int64("chromium-max-queue-size", 0, "Maximum request queue size for Chromium. Set to 0 to disable this feature")
|
||||||
fs.Bool("chromium-auto-start", false, "Automatically launch Chromium upon initialization if set to true; otherwise, Chromium will start at the time of the first conversion")
|
fs.Bool("chromium-auto-start", false, "Automatically launch Chromium upon initialization if set to true; otherwise, Chromium will start at the time of the first conversion")
|
||||||
fs.Duration("chromium-start-timeout", time.Duration(20)*time.Second, "Maximum duration to wait for Chromium to start or restart")
|
fs.Duration("chromium-start-timeout", time.Duration(20)*time.Second, "Maximum duration to wait for Chromium to start or restart")
|
||||||
fs.Bool("chromium-incognito", false, "Start Chromium with incognito mode")
|
|
||||||
fs.Bool("chromium-allow-insecure-localhost", false, "Ignore TLS/SSL errors on localhost")
|
fs.Bool("chromium-allow-insecure-localhost", false, "Ignore TLS/SSL errors on localhost")
|
||||||
fs.Bool("chromium-ignore-certificate-errors", false, "Ignore the certificate errors")
|
fs.Bool("chromium-ignore-certificate-errors", false, "Ignore the certificate errors")
|
||||||
fs.Bool("chromium-disable-web-security", false, "Don't enforce the same-origin policy")
|
fs.Bool("chromium-disable-web-security", false, "Don't enforce the same-origin policy")
|
||||||
@@ -378,6 +384,13 @@ func (mod *Chromium) Descriptor() gotenberg.ModuleDescriptor {
|
|||||||
fs.Bool("chromium-disable-javascript", false, "Disable JavaScript")
|
fs.Bool("chromium-disable-javascript", false, "Disable JavaScript")
|
||||||
fs.Bool("chromium-disable-routes", false, "Disable the routes")
|
fs.Bool("chromium-disable-routes", false, "Disable the routes")
|
||||||
|
|
||||||
|
// Deprecated flags.
|
||||||
|
fs.Bool("chromium-incognito", false, "Start Chromium with incognito mode")
|
||||||
|
err := fs.MarkDeprecated("chromium-incognito", "this flag is ignored as it provides no benefits")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
return fs
|
return fs
|
||||||
}(),
|
}(),
|
||||||
New: func() gotenberg.Module { return new(Chromium) },
|
New: func() gotenberg.Module { return new(Chromium) },
|
||||||
@@ -402,7 +415,6 @@ func (mod *Chromium) Provision(ctx *gotenberg.Context) error {
|
|||||||
|
|
||||||
mod.args = browserArguments{
|
mod.args = browserArguments{
|
||||||
binPath: binPath,
|
binPath: binPath,
|
||||||
incognito: flags.MustBool("chromium-incognito"),
|
|
||||||
allowInsecureLocalhost: flags.MustBool("chromium-allow-insecure-localhost"),
|
allowInsecureLocalhost: flags.MustBool("chromium-allow-insecure-localhost"),
|
||||||
ignoreCertificateErrors: flags.MustBool("chromium-ignore-certificate-errors"),
|
ignoreCertificateErrors: flags.MustBool("chromium-ignore-certificate-errors"),
|
||||||
disableWebSecurity: flags.MustBool("chromium-disable-web-security"),
|
disableWebSecurity: flags.MustBool("chromium-disable-web-security"),
|
||||||
|
|||||||
@@ -24,6 +24,11 @@ import (
|
|||||||
"github.com/gotenberg/gotenberg/v8/pkg/modules/pdfengines"
|
"github.com/gotenberg/gotenberg/v8/pkg/modules/pdfengines"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var sameSiteRegexp = regexp2.MustCompile(
|
||||||
|
`("sameSite"\s*:\s*")(?i:(lax|strict|none))(")`,
|
||||||
|
regexp2.None,
|
||||||
|
)
|
||||||
|
|
||||||
// FormDataChromiumOptions creates [Options] from the form data. Fallback to
|
// FormDataChromiumOptions creates [Options] from the form data. Fallback to
|
||||||
// the 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) {
|
||||||
@@ -84,7 +89,30 @@ func FormDataChromiumOptions(ctx *api.Context) (*api.FormData, Options) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err := json.Unmarshal([]byte(value), &cookies)
|
// sameSite attribute from cookies must accept case-insensitive
|
||||||
|
// values.
|
||||||
|
// See https://github.com/gotenberg/gotenberg/issues/1331.
|
||||||
|
normalized, err := sameSiteRegexp.ReplaceFunc(value, func(m regexp2.Match) string {
|
||||||
|
groups := m.Groups()
|
||||||
|
provided := groups[2].String()
|
||||||
|
var canon string
|
||||||
|
switch strings.ToLower(provided) {
|
||||||
|
case "lax":
|
||||||
|
canon = "Lax"
|
||||||
|
case "strict":
|
||||||
|
canon = "Strict"
|
||||||
|
case "none":
|
||||||
|
canon = "None"
|
||||||
|
default:
|
||||||
|
canon = provided
|
||||||
|
}
|
||||||
|
return groups[1].String() + canon + groups[3].String()
|
||||||
|
}, -1, -1)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("normalize sameSite from cookies: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal([]byte(normalized), &cookies)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unmarshal cookies: %w", err)
|
return fmt.Errorf("unmarshal cookies: %w", err)
|
||||||
}
|
}
|
||||||
@@ -141,7 +169,7 @@ func FormDataChromiumOptions(ctx *api.Context) (*api.FormData, Options) {
|
|||||||
|
|
||||||
var scopeRegexp *regexp2.Regexp
|
var scopeRegexp *regexp2.Regexp
|
||||||
if len(scope) > 0 {
|
if len(scope) > 0 {
|
||||||
p, errCompile := regexp2.Compile(scope, 0)
|
p, errCompile := regexp2.Compile(scope, regexp2.None)
|
||||||
if errCompile != nil {
|
if errCompile != nil {
|
||||||
err = multierr.Append(err, fmt.Errorf("invalid scope regex pattern for header '%s': %w", k, errCompile))
|
err = multierr.Append(err, fmt.Errorf("invalid scope regex pattern for header '%s': %w", k, errCompile))
|
||||||
continue
|
continue
|
||||||
@@ -333,6 +361,7 @@ func convertUrlRoute(chromium Api, engine gotenberg.PdfEngine) api.Route {
|
|||||||
pdfFormats := pdfengines.FormDataPdfFormats(form)
|
pdfFormats := pdfengines.FormDataPdfFormats(form)
|
||||||
metadata := pdfengines.FormDataPdfMetadata(form, false)
|
metadata := pdfengines.FormDataPdfMetadata(form, false)
|
||||||
userPassword, ownerPassword := pdfengines.FormDataPdfEncrypt(form)
|
userPassword, ownerPassword := pdfengines.FormDataPdfEncrypt(form)
|
||||||
|
embedPaths := pdfengines.FormDataPdfEmbeds(form)
|
||||||
|
|
||||||
var url string
|
var url string
|
||||||
err := form.
|
err := form.
|
||||||
@@ -342,7 +371,7 @@ func convertUrlRoute(chromium Api, engine gotenberg.PdfEngine) api.Route {
|
|||||||
return fmt.Errorf("validate form data: %w", err)
|
return fmt.Errorf("validate form data: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = convertUrl(ctx, chromium, engine, url, options, mode, pdfFormats, metadata, userPassword, ownerPassword)
|
err = convertUrl(ctx, chromium, engine, url, options, mode, pdfFormats, metadata, userPassword, ownerPassword, embedPaths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("convert URL to PDF: %w", err)
|
return fmt.Errorf("convert URL to PDF: %w", err)
|
||||||
}
|
}
|
||||||
@@ -395,6 +424,7 @@ func convertHtmlRoute(chromium Api, engine gotenberg.PdfEngine) api.Route {
|
|||||||
pdfFormats := pdfengines.FormDataPdfFormats(form)
|
pdfFormats := pdfengines.FormDataPdfFormats(form)
|
||||||
metadata := pdfengines.FormDataPdfMetadata(form, false)
|
metadata := pdfengines.FormDataPdfMetadata(form, false)
|
||||||
userPassword, ownerPassword := pdfengines.FormDataPdfEncrypt(form)
|
userPassword, ownerPassword := pdfengines.FormDataPdfEncrypt(form)
|
||||||
|
embedPaths := pdfengines.FormDataPdfEmbeds(form)
|
||||||
|
|
||||||
var inputPath string
|
var inputPath string
|
||||||
err := form.
|
err := form.
|
||||||
@@ -405,7 +435,7 @@ func convertHtmlRoute(chromium Api, engine gotenberg.PdfEngine) api.Route {
|
|||||||
}
|
}
|
||||||
|
|
||||||
url := fmt.Sprintf("file://%s", inputPath)
|
url := fmt.Sprintf("file://%s", inputPath)
|
||||||
err = convertUrl(ctx, chromium, engine, url, options, mode, pdfFormats, metadata, userPassword, ownerPassword)
|
err = convertUrl(ctx, chromium, engine, url, options, mode, pdfFormats, metadata, userPassword, ownerPassword, embedPaths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("convert HTML to PDF: %w", err)
|
return fmt.Errorf("convert HTML to PDF: %w", err)
|
||||||
}
|
}
|
||||||
@@ -459,6 +489,7 @@ func convertMarkdownRoute(chromium Api, engine gotenberg.PdfEngine) api.Route {
|
|||||||
pdfFormats := pdfengines.FormDataPdfFormats(form)
|
pdfFormats := pdfengines.FormDataPdfFormats(form)
|
||||||
metadata := pdfengines.FormDataPdfMetadata(form, false)
|
metadata := pdfengines.FormDataPdfMetadata(form, false)
|
||||||
userPassword, ownerPassword := pdfengines.FormDataPdfEncrypt(form)
|
userPassword, ownerPassword := pdfengines.FormDataPdfEncrypt(form)
|
||||||
|
embedPaths := pdfengines.FormDataPdfEmbeds(form)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
inputPath string
|
inputPath string
|
||||||
@@ -478,7 +509,7 @@ func convertMarkdownRoute(chromium Api, engine gotenberg.PdfEngine) api.Route {
|
|||||||
return fmt.Errorf("transform markdown file(s) to HTML: %w", err)
|
return fmt.Errorf("transform markdown file(s) to HTML: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = convertUrl(ctx, chromium, engine, url, options, mode, pdfFormats, metadata, userPassword, ownerPassword)
|
err = convertUrl(ctx, chromium, engine, url, options, mode, pdfFormats, metadata, userPassword, ownerPassword, embedPaths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("convert markdown to PDF: %w", err)
|
return fmt.Errorf("convert markdown to PDF: %w", err)
|
||||||
}
|
}
|
||||||
@@ -602,7 +633,7 @@ func markdownToHtml(ctx *api.Context, inputPath string, markdownPaths []string)
|
|||||||
return fmt.Sprintf("file://%s", inputPath), nil
|
return fmt.Sprintf("file://%s", inputPath), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertUrl(ctx *api.Context, chromium Api, engine gotenberg.PdfEngine, url string, options PdfOptions, mode gotenberg.SplitMode, pdfFormats gotenberg.PdfFormats, metadata map[string]interface{}, userPassword, ownerPassword string) error {
|
func convertUrl(ctx *api.Context, chromium Api, engine gotenberg.PdfEngine, url string, options PdfOptions, mode gotenberg.SplitMode, pdfFormats gotenberg.PdfFormats, metadata map[string]interface{}, userPassword, ownerPassword string, embedPaths []string) error {
|
||||||
outputPath := ctx.GeneratePath(".pdf")
|
outputPath := ctx.GeneratePath(".pdf")
|
||||||
// See https://github.com/gotenberg/gotenberg/issues/1130.
|
// See https://github.com/gotenberg/gotenberg/issues/1130.
|
||||||
filename := ctx.OutputFilename(outputPath)
|
filename := ctx.OutputFilename(outputPath)
|
||||||
@@ -621,6 +652,16 @@ func convertUrl(ctx *api.Context, chromium Api, engine gotenberg.PdfEngine, url
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if errors.Is(err, ErrPrintingFailed) {
|
||||||
|
return api.WrapError(
|
||||||
|
fmt.Errorf("convert to PDF: %w", err),
|
||||||
|
api.NewSentinelHttpError(
|
||||||
|
http.StatusBadRequest,
|
||||||
|
"Chromium failed to print the PDF; this usually happens when the page is too large",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if errors.Is(err, ErrInvalidPrinterSettings) {
|
if errors.Is(err, ErrInvalidPrinterSettings) {
|
||||||
return api.WrapError(
|
return api.WrapError(
|
||||||
fmt.Errorf("convert to PDF: %w", err),
|
fmt.Errorf("convert to PDF: %w", err),
|
||||||
@@ -631,12 +672,22 @@ func convertUrl(ctx *api.Context, chromium Api, engine gotenberg.PdfEngine, url
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if errors.Is(err, ErrPageRangesExceedsPageCount) {
|
||||||
|
return api.WrapError(
|
||||||
|
fmt.Errorf("convert to PDF: %w", err),
|
||||||
|
api.NewSentinelHttpError(
|
||||||
|
http.StatusBadRequest,
|
||||||
|
fmt.Sprintf("The page ranges '%s' (nativePageRanges) exceeds the page count", options.PageRanges),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if errors.Is(err, ErrPageRangesSyntaxError) {
|
if errors.Is(err, ErrPageRangesSyntaxError) {
|
||||||
return api.WrapError(
|
return api.WrapError(
|
||||||
fmt.Errorf("convert to PDF: %w", err),
|
fmt.Errorf("convert to PDF: %w", err),
|
||||||
api.NewSentinelHttpError(
|
api.NewSentinelHttpError(
|
||||||
http.StatusBadRequest,
|
http.StatusBadRequest,
|
||||||
fmt.Sprintf("Chromium does not handle the page ranges '%s' (nativePageRanges)", options.PageRanges),
|
fmt.Sprintf("Chromium does not handle the page ranges '%s' (nativePageRanges) syntax", options.PageRanges),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -654,6 +705,11 @@ func convertUrl(ctx *api.Context, chromium Api, engine gotenberg.PdfEngine, url
|
|||||||
return fmt.Errorf("convert PDF(s): %w", err)
|
return fmt.Errorf("convert PDF(s): %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = pdfengines.EmbedFilesStub(ctx, engine, embedPaths, convertOutputPaths)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("embed files into PDFs: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
err = pdfengines.WriteMetadataStub(ctx, engine, metadata, convertOutputPaths)
|
err = pdfengines.WriteMetadataStub(ctx, engine, metadata, convertOutputPaths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("write metadata: %w", err)
|
return fmt.Errorf("write metadata: %w", err)
|
||||||
|
|||||||
@@ -181,6 +181,11 @@ func (engine *ExifTool) Encrypt(ctx context.Context, logger *zap.Logger, inputPa
|
|||||||
return fmt.Errorf("encrypt PDF using ExifTool: %w", gotenberg.ErrPdfEncryptionNotSupported)
|
return fmt.Errorf("encrypt PDF using ExifTool: %w", gotenberg.ErrPdfEncryptionNotSupported)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EmbedFiles is not available in this implementation.
|
||||||
|
func (engine *ExifTool) EmbedFiles(ctx context.Context, logger *zap.Logger, filePaths []string, inputPath string) error {
|
||||||
|
return fmt.Errorf("embed files with ExifTool: %w", gotenberg.ErrPdfEngineMethodNotSupported)
|
||||||
|
}
|
||||||
|
|
||||||
// Interface guards.
|
// Interface guards.
|
||||||
var (
|
var (
|
||||||
_ gotenberg.Module = (*ExifTool)(nil)
|
_ gotenberg.Module = (*ExifTool)(nil)
|
||||||
|
|||||||
@@ -96,6 +96,11 @@ func (engine *LibreOfficePdfEngine) Encrypt(ctx context.Context, logger *zap.Log
|
|||||||
return fmt.Errorf("encrypt PDF using LibreOffice: %w", gotenberg.ErrPdfEngineMethodNotSupported)
|
return fmt.Errorf("encrypt PDF using LibreOffice: %w", gotenberg.ErrPdfEngineMethodNotSupported)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EmbedFiles is not available in this implementation.
|
||||||
|
func (engine *LibreOfficePdfEngine) EmbedFiles(ctx context.Context, logger *zap.Logger, filePaths []string, inputPath string) error {
|
||||||
|
return fmt.Errorf("embed files with LibreOffice: %w", gotenberg.ErrPdfEngineMethodNotSupported)
|
||||||
|
}
|
||||||
|
|
||||||
// Interface guards.
|
// Interface guards.
|
||||||
var (
|
var (
|
||||||
_ gotenberg.Module = (*LibreOfficePdfEngine)(nil)
|
_ gotenberg.Module = (*LibreOfficePdfEngine)(nil)
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap
|
|||||||
pdfFormats := pdfengines.FormDataPdfFormats(form)
|
pdfFormats := pdfengines.FormDataPdfFormats(form)
|
||||||
metadata := pdfengines.FormDataPdfMetadata(form, false)
|
metadata := pdfengines.FormDataPdfMetadata(form, false)
|
||||||
userPassword, ownerPassword := pdfengines.FormDataPdfEncrypt(form)
|
userPassword, ownerPassword := pdfengines.FormDataPdfEncrypt(form)
|
||||||
|
embedPaths := pdfengines.FormDataPdfEmbeds(form)
|
||||||
|
|
||||||
zeroValuedSplitMode := gotenberg.SplitMode{}
|
zeroValuedSplitMode := gotenberg.SplitMode{}
|
||||||
|
|
||||||
@@ -252,6 +253,11 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = pdfengines.EmbedFilesStub(ctx, engine, embedPaths, outputPaths)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("embed files into PDFs: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
err = pdfengines.WriteMetadataStub(ctx, engine, metadata, outputPaths)
|
err = pdfengines.WriteMetadataStub(ctx, engine, metadata, outputPaths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("write metadata: %w", err)
|
return fmt.Errorf("write metadata: %w", err)
|
||||||
|
|||||||
@@ -171,6 +171,34 @@ func (engine *PdfCpu) WriteMetadata(ctx context.Context, logger *zap.Logger, met
|
|||||||
return fmt.Errorf("write PDF metadata with pdfcpu: %w", gotenberg.ErrPdfEngineMethodNotSupported)
|
return fmt.Errorf("write PDF metadata with pdfcpu: %w", gotenberg.ErrPdfEngineMethodNotSupported)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EmbedFiles embeds files into a PDF. All files are embedded as file attachments
|
||||||
|
// without modifying the main PDF content.
|
||||||
|
func (engine *PdfCpu) EmbedFiles(ctx context.Context, logger *zap.Logger, filePaths []string, inputPath string) error {
|
||||||
|
if len(filePaths) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Debug(fmt.Sprintf("embedding %d file(s) to %s: %v", len(filePaths), inputPath, filePaths))
|
||||||
|
|
||||||
|
args := []string{
|
||||||
|
"attachments", "add",
|
||||||
|
inputPath,
|
||||||
|
}
|
||||||
|
args = append(args, filePaths...)
|
||||||
|
|
||||||
|
cmd, err := gotenberg.CommandContext(ctx, logger, engine.binPath, args...)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("create command for attaching files: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = cmd.Exec()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("attach files with pdfcpu: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Encrypt adds password protection to a PDF file using pdfcpu.
|
// Encrypt adds password protection to a PDF file using pdfcpu.
|
||||||
func (engine *PdfCpu) Encrypt(ctx context.Context, logger *zap.Logger, inputPath, userPassword, ownerPassword string) error {
|
func (engine *PdfCpu) Encrypt(ctx context.Context, logger *zap.Logger, inputPath, userPassword, ownerPassword string) error {
|
||||||
if userPassword == "" {
|
if userPassword == "" {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ type multiPdfEngines struct {
|
|||||||
readMetadataEngines []gotenberg.PdfEngine
|
readMetadataEngines []gotenberg.PdfEngine
|
||||||
writeMetadataEngines []gotenberg.PdfEngine
|
writeMetadataEngines []gotenberg.PdfEngine
|
||||||
passwordEngines []gotenberg.PdfEngine
|
passwordEngines []gotenberg.PdfEngine
|
||||||
|
embedEngines []gotenberg.PdfEngine
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMultiPdfEngines(
|
func newMultiPdfEngines(
|
||||||
@@ -28,7 +29,8 @@ func newMultiPdfEngines(
|
|||||||
convertEngines,
|
convertEngines,
|
||||||
readMetadataEngines,
|
readMetadataEngines,
|
||||||
writeMetadataEngines,
|
writeMetadataEngines,
|
||||||
passwordEngines []gotenberg.PdfEngine,
|
passwordEngines,
|
||||||
|
embedEngines []gotenberg.PdfEngine,
|
||||||
) *multiPdfEngines {
|
) *multiPdfEngines {
|
||||||
return &multiPdfEngines{
|
return &multiPdfEngines{
|
||||||
mergeEngines: mergeEngines,
|
mergeEngines: mergeEngines,
|
||||||
@@ -38,6 +40,7 @@ func newMultiPdfEngines(
|
|||||||
readMetadataEngines: readMetadataEngines,
|
readMetadataEngines: readMetadataEngines,
|
||||||
writeMetadataEngines: writeMetadataEngines,
|
writeMetadataEngines: writeMetadataEngines,
|
||||||
passwordEngines: passwordEngines,
|
passwordEngines: passwordEngines,
|
||||||
|
embedEngines: embedEngines,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,6 +241,31 @@ func (multi *multiPdfEngines) Encrypt(ctx context.Context, logger *zap.Logger, i
|
|||||||
return fmt.Errorf("encrypt PDF using multi PDF engines: %w", err)
|
return fmt.Errorf("encrypt PDF using multi PDF engines: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EmbedFiles embeds files into a PDF using the first available
|
||||||
|
// engine that supports file embedding.
|
||||||
|
func (multi *multiPdfEngines) EmbedFiles(ctx context.Context, logger *zap.Logger, filePaths []string, inputPath string) error {
|
||||||
|
var err error
|
||||||
|
errChan := make(chan error, 1)
|
||||||
|
|
||||||
|
for _, engine := range multi.embedEngines {
|
||||||
|
go func(engine gotenberg.PdfEngine) {
|
||||||
|
errChan <- engine.EmbedFiles(ctx, logger, filePaths, inputPath)
|
||||||
|
}(engine)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case embedErr := <-errChan:
|
||||||
|
errored := multierr.AppendInto(&err, embedErr)
|
||||||
|
if !errored {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("embed files into PDF using multi PDF engines: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Interface guards.
|
// Interface guards.
|
||||||
var (
|
var (
|
||||||
_ gotenberg.PdfEngine = (*multiPdfEngines)(nil)
|
_ gotenberg.PdfEngine = (*multiPdfEngines)(nil)
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ type PdfEngines struct {
|
|||||||
readMetadataNames []string
|
readMetadataNames []string
|
||||||
writeMetadataNames []string
|
writeMetadataNames []string
|
||||||
encryptNames []string
|
encryptNames []string
|
||||||
|
embedNames []string
|
||||||
engines []gotenberg.PdfEngine
|
engines []gotenberg.PdfEngine
|
||||||
disableRoutes bool
|
disableRoutes bool
|
||||||
}
|
}
|
||||||
@@ -51,6 +52,7 @@ func (mod *PdfEngines) Descriptor() gotenberg.ModuleDescriptor {
|
|||||||
fs.StringSlice("pdfengines-read-metadata-engines", []string{"exiftool"}, "Set the PDF engines and their order for the read metadata feature - empty means all")
|
fs.StringSlice("pdfengines-read-metadata-engines", []string{"exiftool"}, "Set the PDF engines and their order for the read metadata feature - empty means all")
|
||||||
fs.StringSlice("pdfengines-write-metadata-engines", []string{"exiftool"}, "Set the PDF engines and their order for the write metadata feature - empty means all")
|
fs.StringSlice("pdfengines-write-metadata-engines", []string{"exiftool"}, "Set the PDF engines and their order for the write metadata feature - empty means all")
|
||||||
fs.StringSlice("pdfengines-encrypt-engines", []string{"qpdf", "pdftk", "pdfcpu"}, "Set the PDF engines and their order for the password protection feature - empty means all")
|
fs.StringSlice("pdfengines-encrypt-engines", []string{"qpdf", "pdftk", "pdfcpu"}, "Set the PDF engines and their order for the password protection feature - empty means all")
|
||||||
|
fs.StringSlice("pdfengines-embed-engines", []string{"pdfcpu"}, "Set the PDF engines and their order for the file embedding feature - empty means all")
|
||||||
fs.Bool("pdfengines-disable-routes", false, "Disable the routes")
|
fs.Bool("pdfengines-disable-routes", false, "Disable the routes")
|
||||||
|
|
||||||
// Deprecated flags.
|
// Deprecated flags.
|
||||||
@@ -77,6 +79,7 @@ func (mod *PdfEngines) Provision(ctx *gotenberg.Context) error {
|
|||||||
readMetadataNames := flags.MustStringSlice("pdfengines-read-metadata-engines")
|
readMetadataNames := flags.MustStringSlice("pdfengines-read-metadata-engines")
|
||||||
writeMetadataNames := flags.MustStringSlice("pdfengines-write-metadata-engines")
|
writeMetadataNames := flags.MustStringSlice("pdfengines-write-metadata-engines")
|
||||||
encryptNames := flags.MustStringSlice("pdfengines-encrypt-engines")
|
encryptNames := flags.MustStringSlice("pdfengines-encrypt-engines")
|
||||||
|
embedNames := flags.MustStringSlice("pdfengines-embed-engines")
|
||||||
mod.disableRoutes = flags.MustBool("pdfengines-disable-routes")
|
mod.disableRoutes = flags.MustBool("pdfengines-disable-routes")
|
||||||
|
|
||||||
engines, err := ctx.Modules(new(gotenberg.PdfEngine))
|
engines, err := ctx.Modules(new(gotenberg.PdfEngine))
|
||||||
@@ -138,6 +141,11 @@ func (mod *PdfEngines) Provision(ctx *gotenberg.Context) error {
|
|||||||
mod.encryptNames = encryptNames
|
mod.encryptNames = encryptNames
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod.embedNames = defaultNames
|
||||||
|
if len(embedNames) > 0 {
|
||||||
|
mod.embedNames = embedNames
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,6 +200,7 @@ func (mod *PdfEngines) Validate() error {
|
|||||||
findNonExistingEngines(mod.readMetadataNames)
|
findNonExistingEngines(mod.readMetadataNames)
|
||||||
findNonExistingEngines(mod.writeMetadataNames)
|
findNonExistingEngines(mod.writeMetadataNames)
|
||||||
findNonExistingEngines(mod.encryptNames)
|
findNonExistingEngines(mod.encryptNames)
|
||||||
|
findNonExistingEngines(mod.embedNames)
|
||||||
|
|
||||||
if len(nonExistingEngines) == 0 {
|
if len(nonExistingEngines) == 0 {
|
||||||
return nil
|
return nil
|
||||||
@@ -238,6 +247,7 @@ func (mod *PdfEngines) PdfEngine() (gotenberg.PdfEngine, error) {
|
|||||||
engines(mod.readMetadataNames),
|
engines(mod.readMetadataNames),
|
||||||
engines(mod.writeMetadataNames),
|
engines(mod.writeMetadataNames),
|
||||||
engines(mod.encryptNames),
|
engines(mod.encryptNames),
|
||||||
|
engines(mod.embedNames),
|
||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,6 +272,7 @@ func (mod *PdfEngines) Routes() ([]api.Route, error) {
|
|||||||
readMetadataRoute(engine),
|
readMetadataRoute(engine),
|
||||||
writeMetadataRoute(engine),
|
writeMetadataRoute(engine),
|
||||||
encryptRoute(engine),
|
encryptRoute(engine),
|
||||||
|
embedRoute(engine),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -254,6 +254,14 @@ func WriteMetadataStub(ctx *api.Context, engine gotenberg.PdfEngine, metadata ma
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FormDataPdfEmbeds extracts embedded file paths from form data.
|
||||||
|
// Only files uploaded with the "embeds" field name are included.
|
||||||
|
func FormDataPdfEmbeds(form *api.FormData) []string {
|
||||||
|
var embedPaths []string
|
||||||
|
form.Embeds(&embedPaths)
|
||||||
|
return embedPaths
|
||||||
|
}
|
||||||
|
|
||||||
// FormDataPdfEncrypt extracts encryption parameters from form data.
|
// FormDataPdfEncrypt extracts encryption parameters from form data.
|
||||||
func FormDataPdfEncrypt(form *api.FormData) (userPassword, ownerPassword string) {
|
func FormDataPdfEncrypt(form *api.FormData) (userPassword, ownerPassword string) {
|
||||||
form.String("userPassword", &userPassword, "")
|
form.String("userPassword", &userPassword, "")
|
||||||
@@ -277,6 +285,22 @@ func EncryptPdfStub(ctx *api.Context, engine gotenberg.PdfEngine, userPassword,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EmbedFilesStub embeds files into PDF files.
|
||||||
|
func EmbedFilesStub(ctx *api.Context, engine gotenberg.PdfEngine, embedPaths []string, inputPaths []string) error {
|
||||||
|
if len(embedPaths) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, inputPath := range inputPaths {
|
||||||
|
err := engine.EmbedFiles(ctx, ctx.Log(), embedPaths, inputPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("embed files into PDF '%s': %w", inputPath, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// mergeRoute returns an [api.Route] which can merge PDFs.
|
// mergeRoute returns an [api.Route] which can merge PDFs.
|
||||||
func mergeRoute(engine gotenberg.PdfEngine) api.Route {
|
func mergeRoute(engine gotenberg.PdfEngine) api.Route {
|
||||||
return api.Route{
|
return api.Route{
|
||||||
@@ -290,6 +314,7 @@ func mergeRoute(engine gotenberg.PdfEngine) api.Route {
|
|||||||
pdfFormats := FormDataPdfFormats(form)
|
pdfFormats := FormDataPdfFormats(form)
|
||||||
metadata := FormDataPdfMetadata(form, false)
|
metadata := FormDataPdfMetadata(form, false)
|
||||||
userPassword, ownerPassword := FormDataPdfEncrypt(form)
|
userPassword, ownerPassword := FormDataPdfEncrypt(form)
|
||||||
|
embedPaths := FormDataPdfEmbeds(form)
|
||||||
|
|
||||||
var inputPaths []string
|
var inputPaths []string
|
||||||
var flatten bool
|
var flatten bool
|
||||||
@@ -312,6 +337,11 @@ func mergeRoute(engine gotenberg.PdfEngine) api.Route {
|
|||||||
return fmt.Errorf("convert PDF: %w", err)
|
return fmt.Errorf("convert PDF: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = EmbedFilesStub(ctx, engine, embedPaths, outputPaths)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("embed files into PDFs: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
err = WriteMetadataStub(ctx, engine, metadata, outputPaths)
|
err = WriteMetadataStub(ctx, engine, metadata, outputPaths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("write metadata: %w", err)
|
return fmt.Errorf("write metadata: %w", err)
|
||||||
@@ -353,6 +383,7 @@ func splitRoute(engine gotenberg.PdfEngine) api.Route {
|
|||||||
pdfFormats := FormDataPdfFormats(form)
|
pdfFormats := FormDataPdfFormats(form)
|
||||||
metadata := FormDataPdfMetadata(form, false)
|
metadata := FormDataPdfMetadata(form, false)
|
||||||
userPassword, ownerPassword := FormDataPdfEncrypt(form)
|
userPassword, ownerPassword := FormDataPdfEncrypt(form)
|
||||||
|
embedPaths := FormDataPdfEmbeds(form)
|
||||||
|
|
||||||
var inputPaths []string
|
var inputPaths []string
|
||||||
var flatten bool
|
var flatten bool
|
||||||
@@ -374,6 +405,11 @@ func splitRoute(engine gotenberg.PdfEngine) api.Route {
|
|||||||
return fmt.Errorf("convert PDFs: %w", err)
|
return fmt.Errorf("convert PDFs: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = EmbedFilesStub(ctx, engine, embedPaths, convertOutputPaths)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("embed files into PDFs: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
err = WriteMetadataStub(ctx, engine, metadata, convertOutputPaths)
|
err = WriteMetadataStub(ctx, engine, metadata, convertOutputPaths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("write metadata: %w", err)
|
return fmt.Errorf("write metadata: %w", err)
|
||||||
@@ -620,3 +656,38 @@ func encryptRoute(engine gotenberg.PdfEngine) api.Route {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// embedRoute returns an [api.Route] which can add embedded files to PDFs.
|
||||||
|
func embedRoute(engine gotenberg.PdfEngine) api.Route {
|
||||||
|
return api.Route{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/forms/pdfengines/embed",
|
||||||
|
IsMultipart: true,
|
||||||
|
Handler: func(c echo.Context) error {
|
||||||
|
ctx := c.Get("context").(*api.Context)
|
||||||
|
|
||||||
|
form := ctx.FormData()
|
||||||
|
embedPaths := FormDataPdfEmbeds(form)
|
||||||
|
|
||||||
|
var inputPaths []string
|
||||||
|
err := form.
|
||||||
|
MandatoryPaths([]string{".pdf"}, &inputPaths).
|
||||||
|
Validate()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("validate form data: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = EmbedFilesStub(ctx, engine, embedPaths, inputPaths)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("embed files into PDFs: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ctx.AddOutputPaths(inputPaths...)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("add output paths: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -183,6 +183,11 @@ func (engine *PdfTk) Encrypt(ctx context.Context, logger *zap.Logger, inputPath,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EmbedFiles is not available in this implementation.
|
||||||
|
func (engine *PdfTk) EmbedFiles(ctx context.Context, logger *zap.Logger, filePaths []string, inputPath string) error {
|
||||||
|
return fmt.Errorf("embed files with PDFtk: %w", gotenberg.ErrPdfEngineMethodNotSupported)
|
||||||
|
}
|
||||||
|
|
||||||
// Interface guards.
|
// Interface guards.
|
||||||
var (
|
var (
|
||||||
_ gotenberg.Module = (*PdfTk)(nil)
|
_ gotenberg.Module = (*PdfTk)(nil)
|
||||||
|
|||||||
@@ -201,6 +201,11 @@ func (engine *QPdf) Encrypt(ctx context.Context, logger *zap.Logger, inputPath,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EmbedFiles is not available in this implementation.
|
||||||
|
func (engine *QPdf) EmbedFiles(ctx context.Context, logger *zap.Logger, filePaths []string, inputPath string) error {
|
||||||
|
return fmt.Errorf("embed files with QPDF: %w", gotenberg.ErrPdfEngineMethodNotSupported)
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_ gotenberg.Module = (*QPdf)(nil)
|
_ gotenberg.Module = (*QPdf)(nil)
|
||||||
_ gotenberg.Provisioner = (*QPdf)(nil)
|
_ gotenberg.Provisioner = (*QPdf)(nil)
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
# TODO:
|
# TODO:
|
||||||
# 1. JavaScript disabled on some feature.
|
# 1. JavaScript disabled on some feature.
|
||||||
|
|
||||||
|
@chromium
|
||||||
|
@chromium-convert-html
|
||||||
Feature: /forms/chromium/convert/html
|
Feature: /forms/chromium/convert/html
|
||||||
|
|
||||||
Scenario: POST /forms/chromium/convert/html (Default)
|
Scenario: POST /forms/chromium/convert/html (Default)
|
||||||
@@ -443,7 +445,16 @@ Feature: /forms/chromium/convert/html
|
|||||||
Then the response header "Content-Type" should be "text/plain; charset=UTF-8"
|
Then the response header "Content-Type" should be "text/plain; charset=UTF-8"
|
||||||
Then the response body should match string:
|
Then the response body should match string:
|
||||||
"""
|
"""
|
||||||
Chromium does not handle the page ranges 'foo' (nativePageRanges)
|
Chromium does not handle the page ranges 'foo' (nativePageRanges) syntax
|
||||||
|
"""
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
|
| files | testdata/page-1-html/index.html | file |
|
||||||
|
| nativePageRanges | 2-3 | field |
|
||||||
|
Then the response status code should be 400
|
||||||
|
Then the response header "Content-Type" should be "text/plain; charset=UTF-8"
|
||||||
|
Then the response body should match string:
|
||||||
|
"""
|
||||||
|
The page ranges '2-3' (nativePageRanges) exceeds the page count
|
||||||
"""
|
"""
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
| files | testdata/page-1-html/index.html | file |
|
| files | testdata/page-1-html/index.html | file |
|
||||||
@@ -557,6 +568,7 @@ Feature: /forms/chromium/convert/html
|
|||||||
Invalid form data: form field 'metadata' is invalid (got 'foo', resulting to unmarshal metadata: invalid character 'o' in literal false (expecting 'a'))
|
Invalid form data: form field 'metadata' is invalid (got 'foo', resulting to unmarshal metadata: invalid character 'o' in literal false (expecting 'a'))
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@split
|
||||||
Scenario: POST /forms/chromium/convert/html (Split Intervals)
|
Scenario: POST /forms/chromium/convert/html (Split Intervals)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
@@ -585,6 +597,8 @@ Feature: /forms/chromium/convert/html
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# See https://github.com/gotenberg/gotenberg/issues/1130.
|
# See https://github.com/gotenberg/gotenberg/issues/1130.
|
||||||
|
@split
|
||||||
|
@output-filename
|
||||||
Scenario: POST /forms/chromium/convert/html (Split Output Filename)
|
Scenario: POST /forms/chromium/convert/html (Split Output Filename)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
@@ -614,6 +628,7 @@ Feature: /forms/chromium/convert/html
|
|||||||
Page 3
|
Page 3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@split
|
||||||
Scenario: POST /forms/chromium/convert/html (Split Pages)
|
Scenario: POST /forms/chromium/convert/html (Split Pages)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
@@ -637,6 +652,7 @@ Feature: /forms/chromium/convert/html
|
|||||||
Page 3
|
Page 3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@split
|
||||||
Scenario: POST /forms/chromium/convert/html (Split Pages & Unify)
|
Scenario: POST /forms/chromium/convert/html (Split Pages & Unify)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
@@ -660,6 +676,7 @@ Feature: /forms/chromium/convert/html
|
|||||||
Page 3
|
Page 3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@split
|
||||||
Scenario: POST /forms/chromium/convert/html (Split Many PDFs - Lot of Pages)
|
Scenario: POST /forms/chromium/convert/html (Split Many PDFs - Lot of Pages)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
@@ -693,6 +710,7 @@ Feature: /forms/chromium/convert/html
|
|||||||
Page 12
|
Page 12
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@convert
|
||||||
Scenario: POST /forms/chromium/convert/html (PDF/A-1b & PDF/UA-1)
|
Scenario: POST /forms/chromium/convert/html (PDF/A-1b & PDF/UA-1)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
@@ -705,6 +723,8 @@ Feature: /forms/chromium/convert/html
|
|||||||
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 1 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 1 failed rule(s)
|
||||||
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
||||||
|
|
||||||
|
@convert
|
||||||
|
@split
|
||||||
Scenario: POST /forms/chromium/convert/html (Split & PDF/A-1b & PDF/UA-1)
|
Scenario: POST /forms/chromium/convert/html (Split & PDF/A-1b & PDF/UA-1)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
@@ -737,6 +757,9 @@ Feature: /forms/chromium/convert/html
|
|||||||
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
||||||
|
|
||||||
# See https://github.com/gotenberg/gotenberg/issues/1130.
|
# See https://github.com/gotenberg/gotenberg/issues/1130.
|
||||||
|
@convert
|
||||||
|
@split
|
||||||
|
@output-filename
|
||||||
Scenario: POST /forms/chromium/convert/html (Split & PDF/A-1b & PDF/UA-1 & Output Filename)
|
Scenario: POST /forms/chromium/convert/html (Split & PDF/A-1b & PDF/UA-1 & Output Filename)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
@@ -770,6 +793,7 @@ Feature: /forms/chromium/convert/html
|
|||||||
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 1 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 1 failed rule(s)
|
||||||
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
||||||
|
|
||||||
|
@metadata
|
||||||
Scenario: POST /forms/chromium/convert/html (Metadata)
|
Scenario: POST /forms/chromium/convert/html (Metadata)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
@@ -805,6 +829,7 @@ Feature: /forms/chromium/convert/html
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@flatten
|
||||||
Scenario: POST /forms/chromium/convert/html (Flatten)
|
Scenario: POST /forms/chromium/convert/html (Flatten)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
@@ -815,6 +840,7 @@ Feature: /forms/chromium/convert/html
|
|||||||
Then there should be 1 PDF(s) in the response
|
Then there should be 1 PDF(s) in the response
|
||||||
Then the response PDF(s) should be flatten
|
Then the response PDF(s) should be flatten
|
||||||
|
|
||||||
|
@encrypt
|
||||||
Scenario: POST /forms/chromium/convert/html (Encrypt - user password only)
|
Scenario: POST /forms/chromium/convert/html (Encrypt - user password only)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
@@ -825,6 +851,7 @@ Feature: /forms/chromium/convert/html
|
|||||||
Then there should be 1 PDF(s) in the response
|
Then there should be 1 PDF(s) in the response
|
||||||
Then the response PDF(s) should be encrypted
|
Then the response PDF(s) should be encrypted
|
||||||
|
|
||||||
|
@encrypt
|
||||||
Scenario: POST /forms/chromium/convert/html (Encrypt - both user and owner passwords)
|
Scenario: POST /forms/chromium/convert/html (Encrypt - both user and owner passwords)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
@@ -836,8 +863,28 @@ Feature: /forms/chromium/convert/html
|
|||||||
Then there should be 1 PDF(s) in the response
|
Then there should be 1 PDF(s) in the response
|
||||||
Then the response PDF(s) should be encrypted
|
Then the response PDF(s) should be encrypted
|
||||||
|
|
||||||
|
@embed
|
||||||
|
Scenario: POST /forms/chromium/convert/html (Embeds)
|
||||||
|
Given I have a default Gotenberg container
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
|
| files | testdata/page-1-html/index.html | file |
|
||||||
|
| embeds | testdata/embed_1.xml | file |
|
||||||
|
| embeds | testdata/embed_2.xml | file |
|
||||||
|
| Gotenberg-Output-Filename | foo | header |
|
||||||
|
Then the response status code should be 200
|
||||||
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
Then there should be 1 PDF(s) in the response
|
||||||
|
Then there should be the following file(s) in the response:
|
||||||
|
| foo.pdf |
|
||||||
|
Then the response PDF(s) should have the "embed_1.xml" file embedded
|
||||||
|
Then the response PDF(s) should have the "embed_2.xml" file embedded
|
||||||
|
|
||||||
# FIXME: once decrypt is done, add encrypt and check after the content of the PDF.
|
# FIXME: once decrypt is done, add encrypt and check after the content of the PDF.
|
||||||
Scenario: POST /forms/chromium/convert/html (PDF/A-1b & PDF/UA-1 & Metadata & Flatten)
|
@convert
|
||||||
|
@metadata
|
||||||
|
@flatten
|
||||||
|
@embed
|
||||||
|
Scenario: POST /forms/chromium/convert/html (PDF/A-1b & PDF/UA-1 & Metadata & Flatten & Embeds)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
| files | testdata/page-1-html/index.html | file |
|
| files | testdata/page-1-html/index.html | file |
|
||||||
@@ -845,15 +892,19 @@ Feature: /forms/chromium/convert/html
|
|||||||
| pdfua | true | field |
|
| pdfua | true | field |
|
||||||
| metadata | {"Author":"Julien Neuhart","Copyright":"Julien Neuhart","CreateDate":"2006-09-18T16:27:50-04:00","Creator":"Gotenberg","Keywords":["first","second"],"Marked":true,"ModDate":"2006-09-18T16:27:50-04:00","PDFVersion":1.7,"Producer":"Gotenberg","Subject":"Sample","Title":"Sample","Trapped":"Unknown"} | field |
|
| metadata | {"Author":"Julien Neuhart","Copyright":"Julien Neuhart","CreateDate":"2006-09-18T16:27:50-04:00","Creator":"Gotenberg","Keywords":["first","second"],"Marked":true,"ModDate":"2006-09-18T16:27:50-04:00","PDFVersion":1.7,"Producer":"Gotenberg","Subject":"Sample","Title":"Sample","Trapped":"Unknown"} | field |
|
||||||
| flatten | true | field |
|
| flatten | true | field |
|
||||||
|
| embeds | testdata/embed_1.xml | file |
|
||||||
|
| embeds | testdata/embed_2.xml | file |
|
||||||
| Gotenberg-Output-Filename | foo | header |
|
| Gotenberg-Output-Filename | foo | header |
|
||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
Then the response header "Content-Type" should be "application/pdf"
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
Then there should be 1 PDF(s) in the response
|
Then there should be 1 PDF(s) in the response
|
||||||
Then there should be the following file(s) in the response:
|
Then there should be the following file(s) in the response:
|
||||||
| foo.pdf |
|
| foo.pdf |
|
||||||
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 7 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 9 failed rule(s)
|
||||||
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 2 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 2 failed rule(s)
|
||||||
Then the response PDF(s) should be flatten
|
Then the response PDF(s) should be flatten
|
||||||
|
Then the response PDF(s) should have the "embed_1.xml" file embedded
|
||||||
|
Then the response PDF(s) should have the "embed_2.xml" file embedded
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/metadata/read" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/metadata/read" endpoint with the following form data and header(s):
|
||||||
| files | teststore/foo.pdf | file |
|
| files | teststore/foo.pdf | file |
|
||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
@@ -896,6 +947,7 @@ Feature: /forms/chromium/convert/html
|
|||||||
Then the Gotenberg container should log the following entries:
|
Then the Gotenberg container should log the following entries:
|
||||||
| "trace":"forms_chromium_convert_html" |
|
| "trace":"forms_chromium_convert_html" |
|
||||||
|
|
||||||
|
@download-from
|
||||||
Scenario: POST /forms/chromium/convert/html (Download From)
|
Scenario: POST /forms/chromium/convert/html (Download From)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -905,6 +957,7 @@ Feature: /forms/chromium/convert/html
|
|||||||
Then the file request header "X-Foo" should be "bar"
|
Then the file request header "X-Foo" should be "bar"
|
||||||
Then the response header "Content-Type" should be "application/pdf"
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
|
||||||
|
@webhook
|
||||||
Scenario: POST /forms/chromium/convert/html (Webhook)
|
Scenario: POST /forms/chromium/convert/html (Webhook)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a webhook server
|
Given I have a webhook server
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
# TODO:
|
# TODO:
|
||||||
# 1. JavaScript disabled on some feature.
|
# 1. JavaScript disabled on some feature.
|
||||||
|
|
||||||
|
@chromium
|
||||||
|
@chromium-convert-markdown
|
||||||
Feature: /forms/chromium/convert/markdown
|
Feature: /forms/chromium/convert/markdown
|
||||||
|
|
||||||
Scenario: POST /forms/chromium/convert/markdown (Default)
|
Scenario: POST /forms/chromium/convert/markdown (Default)
|
||||||
@@ -522,7 +524,17 @@ Feature: /forms/chromium/convert/markdown
|
|||||||
Then the response header "Content-Type" should be "text/plain; charset=UTF-8"
|
Then the response header "Content-Type" should be "text/plain; charset=UTF-8"
|
||||||
Then the response body should match string:
|
Then the response body should match string:
|
||||||
"""
|
"""
|
||||||
Chromium does not handle the page ranges 'foo' (nativePageRanges)
|
Chromium does not handle the page ranges 'foo' (nativePageRanges) syntax
|
||||||
|
"""
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
||||||
|
| files | testdata/page-1-markdown/index.html | file |
|
||||||
|
| files | testdata/page-1-markdown/page_1.md | file |
|
||||||
|
| nativePageRanges | 2-3 | field |
|
||||||
|
Then the response status code should be 400
|
||||||
|
Then the response header "Content-Type" should be "text/plain; charset=UTF-8"
|
||||||
|
Then the response body should match string:
|
||||||
|
"""
|
||||||
|
The page ranges '2-3' (nativePageRanges) exceeds the page count
|
||||||
"""
|
"""
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
||||||
| files | testdata/page-1-markdown/index.html | file |
|
| files | testdata/page-1-markdown/index.html | file |
|
||||||
@@ -648,6 +660,7 @@ Feature: /forms/chromium/convert/markdown
|
|||||||
Invalid form data: form field 'metadata' is invalid (got 'foo', resulting to unmarshal metadata: invalid character 'o' in literal false (expecting 'a'))
|
Invalid form data: form field 'metadata' is invalid (got 'foo', resulting to unmarshal metadata: invalid character 'o' in literal false (expecting 'a'))
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@split
|
||||||
Scenario: POST /forms/chromium/convert/markdown (Split Intervals)
|
Scenario: POST /forms/chromium/convert/markdown (Split Intervals)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
||||||
@@ -679,6 +692,8 @@ Feature: /forms/chromium/convert/markdown
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# See https://github.com/gotenberg/gotenberg/issues/1130.
|
# See https://github.com/gotenberg/gotenberg/issues/1130.
|
||||||
|
@split
|
||||||
|
@output-filename
|
||||||
Scenario: POST /forms/chromium/convert/markdown (Split Output Filename)
|
Scenario: POST /forms/chromium/convert/markdown (Split Output Filename)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
||||||
@@ -711,6 +726,7 @@ Feature: /forms/chromium/convert/markdown
|
|||||||
Page 3
|
Page 3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@split
|
||||||
Scenario: POST /forms/chromium/convert/markdown (Split Pages)
|
Scenario: POST /forms/chromium/convert/markdown (Split Pages)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
||||||
@@ -737,6 +753,7 @@ Feature: /forms/chromium/convert/markdown
|
|||||||
Page 3
|
Page 3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@split
|
||||||
Scenario: POST /forms/chromium/convert/markdown (Split Pages & Unify)
|
Scenario: POST /forms/chromium/convert/markdown (Split Pages & Unify)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
||||||
@@ -763,6 +780,7 @@ Feature: /forms/chromium/convert/markdown
|
|||||||
Page 3
|
Page 3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@split
|
||||||
Scenario: POST /forms/chromium/convert/markdown (Split Many PDFs - Lot of Pages)
|
Scenario: POST /forms/chromium/convert/markdown (Split Many PDFs - Lot of Pages)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
||||||
@@ -808,6 +826,7 @@ Feature: /forms/chromium/convert/markdown
|
|||||||
Page 12
|
Page 12
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@convert
|
||||||
Scenario: POST /forms/chromium/convert/markdown (PDF/A-1b & PDF/UA-1)
|
Scenario: POST /forms/chromium/convert/markdown (PDF/A-1b & PDF/UA-1)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
||||||
@@ -821,6 +840,8 @@ Feature: /forms/chromium/convert/markdown
|
|||||||
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 1 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 1 failed rule(s)
|
||||||
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
||||||
|
|
||||||
|
@convert
|
||||||
|
@split
|
||||||
Scenario: POST /forms/chromium/convert/markdown (Split & PDF/A-1b & PDF/UA-1)
|
Scenario: POST /forms/chromium/convert/markdown (Split & PDF/A-1b & PDF/UA-1)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
||||||
@@ -856,6 +877,9 @@ Feature: /forms/chromium/convert/markdown
|
|||||||
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
||||||
|
|
||||||
# See https://github.com/gotenberg/gotenberg/issues/1130.
|
# See https://github.com/gotenberg/gotenberg/issues/1130.
|
||||||
|
@convert
|
||||||
|
@split
|
||||||
|
@output-filename
|
||||||
Scenario: POST /forms/chromium/convert/markdown (Split & PDF/A-1b & PDF/UA-1 & Output Filename)
|
Scenario: POST /forms/chromium/convert/markdown (Split & PDF/A-1b & PDF/UA-1 & Output Filename)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
||||||
@@ -892,6 +916,7 @@ Feature: /forms/chromium/convert/markdown
|
|||||||
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 1 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 1 failed rule(s)
|
||||||
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
||||||
|
|
||||||
|
@metadata
|
||||||
Scenario: POST /forms/chromium/convert/markdown (Metadata)
|
Scenario: POST /forms/chromium/convert/markdown (Metadata)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
||||||
@@ -928,6 +953,7 @@ Feature: /forms/chromium/convert/markdown
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@flatten
|
||||||
Scenario: POST /forms/chromium/convert/markdown (Flatten)
|
Scenario: POST /forms/chromium/convert/markdown (Flatten)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
||||||
@@ -939,6 +965,7 @@ Feature: /forms/chromium/convert/markdown
|
|||||||
Then there should be 1 PDF(s) in the response
|
Then there should be 1 PDF(s) in the response
|
||||||
Then the response PDF(s) should be flatten
|
Then the response PDF(s) should be flatten
|
||||||
|
|
||||||
|
@encrypt
|
||||||
Scenario: POST /forms/chromium/convert/markdown (Encrypt - user password only)
|
Scenario: POST /forms/chromium/convert/markdown (Encrypt - user password only)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
||||||
@@ -950,6 +977,7 @@ Feature: /forms/chromium/convert/markdown
|
|||||||
Then there should be 1 PDF(s) in the response
|
Then there should be 1 PDF(s) in the response
|
||||||
Then the response PDF(s) should be encrypted
|
Then the response PDF(s) should be encrypted
|
||||||
|
|
||||||
|
@encrypt
|
||||||
Scenario: POST /forms/chromium/convert/markdown (Encrypt - both user and owner passwords)
|
Scenario: POST /forms/chromium/convert/markdown (Encrypt - both user and owner passwords)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
||||||
@@ -962,8 +990,29 @@ Feature: /forms/chromium/convert/markdown
|
|||||||
Then there should be 1 PDF(s) in the response
|
Then there should be 1 PDF(s) in the response
|
||||||
Then the response PDF(s) should be encrypted
|
Then the response PDF(s) should be encrypted
|
||||||
|
|
||||||
|
@embed
|
||||||
|
Scenario: POST /forms/chromium/convert/markdown (Embeds)
|
||||||
|
Given I have a default Gotenberg container
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
||||||
|
| files | testdata/page-1-markdown/index.html | file |
|
||||||
|
| files | testdata/page-1-markdown/page_1.md | file |
|
||||||
|
| embeds | testdata/embed_1.xml | file |
|
||||||
|
| embeds | testdata/embed_2.xml | file |
|
||||||
|
| Gotenberg-Output-Filename | foo | header |
|
||||||
|
Then the response status code should be 200
|
||||||
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
Then there should be 1 PDF(s) in the response
|
||||||
|
Then there should be the following file(s) in the response:
|
||||||
|
| foo.pdf |
|
||||||
|
Then the response PDF(s) should have the "embed_1.xml" file embedded
|
||||||
|
Then the response PDF(s) should have the "embed_2.xml" file embedded
|
||||||
|
|
||||||
# FIXME: once decrypt is done, add encrypt and check after the content of the PDF.
|
# FIXME: once decrypt is done, add encrypt and check after the content of the PDF.
|
||||||
Scenario: POST /forms/chromium/convert/markdown (PDF/A-1b & PDF/UA-1 & Metadata & Flatten)
|
@convert
|
||||||
|
@metadata
|
||||||
|
@flatten
|
||||||
|
@embed
|
||||||
|
Scenario: POST /forms/chromium/convert/markdown (PDF/A-1b & PDF/UA-1 & Metadata & Flatten & Embeds)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s):
|
||||||
| files | testdata/page-1-markdown/index.html | file |
|
| files | testdata/page-1-markdown/index.html | file |
|
||||||
@@ -972,15 +1021,19 @@ Feature: /forms/chromium/convert/markdown
|
|||||||
| pdfua | true | field |
|
| pdfua | true | field |
|
||||||
| metadata | {"Author":"Julien Neuhart","Copyright":"Julien Neuhart","CreateDate":"2006-09-18T16:27:50-04:00","Creator":"Gotenberg","Keywords":["first","second"],"Marked":true,"ModDate":"2006-09-18T16:27:50-04:00","PDFVersion":1.7,"Producer":"Gotenberg","Subject":"Sample","Title":"Sample","Trapped":"Unknown"} | field |
|
| metadata | {"Author":"Julien Neuhart","Copyright":"Julien Neuhart","CreateDate":"2006-09-18T16:27:50-04:00","Creator":"Gotenberg","Keywords":["first","second"],"Marked":true,"ModDate":"2006-09-18T16:27:50-04:00","PDFVersion":1.7,"Producer":"Gotenberg","Subject":"Sample","Title":"Sample","Trapped":"Unknown"} | field |
|
||||||
| flatten | true | field |
|
| flatten | true | field |
|
||||||
|
| embeds | testdata/embed_1.xml | file |
|
||||||
|
| embeds | testdata/embed_2.xml | file |
|
||||||
| Gotenberg-Output-Filename | foo | header |
|
| Gotenberg-Output-Filename | foo | header |
|
||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
Then the response header "Content-Type" should be "application/pdf"
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
Then there should be 1 PDF(s) in the response
|
Then there should be 1 PDF(s) in the response
|
||||||
Then there should be the following file(s) in the response:
|
Then there should be the following file(s) in the response:
|
||||||
| foo.pdf |
|
| foo.pdf |
|
||||||
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 7 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 9 failed rule(s)
|
||||||
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 2 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 2 failed rule(s)
|
||||||
Then the response PDF(s) should be flatten
|
Then the response PDF(s) should be flatten
|
||||||
|
Then the response PDF(s) should have the "embed_1.xml" file embedded
|
||||||
|
Then the response PDF(s) should have the "embed_2.xml" file embedded
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/metadata/read" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/metadata/read" endpoint with the following form data and header(s):
|
||||||
| files | teststore/foo.pdf | file |
|
| files | teststore/foo.pdf | file |
|
||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
@@ -1025,6 +1078,7 @@ Feature: /forms/chromium/convert/markdown
|
|||||||
Then the Gotenberg container should log the following entries:
|
Then the Gotenberg container should log the following entries:
|
||||||
| "trace":"forms_chromium_convert_html" |
|
| "trace":"forms_chromium_convert_html" |
|
||||||
|
|
||||||
|
@download-from
|
||||||
Scenario: POST /forms/chromium/convert/markdown (Download From)
|
Scenario: POST /forms/chromium/convert/markdown (Download From)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -1035,6 +1089,7 @@ Feature: /forms/chromium/convert/markdown
|
|||||||
Then the file request header "X-Foo" should be "bar"
|
Then the file request header "X-Foo" should be "bar"
|
||||||
Then the response header "Content-Type" should be "application/pdf"
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
|
||||||
|
@webhook
|
||||||
Scenario: POST /forms/chromium/convert/markdown (Webhook)
|
Scenario: POST /forms/chromium/convert/markdown (Webhook)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a webhook server
|
Given I have a webhook server
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
# TODO:
|
# TODO:
|
||||||
# 1. JavaScript disabled on some feature.
|
# 1. JavaScript disabled on some feature.
|
||||||
|
|
||||||
|
@chromium
|
||||||
|
@chromium-convert-url
|
||||||
Feature: /forms/chromium/convert/url
|
Feature: /forms/chromium/convert/url
|
||||||
|
|
||||||
Scenario: POST /forms/chromium/convert/url (Default)
|
Scenario: POST /forms/chromium/convert/url (Default)
|
||||||
@@ -173,6 +175,22 @@ Feature: /forms/chromium/convert/url
|
|||||||
Then the server request cookie "cookie_1" should be "foo"
|
Then the server request cookie "cookie_1" should be "foo"
|
||||||
Then the server request cookie "cookie_2" should be ""
|
Then the server request cookie "cookie_2" should be ""
|
||||||
|
|
||||||
|
# See https://github.com/gotenberg/gotenberg/issues/1130.
|
||||||
|
Scenario: POST /forms/chromium/convert/url (case-insensitive sameSite)
|
||||||
|
Given I have a default Gotenberg container
|
||||||
|
Given I have a static server
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/url" endpoint with the following form data and header(s):
|
||||||
|
| url | http://host.docker.internal:%d/html/testdata/page-1-html/index.html | field |
|
||||||
|
| cookies | [{"name":"cookie_1","value":"foo","domain":"host.docker.internal:%d"},{"name":"cookie_2","value":"bar","domain":"domain.com","sameSite":"lax"}] | field |
|
||||||
|
| Gotenberg-Output-Filename | foo | header |
|
||||||
|
Then the response status code should be 200
|
||||||
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
Then there should be 1 PDF(s) in the response
|
||||||
|
Then there should be the following file(s) in the response:
|
||||||
|
| foo.pdf |
|
||||||
|
Then the server request cookie "cookie_1" should be "foo"
|
||||||
|
Then the server request cookie "cookie_2" should be ""
|
||||||
|
|
||||||
Scenario: POST /forms/chromium/convert/url (Wait Delay)
|
Scenario: POST /forms/chromium/convert/url (Wait Delay)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -504,7 +522,17 @@ Feature: /forms/chromium/convert/url
|
|||||||
Then the response header "Content-Type" should be "text/plain; charset=UTF-8"
|
Then the response header "Content-Type" should be "text/plain; charset=UTF-8"
|
||||||
Then the response body should match string:
|
Then the response body should match string:
|
||||||
"""
|
"""
|
||||||
Chromium does not handle the page ranges 'foo' (nativePageRanges)
|
Chromium does not handle the page ranges 'foo' (nativePageRanges) syntax
|
||||||
|
"""
|
||||||
|
Given I have a static server
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/url" endpoint with the following form data and header(s):
|
||||||
|
| url | http://host.docker.internal:%d/html/testdata/page-1-html/index.html | field |
|
||||||
|
| nativePageRanges | 2-3 | field |
|
||||||
|
Then the response status code should be 400
|
||||||
|
Then the response header "Content-Type" should be "text/plain; charset=UTF-8"
|
||||||
|
Then the response body should match string:
|
||||||
|
"""
|
||||||
|
The page ranges '2-3' (nativePageRanges) exceeds the page count
|
||||||
"""
|
"""
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/url" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/url" endpoint with the following form data and header(s):
|
||||||
@@ -630,6 +658,7 @@ Feature: /forms/chromium/convert/url
|
|||||||
Invalid form data: form field 'metadata' is invalid (got 'foo', resulting to unmarshal metadata: invalid character 'o' in literal false (expecting 'a'))
|
Invalid form data: form field 'metadata' is invalid (got 'foo', resulting to unmarshal metadata: invalid character 'o' in literal false (expecting 'a'))
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@split
|
||||||
Scenario: POST /forms/chromium/convert/url (Split Intervals)
|
Scenario: POST /forms/chromium/convert/url (Split Intervals)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -659,6 +688,8 @@ Feature: /forms/chromium/convert/url
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# See https://github.com/gotenberg/gotenberg/issues/1130.
|
# See https://github.com/gotenberg/gotenberg/issues/1130.
|
||||||
|
@split
|
||||||
|
@output-filename
|
||||||
Scenario: POST /forms/chromium/convert/url (Split Output Filename)
|
Scenario: POST /forms/chromium/convert/url (Split Output Filename)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -689,6 +720,7 @@ Feature: /forms/chromium/convert/url
|
|||||||
Page 3
|
Page 3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@split
|
||||||
Scenario: POST /forms/chromium/convert/url (Split Pages)
|
Scenario: POST /forms/chromium/convert/url (Split Pages)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -713,6 +745,7 @@ Feature: /forms/chromium/convert/url
|
|||||||
Page 3
|
Page 3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@split
|
||||||
Scenario: POST /forms/chromium/convert/url (Split Pages & Unify)
|
Scenario: POST /forms/chromium/convert/url (Split Pages & Unify)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -737,6 +770,7 @@ Feature: /forms/chromium/convert/url
|
|||||||
Page 3
|
Page 3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@split
|
||||||
Scenario: POST /forms/chromium/convert/url (Split Many PDFs - Lot of Pages)
|
Scenario: POST /forms/chromium/convert/url (Split Many PDFs - Lot of Pages)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -771,6 +805,7 @@ Feature: /forms/chromium/convert/url
|
|||||||
Page 12
|
Page 12
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@convert
|
||||||
Scenario: POST /forms/chromium/convert/url (PDF/A-1b & PDF/UA-1)
|
Scenario: POST /forms/chromium/convert/url (PDF/A-1b & PDF/UA-1)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -817,6 +852,9 @@ Feature: /forms/chromium/convert/url
|
|||||||
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
||||||
|
|
||||||
# See https://github.com/gotenberg/gotenberg/issues/1130.
|
# See https://github.com/gotenberg/gotenberg/issues/1130.
|
||||||
|
@convert
|
||||||
|
@split
|
||||||
|
@output-filename
|
||||||
Scenario: POST /forms/chromium/convert/url (Split & PDF/A-1b & PDF/UA-1 & Output Filename)
|
Scenario: POST /forms/chromium/convert/url (Split & PDF/A-1b & PDF/UA-1 & Output Filename)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -851,6 +889,7 @@ Feature: /forms/chromium/convert/url
|
|||||||
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 1 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 1 failed rule(s)
|
||||||
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
||||||
|
|
||||||
|
@metadata
|
||||||
Scenario: POST /forms/chromium/convert/url (Metadata)
|
Scenario: POST /forms/chromium/convert/url (Metadata)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -887,6 +926,7 @@ Feature: /forms/chromium/convert/url
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@flatten
|
||||||
Scenario: POST /forms/chromium/convert/url (Flatten)
|
Scenario: POST /forms/chromium/convert/url (Flatten)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -898,6 +938,7 @@ Feature: /forms/chromium/convert/url
|
|||||||
Then there should be 1 PDF(s) in the response
|
Then there should be 1 PDF(s) in the response
|
||||||
Then the response PDF(s) should be flatten
|
Then the response PDF(s) should be flatten
|
||||||
|
|
||||||
|
@encrypt
|
||||||
Scenario: POST /forms/chromium/convert/url (Encrypt - user password only)
|
Scenario: POST /forms/chromium/convert/url (Encrypt - user password only)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -909,6 +950,7 @@ Feature: /forms/chromium/convert/url
|
|||||||
Then there should be 1 PDF(s) in the response
|
Then there should be 1 PDF(s) in the response
|
||||||
Then the response PDF(s) should be encrypted
|
Then the response PDF(s) should be encrypted
|
||||||
|
|
||||||
|
@encrypt
|
||||||
Scenario: POST /forms/chromium/convert/url (Encrypt - both user and owner passwords)
|
Scenario: POST /forms/chromium/convert/url (Encrypt - both user and owner passwords)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -921,7 +963,28 @@ Feature: /forms/chromium/convert/url
|
|||||||
Then there should be 1 PDF(s) in the response
|
Then there should be 1 PDF(s) in the response
|
||||||
Then the response PDF(s) should be encrypted
|
Then the response PDF(s) should be encrypted
|
||||||
|
|
||||||
|
@embed
|
||||||
|
Scenario: POST /foo/forms/chromium/convert/url (Embeds)
|
||||||
|
Given I have a default Gotenberg container
|
||||||
|
Given I have a static server
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/url" endpoint with the following form data and header(s):
|
||||||
|
| url | http://host.docker.internal:%d/html/testdata/page-1-html/index.html | field |
|
||||||
|
| embeds | testdata/embed_1.xml | file |
|
||||||
|
| embeds | testdata/embed_2.xml | file |
|
||||||
|
| Gotenberg-Output-Filename | foo | header |
|
||||||
|
Then the response status code should be 200
|
||||||
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
Then there should be 1 PDF(s) in the response
|
||||||
|
Then there should be the following file(s) in the webhook request:
|
||||||
|
| foo.pdf |
|
||||||
|
Then the response PDF(s) should have the "embed_1.xml" file embedded
|
||||||
|
Then the response PDF(s) should have the "embed_2.xml" file embedded
|
||||||
|
|
||||||
# FIXME: once decrypt is done, add encrypt and check after the content of the PDF.
|
# FIXME: once decrypt is done, add encrypt and check after the content of the PDF.
|
||||||
|
@convert
|
||||||
|
@metadata
|
||||||
|
@flatten
|
||||||
|
@embed
|
||||||
Scenario: POST /forms/chromium/convert/url (PDF/A-1b & PDF/UA-1 & Metadata & Flatten)
|
Scenario: POST /forms/chromium/convert/url (PDF/A-1b & PDF/UA-1 & Metadata & Flatten)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -931,15 +994,19 @@ Feature: /forms/chromium/convert/url
|
|||||||
| pdfua | true | field |
|
| pdfua | true | field |
|
||||||
| metadata | {"Author":"Julien Neuhart","Copyright":"Julien Neuhart","CreateDate":"2006-09-18T16:27:50-04:00","Creator":"Gotenberg","Keywords":["first","second"],"Marked":true,"ModDate":"2006-09-18T16:27:50-04:00","PDFVersion":1.7,"Producer":"Gotenberg","Subject":"Sample","Title":"Sample","Trapped":"Unknown"} | field |
|
| metadata | {"Author":"Julien Neuhart","Copyright":"Julien Neuhart","CreateDate":"2006-09-18T16:27:50-04:00","Creator":"Gotenberg","Keywords":["first","second"],"Marked":true,"ModDate":"2006-09-18T16:27:50-04:00","PDFVersion":1.7,"Producer":"Gotenberg","Subject":"Sample","Title":"Sample","Trapped":"Unknown"} | field |
|
||||||
| flatten | true | field |
|
| flatten | true | field |
|
||||||
|
| embeds | testdata/embed_1.xml | file |
|
||||||
|
| embeds | testdata/embed_2.xml | file |
|
||||||
| Gotenberg-Output-Filename | foo | header |
|
| Gotenberg-Output-Filename | foo | header |
|
||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
Then the response header "Content-Type" should be "application/pdf"
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
Then there should be 1 PDF(s) in the response
|
Then there should be 1 PDF(s) in the response
|
||||||
Then there should be the following file(s) in the response:
|
Then there should be the following file(s) in the response:
|
||||||
| foo.pdf |
|
| foo.pdf |
|
||||||
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 7 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 9 failed rule(s)
|
||||||
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 2 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 2 failed rule(s)
|
||||||
Then the response PDF(s) should be flatten
|
Then the response PDF(s) should be flatten
|
||||||
|
Then the response PDF(s) should have the "embed_1.xml" file embedded
|
||||||
|
Then the response PDF(s) should have the "embed_2.xml" file embedded
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/metadata/read" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/metadata/read" endpoint with the following form data and header(s):
|
||||||
| files | teststore/foo.pdf | file |
|
| files | teststore/foo.pdf | file |
|
||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
@@ -984,6 +1051,7 @@ Feature: /forms/chromium/convert/url
|
|||||||
Then the Gotenberg container should log the following entries:
|
Then the Gotenberg container should log the following entries:
|
||||||
| "trace":"forms_chromium_convert_url" |
|
| "trace":"forms_chromium_convert_url" |
|
||||||
|
|
||||||
|
@webhook
|
||||||
Scenario: POST /forms/chromium/convert/url (Webhook)
|
Scenario: POST /forms/chromium/convert/url (Webhook)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a webhook server
|
Given I have a webhook server
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
@debug
|
||||||
Feature: /debug
|
Feature: /debug
|
||||||
|
|
||||||
Scenario: GET /debug (Disabled)
|
Scenario: GET /debug (Disabled)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
# 1. Check if down for each module.
|
# 1. Check if down for each module.
|
||||||
# 2. Restarting modules do not make health check fail.
|
# 2. Restarting modules do not make health check fail.
|
||||||
|
|
||||||
|
@health
|
||||||
Feature: /health
|
Feature: /health
|
||||||
|
|
||||||
Scenario: GET /health
|
Scenario: GET /health
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
@libreoffice
|
||||||
|
@libreoffice-convert
|
||||||
Feature: /forms/libreoffice/convert
|
Feature: /forms/libreoffice/convert
|
||||||
|
|
||||||
Scenario: POST /forms/libreoffice/convert (Single Document)
|
Scenario: POST /forms/libreoffice/convert (Single Document)
|
||||||
@@ -272,6 +274,7 @@ Feature: /forms/libreoffice/convert
|
|||||||
Invalid form data: form field 'metadata' is invalid (got 'foo', resulting to unmarshal metadata: invalid character 'o' in literal false (expecting 'a'))
|
Invalid form data: form field 'metadata' is invalid (got 'foo', resulting to unmarshal metadata: invalid character 'o' in literal false (expecting 'a'))
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@merge
|
||||||
Scenario: POST /forms/libreoffice/convert (Merge)
|
Scenario: POST /forms/libreoffice/convert (Merge)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
||||||
@@ -294,6 +297,8 @@ Feature: /forms/libreoffice/convert
|
|||||||
Page 2
|
Page 2
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@merge
|
||||||
|
@split
|
||||||
Scenario: POST /forms/libreoffice/convert (Merge & Split)
|
Scenario: POST /forms/libreoffice/convert (Merge & Split)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
||||||
@@ -319,6 +324,7 @@ Feature: /forms/libreoffice/convert
|
|||||||
Page 2
|
Page 2
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@split
|
||||||
Scenario: POST /forms/libreoffice/convert (Split Intervals)
|
Scenario: POST /forms/libreoffice/convert (Split Intervals)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
||||||
@@ -346,6 +352,7 @@ Feature: /forms/libreoffice/convert
|
|||||||
Page 3
|
Page 3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@split
|
||||||
Scenario: POST /forms/libreoffice/convert (Split Pages)
|
Scenario: POST /forms/libreoffice/convert (Split Pages)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
||||||
@@ -369,6 +376,7 @@ Feature: /forms/libreoffice/convert
|
|||||||
Page 3
|
Page 3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@split
|
||||||
Scenario: POST /forms/libreoffice/convert (Split Pages & Unify)
|
Scenario: POST /forms/libreoffice/convert (Split Pages & Unify)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
||||||
@@ -391,6 +399,7 @@ Feature: /forms/libreoffice/convert
|
|||||||
Page 3
|
Page 3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@split
|
||||||
Scenario: POST /forms/libreoffice/convert (Split Many PDFs - Lot of Pages)
|
Scenario: POST /forms/libreoffice/convert (Split Many PDFs - Lot of Pages)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
||||||
@@ -438,6 +447,7 @@ Feature: /forms/libreoffice/convert
|
|||||||
Page 12
|
Page 12
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@convert
|
||||||
Scenario: POST /forms/libreoffice/convert (PDF/A-1b & PDF/UA-1)
|
Scenario: POST /forms/libreoffice/convert (PDF/A-1b & PDF/UA-1)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
||||||
@@ -450,6 +460,8 @@ Feature: /forms/libreoffice/convert
|
|||||||
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 1 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 1 failed rule(s)
|
||||||
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
||||||
|
|
||||||
|
@split
|
||||||
|
@convert
|
||||||
Scenario: POST /forms/libreoffice/convert (Split & PDF/A-1b & PDF/UA-1)
|
Scenario: POST /forms/libreoffice/convert (Split & PDF/A-1b & PDF/UA-1)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
||||||
@@ -481,6 +493,7 @@ Feature: /forms/libreoffice/convert
|
|||||||
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 1 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 1 failed rule(s)
|
||||||
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
||||||
|
|
||||||
|
@metadata
|
||||||
Scenario: POST /forms/libreoffice/convert (Metadata)
|
Scenario: POST /forms/libreoffice/convert (Metadata)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
||||||
@@ -516,6 +529,7 @@ Feature: /forms/libreoffice/convert
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@flatten
|
||||||
Scenario: POST /forms/libreoffice/convert (Flatten)
|
Scenario: POST /forms/libreoffice/convert (Flatten)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
||||||
@@ -526,6 +540,7 @@ Feature: /forms/libreoffice/convert
|
|||||||
Then there should be 1 PDF(s) in the response
|
Then there should be 1 PDF(s) in the response
|
||||||
Then the response PDF(s) should be flatten
|
Then the response PDF(s) should be flatten
|
||||||
|
|
||||||
|
@encrypt
|
||||||
Scenario: POST /forms/libreoffice/convert (Encrypt - user password only)
|
Scenario: POST /forms/libreoffice/convert (Encrypt - user password only)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
||||||
@@ -536,6 +551,7 @@ Feature: /forms/libreoffice/convert
|
|||||||
Then there should be 1 PDF(s) in the response
|
Then there should be 1 PDF(s) in the response
|
||||||
Then the response PDF(s) should be encrypted
|
Then the response PDF(s) should be encrypted
|
||||||
|
|
||||||
|
@encrypt
|
||||||
Scenario: POST /forms/libreoffice/convert (Encrypt - both user and owner passwords)
|
Scenario: POST /forms/libreoffice/convert (Encrypt - both user and owner passwords)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
||||||
@@ -547,23 +563,48 @@ Feature: /forms/libreoffice/convert
|
|||||||
Then there should be 1 PDF(s) in the response
|
Then there should be 1 PDF(s) in the response
|
||||||
Then the response PDF(s) should be encrypted
|
Then the response PDF(s) should be encrypted
|
||||||
|
|
||||||
|
@embed
|
||||||
|
Scenario: POST /forms/libreoffice/convert (Embeds)
|
||||||
|
Given I have a default Gotenberg container
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
||||||
|
| files | testdata/page_1.docx | file |
|
||||||
|
| embeds | testdata/embed_1.xml | file |
|
||||||
|
| embeds | testdata/embed_2.xml | file |
|
||||||
|
| Gotenberg-Output-Filename | foo | header |
|
||||||
|
Then the response status code should be 200
|
||||||
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
Then there should be 1 PDF(s) in the response
|
||||||
|
Then there should be the following file(s) in the response:
|
||||||
|
| foo.pdf |
|
||||||
|
Then the response PDF(s) should have the "embed_1.xml" file embedded
|
||||||
|
Then the response PDF(s) should have the "embed_2.xml" file embedded
|
||||||
|
|
||||||
# FIXME: once decrypt is done, add encrypt and check after the content of the PDF.
|
# FIXME: once decrypt is done, add encrypt and check after the content of the PDF.
|
||||||
Scenario: POST /forms/libreoffice/convert (PDF/A-1b & PDF/UA-1 & Metadata & Flatten)
|
@convert
|
||||||
|
@metadata
|
||||||
|
@flatten
|
||||||
|
@embed
|
||||||
|
Scenario: POST /forms/libreoffice/convert (PDF/A-1b & PDF/UA-1 & Metadata & Flatten & Embeds)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s):
|
||||||
| files | testdata/page_1.docx | file |
|
| files | testdata/page_1.docx | file |
|
||||||
| pdfa | PDF/A-1b | field |
|
| pdfa | PDF/A-1b | field |
|
||||||
| pdfua | true | field |
|
| pdfua | true | field |
|
||||||
| metadata | {"Author":"Julien Neuhart","Copyright":"Julien Neuhart","CreateDate":"2006-09-18T16:27:50-04:00","Creator":"Gotenberg","Keywords":["first","second"],"Marked":true,"ModDate":"2006-09-18T16:27:50-04:00","PDFVersion":1.7,"Producer":"Gotenberg","Subject":"Sample","Title":"Sample","Trapped":"Unknown"} | field |
|
| metadata | {"Author":"Julien Neuhart","Copyright":"Julien Neuhart","CreateDate":"2006-09-18T16:27:50-04:00","Creator":"Gotenberg","Keywords":["first","second"],"Marked":true,"ModDate":"2006-09-18T16:27:50-04:00","PDFVersion":1.7,"Producer":"Gotenberg","Subject":"Sample","Title":"Sample","Trapped":"Unknown"} | field |
|
||||||
|
| flatten | true | field |
|
||||||
|
| embeds | testdata/embed_1.xml | file |
|
||||||
|
| embeds | testdata/embed_2.xml | file |
|
||||||
| Gotenberg-Output-Filename | foo | header |
|
| Gotenberg-Output-Filename | foo | header |
|
||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
Then the response header "Content-Type" should be "application/pdf"
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
Then there should be 1 PDF(s) in the response
|
Then there should be 1 PDF(s) in the response
|
||||||
Then there should be the following file(s) in the response:
|
Then there should be the following file(s) in the response:
|
||||||
| foo.pdf |
|
| foo.pdf |
|
||||||
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 7 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 10 failed rule(s)
|
||||||
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 2 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 2 failed rule(s)
|
||||||
Then the response PDF(s) should be flatten
|
Then the response PDF(s) should be flatten
|
||||||
|
Then the response PDF(s) should have the "embed_1.xml" file embedded
|
||||||
|
Then the response PDF(s) should have the "embed_2.xml" file embedded
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/metadata/read" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/metadata/read" endpoint with the following form data and header(s):
|
||||||
| files | teststore/foo.pdf | file |
|
| files | teststore/foo.pdf | file |
|
||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
@@ -606,6 +647,7 @@ Feature: /forms/libreoffice/convert
|
|||||||
Then the Gotenberg container should log the following entries:
|
Then the Gotenberg container should log the following entries:
|
||||||
| "trace":"forms_libreoffice_convert" |
|
| "trace":"forms_libreoffice_convert" |
|
||||||
|
|
||||||
|
@download-from
|
||||||
Scenario: POST /forms/libreoffice/convert (Download From)
|
Scenario: POST /forms/libreoffice/convert (Download From)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -615,6 +657,7 @@ Feature: /forms/libreoffice/convert
|
|||||||
Then the file request header "X-Foo" should be "bar"
|
Then the file request header "X-Foo" should be "bar"
|
||||||
Then the response header "Content-Type" should be "application/pdf"
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
|
||||||
|
@webhook
|
||||||
Scenario: POST /forms/libreoffice/convert (Webhook)
|
Scenario: POST /forms/libreoffice/convert (Webhook)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a webhook server
|
Given I have a webhook server
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
@output-filename
|
||||||
Feature: Output Filename
|
Feature: Output Filename
|
||||||
|
|
||||||
Scenario: Default (Single Output File)
|
Scenario: Default (Single Output File)
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
# TODO:
|
# TODO:
|
||||||
# 1. PDF/UA-2.
|
# 1. PDF/UA-2.
|
||||||
|
|
||||||
|
@pdfengines
|
||||||
|
@pdfengines-convert
|
||||||
Feature: /forms/pdfengines/convert
|
Feature: /forms/pdfengines/convert
|
||||||
|
|
||||||
Scenario: POST /forms/pdfengines/convert (Single PDF/A-1b)
|
Scenario: POST /forms/pdfengines/convert (Single PDF/A-1b)
|
||||||
@@ -115,6 +117,7 @@ Feature: /forms/pdfengines/convert
|
|||||||
Then the Gotenberg container should log the following entries:
|
Then the Gotenberg container should log the following entries:
|
||||||
| "trace":"forms_pdfengines_convert" |
|
| "trace":"forms_pdfengines_convert" |
|
||||||
|
|
||||||
|
@output-filename
|
||||||
Scenario: POST /forms/pdfengines/convert (Output Filename - Single PDF)
|
Scenario: POST /forms/pdfengines/convert (Output Filename - Single PDF)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/convert" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/convert" endpoint with the following form data and header(s):
|
||||||
@@ -126,6 +129,7 @@ Feature: /forms/pdfengines/convert
|
|||||||
Then there should be the following file(s) in the response:
|
Then there should be the following file(s) in the response:
|
||||||
| foo.pdf |
|
| foo.pdf |
|
||||||
|
|
||||||
|
@output-filename
|
||||||
Scenario: POST /forms/pdfengines/convert (Output Filename - Many PDFs)
|
Scenario: POST /forms/pdfengines/convert (Output Filename - Many PDFs)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/convert" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/convert" endpoint with the following form data and header(s):
|
||||||
@@ -140,6 +144,7 @@ Feature: /forms/pdfengines/convert
|
|||||||
| page_1.pdf |
|
| page_1.pdf |
|
||||||
| page_2.pdf |
|
| page_2.pdf |
|
||||||
|
|
||||||
|
@download-from
|
||||||
Scenario: POST /forms/pdfengines/convert (Download From)
|
Scenario: POST /forms/pdfengines/convert (Download From)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -150,6 +155,7 @@ Feature: /forms/pdfengines/convert
|
|||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
Then the response header "Content-Type" should be "application/pdf"
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
|
||||||
|
@webhook
|
||||||
Scenario: POST /forms/pdfengines/convert (Webhook)
|
Scenario: POST /forms/pdfengines/convert (Webhook)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a webhook server
|
Given I have a webhook server
|
||||||
|
|||||||
72
test/integration/features/pdfengines_embed.feature
Normal file
72
test/integration/features/pdfengines_embed.feature
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
@pdfengines
|
||||||
|
@pdfengines-embed
|
||||||
|
@embed
|
||||||
|
Feature: /forms/pdfengines/embed
|
||||||
|
|
||||||
|
Scenario: POST /forms/pdfengines/embed
|
||||||
|
Given I have a default Gotenberg container
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/embed" endpoint with the following form data and header(s):
|
||||||
|
| files | testdata/page_1.pdf | file |
|
||||||
|
| embeds | testdata/embed_1.xml | file |
|
||||||
|
| embeds | testdata/embed_2.xml | file |
|
||||||
|
Then the response status code should be 200
|
||||||
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
Then there should be 1 PDF(s) in the response
|
||||||
|
Then there should be the following file(s) in the response:
|
||||||
|
| page_1.pdf |
|
||||||
|
Then the response PDF(s) should have the "embed_1.xml" file embedded
|
||||||
|
Then the response PDF(s) should have the "embed_2.xml" file embedded
|
||||||
|
|
||||||
|
@download-from
|
||||||
|
Scenario: POST /forms/pdfengines/embed with (Download From)
|
||||||
|
Given I have a default Gotenberg container
|
||||||
|
Given I have a static server
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/embed" endpoint with the following form data and header(s):
|
||||||
|
| files | testdata/page_1.pdf | file |
|
||||||
|
| downloadFrom | [{"url":"http://host.docker.internal:%d/static/testdata/embed_1.xml","embedded": true},{"url":"http://host.docker.internal:%d/static/testdata/embed_2.xml","embedded": false}] | field |
|
||||||
|
Then the response status code should be 200
|
||||||
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
Then there should be 1 PDF(s) in the response
|
||||||
|
Then there should be the following file(s) in the response:
|
||||||
|
| page_1.pdf |
|
||||||
|
Then the response PDF(s) should have the "embed_1.xml" file embedded
|
||||||
|
Then the response PDF(s) should NOT have the "embed_2.xml" file embedded
|
||||||
|
|
||||||
|
@webhook
|
||||||
|
Scenario: POST /forms/pdfengines/embed (Webhook)
|
||||||
|
Given I have a default Gotenberg container
|
||||||
|
Given I have a webhook server
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/embed" endpoint with the following form data and header(s):
|
||||||
|
| files | testdata/page_1.pdf | file |
|
||||||
|
| embeds | testdata/embed_1.xml | file |
|
||||||
|
| embeds | testdata/embed_2.xml | file |
|
||||||
|
| Gotenberg-Webhook-Url | http://host.docker.internal:%d/webhook | header |
|
||||||
|
| Gotenberg-Webhook-Error-Url | http://host.docker.internal:%d/webhook/error | header |
|
||||||
|
Then the response status code should be 204
|
||||||
|
When I wait for the asynchronous request to the webhook
|
||||||
|
Then the webhook request header "Content-Type" should be "application/pdf"
|
||||||
|
Then there should be 1 PDF(s) in the webhook request
|
||||||
|
Then the webhook request PDF(s) should have the "embed_1.xml" file embedded
|
||||||
|
Then the webhook request PDF(s) should have the "embed_2.xml" file embedded
|
||||||
|
|
||||||
|
Scenario: POST /forms/pdfengines/embed (Basic Auth)
|
||||||
|
Given I have a Gotenberg container with the following environment variable(s):
|
||||||
|
| API_ENABLE_BASIC_AUTH | true |
|
||||||
|
| GOTENBERG_API_BASIC_AUTH_USERNAME | foo |
|
||||||
|
| GOTENBERG_API_BASIC_AUTH_PASSWORD | bar |
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/embed" endpoint with the following form data and header(s):
|
||||||
|
| files | testdata/page_1.pdf | file |
|
||||||
|
| embeds | testdata/embed_1.xml | file |
|
||||||
|
| embeds | testdata/embed_2.xml | file |
|
||||||
|
Then the response status code should be 401
|
||||||
|
|
||||||
|
Scenario: POST /foo/forms/pdfengines/embed (Root Path)
|
||||||
|
Given I have a Gotenberg container with the following environment variable(s):
|
||||||
|
| API_ENABLE_DEBUG_ROUTE | true |
|
||||||
|
| API_ROOT_PATH | /foo/ |
|
||||||
|
When I make a "POST" request to Gotenberg at the "/foo/forms/pdfengines/embed" endpoint with the following form data and header(s):
|
||||||
|
| files | testdata/page_1.pdf | file |
|
||||||
|
| embeds | testdata/embed_1.xml | file |
|
||||||
|
| embeds | testdata/embed_2.xml | file |
|
||||||
|
Then the response status code should be 200
|
||||||
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
@pdfengines
|
||||||
|
@pdfengines-encrypt
|
||||||
|
@encrypt
|
||||||
Feature: /forms/pdfengines/encrypt
|
Feature: /forms/pdfengines/encrypt
|
||||||
|
|
||||||
Scenario: POST /forms/pdfengines/encrypt (default - user password only)
|
Scenario: POST /forms/pdfengines/encrypt (default - user password only)
|
||||||
@@ -132,6 +135,7 @@ Feature: /forms/pdfengines/encrypt
|
|||||||
Then the Gotenberg container should log the following entries:
|
Then the Gotenberg container should log the following entries:
|
||||||
| "trace":"forms_pdfengines_encrypt" |
|
| "trace":"forms_pdfengines_encrypt" |
|
||||||
|
|
||||||
|
@download-from
|
||||||
Scenario: POST /forms/pdfengines/encrypt (Download From)
|
Scenario: POST /forms/pdfengines/encrypt (Download From)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -143,6 +147,7 @@ Feature: /forms/pdfengines/encrypt
|
|||||||
Then there should be 1 PDF(s) in the response
|
Then there should be 1 PDF(s) in the response
|
||||||
Then the response PDF(s) should be encrypted
|
Then the response PDF(s) should be encrypted
|
||||||
|
|
||||||
|
@webhook
|
||||||
Scenario: POST /forms/pdfengines/encrypt (Webhook)
|
Scenario: POST /forms/pdfengines/encrypt (Webhook)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a webhook server
|
Given I have a webhook server
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
@pdfengines
|
||||||
|
@pdfengines-flatten
|
||||||
|
@flatten
|
||||||
Feature: /forms/pdfengines/flatten
|
Feature: /forms/pdfengines/flatten
|
||||||
|
|
||||||
Scenario: POST /forms/pdfengines/flatten (Single PDF)
|
Scenario: POST /forms/pdfengines/flatten (Single PDF)
|
||||||
@@ -48,6 +51,7 @@ Feature: /forms/pdfengines/flatten
|
|||||||
Then the Gotenberg container should log the following entries:
|
Then the Gotenberg container should log the following entries:
|
||||||
| "trace":"forms_pdfengines_flatten" |
|
| "trace":"forms_pdfengines_flatten" |
|
||||||
|
|
||||||
|
@output-filename
|
||||||
Scenario: POST /forms/pdfengines/flatten (Output Filename - Single PDF)
|
Scenario: POST /forms/pdfengines/flatten (Output Filename - Single PDF)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/flatten" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/flatten" endpoint with the following form data and header(s):
|
||||||
@@ -58,6 +62,7 @@ Feature: /forms/pdfengines/flatten
|
|||||||
Then there should be the following file(s) in the response:
|
Then there should be the following file(s) in the response:
|
||||||
| foo.pdf |
|
| foo.pdf |
|
||||||
|
|
||||||
|
@output-filename
|
||||||
Scenario: POST /forms/pdfengines/flatten (Output Filename - Many PDFs)
|
Scenario: POST /forms/pdfengines/flatten (Output Filename - Many PDFs)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/flatten" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/flatten" endpoint with the following form data and header(s):
|
||||||
@@ -71,6 +76,7 @@ Feature: /forms/pdfengines/flatten
|
|||||||
| page_1.pdf |
|
| page_1.pdf |
|
||||||
| page_2.pdf |
|
| page_2.pdf |
|
||||||
|
|
||||||
|
@download-from
|
||||||
Scenario: POST /forms/pdfengines/flatten (Download From)
|
Scenario: POST /forms/pdfengines/flatten (Download From)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -81,6 +87,7 @@ Feature: /forms/pdfengines/flatten
|
|||||||
Then the response header "Content-Type" should be "application/pdf"
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
Then the response PDF(s) should be flatten
|
Then the response PDF(s) should be flatten
|
||||||
|
|
||||||
|
@webhook
|
||||||
Scenario: POST /forms/pdfengines/flatten (Webhook)
|
Scenario: POST /forms/pdfengines/flatten (Webhook)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a webhook server
|
Given I have a webhook server
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
@pdfengines
|
||||||
|
@pdfengines-encrypt
|
||||||
|
@merge
|
||||||
Feature: /forms/pdfengines/merge
|
Feature: /forms/pdfengines/merge
|
||||||
|
|
||||||
Scenario: POST /forms/pdfengines/merge (default)
|
Scenario: POST /forms/pdfengines/merge (default)
|
||||||
@@ -128,6 +131,7 @@ Feature: /forms/pdfengines/merge
|
|||||||
Invalid form data: form field 'metadata' is invalid (got 'foo', resulting to unmarshal metadata: invalid character 'o' in literal false (expecting 'a'))
|
Invalid form data: form field 'metadata' is invalid (got 'foo', resulting to unmarshal metadata: invalid character 'o' in literal false (expecting 'a'))
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@convert
|
||||||
Scenario: POST /forms/pdfengines/merge (PDF/A-1b & PDF/UA-1)
|
Scenario: POST /forms/pdfengines/merge (PDF/A-1b & PDF/UA-1)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/merge" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/merge" endpoint with the following form data and header(s):
|
||||||
@@ -153,6 +157,7 @@ Feature: /forms/pdfengines/merge
|
|||||||
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 1 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 1 failed rule(s)
|
||||||
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
||||||
|
|
||||||
|
@metadata
|
||||||
Scenario: POST /forms/pdfengines/merge (Metadata)
|
Scenario: POST /forms/pdfengines/merge (Metadata)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/merge" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/merge" endpoint with the following form data and header(s):
|
||||||
@@ -198,6 +203,7 @@ Feature: /forms/pdfengines/merge
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@flatten
|
||||||
Scenario: POST /forms/pdfengines/merge (Flatten)
|
Scenario: POST /forms/pdfengines/merge (Flatten)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/merge" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/merge" endpoint with the following form data and header(s):
|
||||||
@@ -221,6 +227,7 @@ Feature: /forms/pdfengines/merge
|
|||||||
"""
|
"""
|
||||||
Then the response PDF(s) should be flatten
|
Then the response PDF(s) should be flatten
|
||||||
|
|
||||||
|
@encrypt
|
||||||
Scenario: POST /forms/pdfengines/merge (Encrypt - user password only)
|
Scenario: POST /forms/pdfengines/merge (Encrypt - user password only)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/merge" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/merge" endpoint with the following form data and header(s):
|
||||||
@@ -232,6 +239,7 @@ Feature: /forms/pdfengines/merge
|
|||||||
Then there should be 1 PDF(s) in the response
|
Then there should be 1 PDF(s) in the response
|
||||||
Then the response PDF(s) should be encrypted
|
Then the response PDF(s) should be encrypted
|
||||||
|
|
||||||
|
@encrypt
|
||||||
Scenario: POST /forms/pdfengines/merge (Encrypt - both user and owner passwords)
|
Scenario: POST /forms/pdfengines/merge (Encrypt - both user and owner passwords)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/merge" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/merge" endpoint with the following form data and header(s):
|
||||||
@@ -244,8 +252,25 @@ Feature: /forms/pdfengines/merge
|
|||||||
Then there should be 1 PDF(s) in the response
|
Then there should be 1 PDF(s) in the response
|
||||||
Then the response PDF(s) should be encrypted
|
Then the response PDF(s) should be encrypted
|
||||||
|
|
||||||
|
@embed
|
||||||
|
Scenario: POST /foo/forms/pdfengines/merge (Embeds)
|
||||||
|
Given I have a default Gotenberg container
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/merge" endpoint with the following form data and header(s):
|
||||||
|
| files | testdata/page_1.pdf | file |
|
||||||
|
| files | testdata/page_2.pdf | file |
|
||||||
|
| embeds | testdata/embed_1.xml | file |
|
||||||
|
| embeds | testdata/embed_2.xml | file |
|
||||||
|
| Gotenberg-Output-Filename | foo | header |
|
||||||
|
Then the response status code should be 200
|
||||||
|
Then the response PDF(s) should have the "embed_1.xml" file embedded
|
||||||
|
Then the response PDF(s) should have the "embed_2.xml" file embedded
|
||||||
|
|
||||||
# FIXME: once decrypt is done, add encrypt and check after the content of the PDF.
|
# FIXME: once decrypt is done, add encrypt and check after the content of the PDF.
|
||||||
Scenario: POST /forms/pdfengines/merge (PDF/A-1b & PDF/UA-1 & Metadata & Flatten)
|
@convert
|
||||||
|
@metadata
|
||||||
|
@flatten
|
||||||
|
@embed
|
||||||
|
Scenario: POST /forms/pdfengines/merge (PDF/A-1b & PDF/UA-1 & Metadata & Flatten & Embeds)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/merge" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/merge" endpoint with the following form data and header(s):
|
||||||
| files | testdata/page_1.pdf | file |
|
| files | testdata/page_1.pdf | file |
|
||||||
@@ -254,6 +279,8 @@ Feature: /forms/pdfengines/merge
|
|||||||
| pdfua | true | field |
|
| pdfua | true | field |
|
||||||
| metadata | {"Author":"Julien Neuhart","Copyright":"Julien Neuhart","CreateDate":"2006-09-18T16:27:50-04:00","Creator":"Gotenberg","Keywords":["first","second"],"Marked":true,"ModDate":"2006-09-18T16:27:50-04:00","PDFVersion":1.7,"Producer":"Gotenberg","Subject":"Sample","Title":"Sample","Trapped":"Unknown"} | field |
|
| metadata | {"Author":"Julien Neuhart","Copyright":"Julien Neuhart","CreateDate":"2006-09-18T16:27:50-04:00","Creator":"Gotenberg","Keywords":["first","second"],"Marked":true,"ModDate":"2006-09-18T16:27:50-04:00","PDFVersion":1.7,"Producer":"Gotenberg","Subject":"Sample","Title":"Sample","Trapped":"Unknown"} | field |
|
||||||
| flatten | true | field |
|
| flatten | true | field |
|
||||||
|
| embeds | testdata/embed_1.xml | file |
|
||||||
|
| embeds | testdata/embed_2.xml | file |
|
||||||
| Gotenberg-Output-Filename | foo | header |
|
| Gotenberg-Output-Filename | foo | header |
|
||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
Then the response header "Content-Type" should be "application/pdf"
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
@@ -269,9 +296,11 @@ Feature: /forms/pdfengines/merge
|
|||||||
"""
|
"""
|
||||||
Page 2
|
Page 2
|
||||||
"""
|
"""
|
||||||
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 7 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 10 failed rule(s)
|
||||||
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 2 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 2 failed rule(s)
|
||||||
Then the response PDF(s) should be flatten
|
Then the response PDF(s) should be flatten
|
||||||
|
Then the response PDF(s) should have the "embed_1.xml" file embedded
|
||||||
|
Then the response PDF(s) should have the "embed_2.xml" file embedded
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/metadata/read" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/metadata/read" endpoint with the following form data and header(s):
|
||||||
| files | teststore/foo.pdf | file |
|
| files | teststore/foo.pdf | file |
|
||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
@@ -316,6 +345,7 @@ Feature: /forms/pdfengines/merge
|
|||||||
Then the Gotenberg container should log the following entries:
|
Then the Gotenberg container should log the following entries:
|
||||||
| "trace":"forms_pdfengines_merge" |
|
| "trace":"forms_pdfengines_merge" |
|
||||||
|
|
||||||
|
@download-from
|
||||||
Scenario: POST /forms/pdfengines/merge (Download From)
|
Scenario: POST /forms/pdfengines/merge (Download From)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -324,6 +354,7 @@ Feature: /forms/pdfengines/merge
|
|||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
Then the response header "Content-Type" should be "application/pdf"
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
|
||||||
|
@webhook
|
||||||
Scenario: POST /forms/pdfengines/merge (Webhook)
|
Scenario: POST /forms/pdfengines/merge (Webhook)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a webhook server
|
Given I have a webhook server
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
@pdfengines
|
||||||
|
@pdfengines-metadata
|
||||||
|
@metadata
|
||||||
Feature: /forms/pdfengines/{write|read}
|
Feature: /forms/pdfengines/{write|read}
|
||||||
|
|
||||||
Scenario: POST /forms/pdfengines/metadata/{write|read} (Single PDF)
|
Scenario: POST /forms/pdfengines/metadata/{write|read} (Single PDF)
|
||||||
@@ -151,6 +154,7 @@ Feature: /forms/pdfengines/{write|read}
|
|||||||
Then the Gotenberg container should log the following entries:
|
Then the Gotenberg container should log the following entries:
|
||||||
| "trace":"forms_pdfengines_metadata_read" |
|
| "trace":"forms_pdfengines_metadata_read" |
|
||||||
|
|
||||||
|
@output-filename
|
||||||
Scenario: POST /forms/pdfengines/metadata/write (Output Filename - Single PDF)
|
Scenario: POST /forms/pdfengines/metadata/write (Output Filename - Single PDF)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/metadata/write" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/metadata/write" endpoint with the following form data and header(s):
|
||||||
@@ -162,6 +166,7 @@ Feature: /forms/pdfengines/{write|read}
|
|||||||
Then there should be the following file(s) in the response:
|
Then there should be the following file(s) in the response:
|
||||||
| foo.pdf |
|
| foo.pdf |
|
||||||
|
|
||||||
|
@output-filename
|
||||||
Scenario: POST /forms/pdfengines/metadata/write (Output Filename - Many PDFs)
|
Scenario: POST /forms/pdfengines/metadata/write (Output Filename - Many PDFs)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/metadata/write" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/metadata/write" endpoint with the following form data and header(s):
|
||||||
@@ -176,6 +181,7 @@ Feature: /forms/pdfengines/{write|read}
|
|||||||
| page_1.pdf |
|
| page_1.pdf |
|
||||||
| page_2.pdf |
|
| page_2.pdf |
|
||||||
|
|
||||||
|
@download-from
|
||||||
Scenario: POST /forms/pdfengines/metadata/write (Download From)
|
Scenario: POST /forms/pdfengines/metadata/write (Download From)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -187,6 +193,7 @@ Feature: /forms/pdfengines/{write|read}
|
|||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
Then the response header "Content-Type" should be "application/pdf"
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
|
||||||
|
@download-from
|
||||||
Scenario: POST /forms/pdfengines/metadata/read (Download From)
|
Scenario: POST /forms/pdfengines/metadata/read (Download From)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -196,6 +203,7 @@ Feature: /forms/pdfengines/{write|read}
|
|||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
Then the response header "Content-Type" should be "application/json"
|
Then the response header "Content-Type" should be "application/json"
|
||||||
|
|
||||||
|
@webhook
|
||||||
Scenario: POST /forms/pdfengines/metadata/write (Webhook)
|
Scenario: POST /forms/pdfengines/metadata/write (Webhook)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a webhook server
|
Given I have a webhook server
|
||||||
@@ -233,6 +241,7 @@ Feature: /forms/pdfengines/{write|read}
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@webhook
|
||||||
Scenario: POST /forms/pdfengines/metadata/read (Webhook)
|
Scenario: POST /forms/pdfengines/metadata/read (Webhook)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a webhook server
|
Given I have a webhook server
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
@pdfengines
|
||||||
|
@pdfengines-split
|
||||||
|
@split
|
||||||
Feature: /forms/pdfengines/split
|
Feature: /forms/pdfengines/split
|
||||||
|
|
||||||
Scenario: POST /forms/pdfengines/split (Intervals - Default)
|
Scenario: POST /forms/pdfengines/split (Intervals - Default)
|
||||||
@@ -314,6 +317,7 @@ Feature: /forms/pdfengines/split
|
|||||||
Invalid form data: form field 'metadata' is invalid (got 'foo', resulting to unmarshal metadata: invalid character 'o' in literal false (expecting 'a'))
|
Invalid form data: form field 'metadata' is invalid (got 'foo', resulting to unmarshal metadata: invalid character 'o' in literal false (expecting 'a'))
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@convert
|
||||||
Scenario: POST /forms/pdfengines/split (PDF/A-1b & PDF/UA-1)
|
Scenario: POST /forms/pdfengines/split (PDF/A-1b & PDF/UA-1)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/split" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/split" endpoint with the following form data and header(s):
|
||||||
@@ -345,6 +349,7 @@ Feature: /forms/pdfengines/split
|
|||||||
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 1 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 1 failed rule(s)
|
||||||
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 3 failed rule(s)
|
||||||
|
|
||||||
|
@metadata
|
||||||
Scenario: POST /forms/pdfengines/split (Metadata)
|
Scenario: POST /forms/pdfengines/split (Metadata)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/split" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/split" endpoint with the following form data and header(s):
|
||||||
@@ -411,6 +416,7 @@ Feature: /forms/pdfengines/split
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@flatten
|
||||||
Scenario: POST /forms/pdfengines/split (Flatten)
|
Scenario: POST /forms/pdfengines/split (Flatten)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/split" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/split" endpoint with the following form data and header(s):
|
||||||
@@ -440,6 +446,7 @@ Feature: /forms/pdfengines/split
|
|||||||
"""
|
"""
|
||||||
Then the response PDF(s) should be flatten
|
Then the response PDF(s) should be flatten
|
||||||
|
|
||||||
|
@encrypt
|
||||||
Scenario: POST /forms/pdfengines/split (Encrypt - user password only)
|
Scenario: POST /forms/pdfengines/split (Encrypt - user password only)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/split" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/split" endpoint with the following form data and header(s):
|
||||||
@@ -452,6 +459,7 @@ Feature: /forms/pdfengines/split
|
|||||||
Then there should be 2 PDF(s) in the response
|
Then there should be 2 PDF(s) in the response
|
||||||
Then the response PDF(s) should be encrypted
|
Then the response PDF(s) should be encrypted
|
||||||
|
|
||||||
|
@encrypt
|
||||||
Scenario: POST /forms/pdfengines/split (Encrypt - both user and owner passwords)
|
Scenario: POST /forms/pdfengines/split (Encrypt - both user and owner passwords)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/split" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/split" endpoint with the following form data and header(s):
|
||||||
@@ -465,8 +473,30 @@ Feature: /forms/pdfengines/split
|
|||||||
Then there should be 2 PDF(s) in the response
|
Then there should be 2 PDF(s) in the response
|
||||||
Then the response PDF(s) should be encrypted
|
Then the response PDF(s) should be encrypted
|
||||||
|
|
||||||
|
@embed
|
||||||
|
Scenario: POST /foo/forms/pdfengines/split (Embeds)
|
||||||
|
Given I have a default Gotenberg container
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/split" endpoint with the following form data and header(s):
|
||||||
|
| files | testdata/pages_3.pdf | file |
|
||||||
|
| embeds | testdata/embed_1.xml | file |
|
||||||
|
| embeds | testdata/embed_2.xml | file |
|
||||||
|
| splitMode | intervals | field |
|
||||||
|
| splitSpan | 2 | field |
|
||||||
|
Then the response status code should be 200
|
||||||
|
And the response header "Content-Type" should be "application/zip"
|
||||||
|
And there should be 2 PDF(s) in the response
|
||||||
|
And there should be the following file(s) in the response:
|
||||||
|
| pages_3_0.pdf |
|
||||||
|
| pages_3_1.pdf |
|
||||||
|
Then the response PDF(s) should have the "embed_1.xml" file embedded
|
||||||
|
Then the response PDF(s) should have the "embed_2.xml" file embedded
|
||||||
|
|
||||||
# FIXME: once decrypt is done, add encrypt and check after the content of the PDFs.
|
# FIXME: once decrypt is done, add encrypt and check after the content of the PDFs.
|
||||||
Scenario: POST /forms/pdfengines/split (PDF/A-1b & PDF/UA-1 & Metadata & Flatten)
|
@convert
|
||||||
|
@metadata
|
||||||
|
@flatten
|
||||||
|
@embed
|
||||||
|
Scenario: POST /forms/pdfengines/split (PDF/A-1b & PDF/UA-1 & Metadata & Flatten & Embeds)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/split" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/split" endpoint with the following form data and header(s):
|
||||||
| files | testdata/pages_3.pdf | file |
|
| files | testdata/pages_3.pdf | file |
|
||||||
@@ -476,6 +506,8 @@ Feature: /forms/pdfengines/split
|
|||||||
| pdfua | true | field |
|
| pdfua | true | field |
|
||||||
| metadata | {"Author":"Julien Neuhart","Copyright":"Julien Neuhart","CreateDate":"2006-09-18T16:27:50-04:00","Creator":"Gotenberg","Keywords":["first","second"],"Marked":true,"ModDate":"2006-09-18T16:27:50-04:00","PDFVersion":1.7,"Producer":"Gotenberg","Subject":"Sample","Title":"Sample","Trapped":"Unknown"} | field |
|
| metadata | {"Author":"Julien Neuhart","Copyright":"Julien Neuhart","CreateDate":"2006-09-18T16:27:50-04:00","Creator":"Gotenberg","Keywords":["first","second"],"Marked":true,"ModDate":"2006-09-18T16:27:50-04:00","PDFVersion":1.7,"Producer":"Gotenberg","Subject":"Sample","Title":"Sample","Trapped":"Unknown"} | field |
|
||||||
| flatten | true | field |
|
| flatten | true | field |
|
||||||
|
| embeds | testdata/embed_1.xml | file |
|
||||||
|
| embeds | testdata/embed_2.xml | file |
|
||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
Then the response header "Content-Type" should be "application/zip"
|
Then the response header "Content-Type" should be "application/zip"
|
||||||
Then there should be 2 PDF(s) in the response
|
Then there should be 2 PDF(s) in the response
|
||||||
@@ -496,9 +528,11 @@ Feature: /forms/pdfengines/split
|
|||||||
"""
|
"""
|
||||||
Page 3
|
Page 3
|
||||||
"""
|
"""
|
||||||
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 7 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/A-1b" with a tolerance of 10 failed rule(s)
|
||||||
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 2 failed rule(s)
|
Then the response PDF(s) should be valid "PDF/UA-1" with a tolerance of 2 failed rule(s)
|
||||||
Then the response PDF(s) should be flatten
|
Then the response PDF(s) should be flatten
|
||||||
|
Then the response PDF(s) should have the "embed_1.xml" file embedded
|
||||||
|
Then the response PDF(s) should have the "embed_2.xml" file embedded
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/metadata/read" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/metadata/read" endpoint with the following form data and header(s):
|
||||||
| files | teststore/pages_3_0.pdf | file |
|
| files | teststore/pages_3_0.pdf | file |
|
||||||
| files | teststore/pages_3_1.pdf | file |
|
| files | teststore/pages_3_1.pdf | file |
|
||||||
@@ -560,6 +594,7 @@ Feature: /forms/pdfengines/split
|
|||||||
Then the Gotenberg container should log the following entries:
|
Then the Gotenberg container should log the following entries:
|
||||||
| "trace":"forms_pdfengines_split" |
|
| "trace":"forms_pdfengines_split" |
|
||||||
|
|
||||||
|
@output-filename
|
||||||
Scenario: POST /forms/pdfengines/split (Output Filename - Single PDF)
|
Scenario: POST /forms/pdfengines/split (Output Filename - Single PDF)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/split" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/split" endpoint with the following form data and header(s):
|
||||||
@@ -573,6 +608,7 @@ Feature: /forms/pdfengines/split
|
|||||||
Then there should be the following file(s) in the response:
|
Then there should be the following file(s) in the response:
|
||||||
| foo.pdf |
|
| foo.pdf |
|
||||||
|
|
||||||
|
@output-filename
|
||||||
Scenario: POST /forms/pdfengines/split (Output Filename - Many PDFs)
|
Scenario: POST /forms/pdfengines/split (Output Filename - Many PDFs)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/split" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/pdfengines/split" endpoint with the following form data and header(s):
|
||||||
@@ -587,6 +623,7 @@ Feature: /forms/pdfengines/split
|
|||||||
| pages_3_0.pdf |
|
| pages_3_0.pdf |
|
||||||
| pages_3_1.pdf |
|
| pages_3_1.pdf |
|
||||||
|
|
||||||
|
@download-from
|
||||||
Scenario: POST /forms/pdfengines/split (Download From)
|
Scenario: POST /forms/pdfengines/split (Download From)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -598,6 +635,7 @@ Feature: /forms/pdfengines/split
|
|||||||
Then the file request header "X-Foo" should be "bar"
|
Then the file request header "X-Foo" should be "bar"
|
||||||
Then the response header "Content-Type" should be "application/zip"
|
Then the response header "Content-Type" should be "application/zip"
|
||||||
|
|
||||||
|
@webhook
|
||||||
Scenario: POST /forms/pdfengines/split (Webhook)
|
Scenario: POST /forms/pdfengines/split (Webhook)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a webhook server
|
Given I have a webhook server
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
# 1. Count restarts.
|
# 1. Count restarts.
|
||||||
# 2. Count queue size.
|
# 2. Count queue size.
|
||||||
|
|
||||||
|
@prometheus-metrics
|
||||||
Feature: /prometheus/metrics
|
Feature: /prometheus/metrics
|
||||||
|
|
||||||
Scenario: GET /prometheus/metrics (Enabled)
|
Scenario: GET /prometheus/metrics (Enabled)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
@root
|
||||||
Feature: /
|
Feature: /
|
||||||
|
|
||||||
Scenario: GET /
|
Scenario: GET /
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
@version
|
||||||
Feature: /version
|
Feature: /version
|
||||||
|
|
||||||
Scenario: GET /version
|
Scenario: GET /version
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
# 1. Other HTTP Methods
|
# 1. Other HTTP Methods
|
||||||
# 2. Errors
|
# 2. Errors
|
||||||
|
|
||||||
|
@webhook
|
||||||
Feature: Webhook
|
Feature: Webhook
|
||||||
|
|
||||||
Scenario: Default
|
Scenario: Default
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ func TestMain(m *testing.M) {
|
|||||||
version := flag.String("gotenberg-version", "", "")
|
version := flag.String("gotenberg-version", "", "")
|
||||||
platform := flag.String("gotenberg-container-platform", "", "")
|
platform := flag.String("gotenberg-container-platform", "", "")
|
||||||
noConcurrency := flag.Bool("no-concurrency", false, "")
|
noConcurrency := flag.Bool("no-concurrency", false, "")
|
||||||
|
tags := flag.String("tags", "", "")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if *platform == "" {
|
if *platform == "" {
|
||||||
@@ -47,6 +48,7 @@ func TestMain(m *testing.M) {
|
|||||||
Paths: []string{"features"},
|
Paths: []string{"features"},
|
||||||
Output: colors.Colored(os.Stdout),
|
Output: colors.Colored(os.Stdout),
|
||||||
Concurrency: concurrency,
|
Concurrency: concurrency,
|
||||||
|
Tags: *tags,
|
||||||
},
|
},
|
||||||
}.Run()
|
}.Run()
|
||||||
|
|
||||||
|
|||||||
@@ -891,6 +891,60 @@ func (s *scenario) thePdfsShouldBeEncrypted(ctx context.Context, kind string, sh
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *scenario) thePdfsShouldHaveEmbeddedFile(ctx context.Context, kind, should, embed string) error {
|
||||||
|
dirPath := fmt.Sprintf("%s/%s", s.workdir, s.resp.Header().Get("Gotenberg-Trace"))
|
||||||
|
|
||||||
|
_, err := os.Stat(dirPath)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return fmt.Errorf("directory %q does not exist", dirPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
var paths []string
|
||||||
|
err = filepath.Walk(dirPath, func(path string, info os.FileInfo, pathErr error) error {
|
||||||
|
if pathErr != nil {
|
||||||
|
return pathErr
|
||||||
|
}
|
||||||
|
if strings.EqualFold(filepath.Ext(info.Name()), ".pdf") {
|
||||||
|
paths = append(paths, path)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("walk %q: %w", dirPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
invert := should == "should NOT"
|
||||||
|
|
||||||
|
for _, path := range paths {
|
||||||
|
cmd := []string{
|
||||||
|
"verapdf",
|
||||||
|
"--off",
|
||||||
|
"--loglevel",
|
||||||
|
"0",
|
||||||
|
"--extract",
|
||||||
|
"embeddedFile",
|
||||||
|
filepath.Base(path),
|
||||||
|
}
|
||||||
|
|
||||||
|
output, err := execCommandInIntegrationToolsContainer(ctx, cmd, path)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("exec %q: %w", cmd, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
found := strings.Contains(output, fmt.Sprintf("<fileName>%s</fileName>", embed))
|
||||||
|
|
||||||
|
if invert && found {
|
||||||
|
return fmt.Errorf("embed %q found", embed)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !invert && !found {
|
||||||
|
return fmt.Errorf("embed %q not found", embed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func InitializeScenario(ctx *godog.ScenarioContext) {
|
func InitializeScenario(ctx *godog.ScenarioContext) {
|
||||||
s := &scenario{}
|
s := &scenario{}
|
||||||
ctx.Before(func(ctx context.Context, sc *godog.Scenario) (context.Context, error) {
|
ctx.Before(func(ctx context.Context, sc *godog.Scenario) (context.Context, error) {
|
||||||
@@ -924,6 +978,7 @@ func InitializeScenario(ctx *godog.ScenarioContext) {
|
|||||||
ctx.Then(`^the (response|webhook request) PDF\(s\) should be valid "([^"]*)" with a tolerance of (\d+) failed rule\(s\)$`, s.thePdfsShouldBeValidWithAToleranceOf)
|
ctx.Then(`^the (response|webhook request) PDF\(s\) should be valid "([^"]*)" with a tolerance of (\d+) failed rule\(s\)$`, s.thePdfsShouldBeValidWithAToleranceOf)
|
||||||
ctx.Then(`^the (response|webhook request) PDF\(s\) (should|should NOT) be flatten$`, s.thePdfsShouldBeFlatten)
|
ctx.Then(`^the (response|webhook request) PDF\(s\) (should|should NOT) be flatten$`, s.thePdfsShouldBeFlatten)
|
||||||
ctx.Then(`^the (response|webhook request) PDF\(s\) (should|should NOT) be encrypted`, s.thePdfsShouldBeEncrypted)
|
ctx.Then(`^the (response|webhook request) PDF\(s\) (should|should NOT) be encrypted`, s.thePdfsShouldBeEncrypted)
|
||||||
|
ctx.Then(`^the (response|webhook request) PDF\(s\) (should|should NOT) have the "([^"]*)" file embedded$`, s.thePdfsShouldHaveEmbeddedFile)
|
||||||
ctx.Then(`^the "([^"]*)" PDF should have (\d+) page\(s\)$`, s.thePdfShouldHavePages)
|
ctx.Then(`^the "([^"]*)" PDF should have (\d+) page\(s\)$`, s.thePdfShouldHavePages)
|
||||||
ctx.Then(`^the "([^"]*)" PDF (should|should NOT) be set to landscape orientation$`, s.thePdfShouldBeSetToLandscapeOrientation)
|
ctx.Then(`^the "([^"]*)" PDF (should|should NOT) be set to landscape orientation$`, s.thePdfShouldBeSetToLandscapeOrientation)
|
||||||
ctx.Then(`^the "([^"]*)" PDF (should|should NOT) have the following content at page (\d+):$`, s.thePdfShouldHaveTheFollowingContentAtPage)
|
ctx.Then(`^the "([^"]*)" PDF (should|should NOT) have the following content at page (\d+):$`, s.thePdfShouldHaveTheFollowingContentAtPage)
|
||||||
|
|||||||
5
test/integration/testdata/embed_1.xml
vendored
Normal file
5
test/integration/testdata/embed_1.xml
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<xml>
|
||||||
|
<test>test 1.1</test>
|
||||||
|
<test>test 1.2</test>
|
||||||
|
<test>test 1.3</test>
|
||||||
|
</xml>
|
||||||
5
test/integration/testdata/embed_2.xml
vendored
Normal file
5
test/integration/testdata/embed_2.xml
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<xml>
|
||||||
|
<test>test 2.1</test>
|
||||||
|
<test>test 2.2</test>
|
||||||
|
<test>test 2.3</test>
|
||||||
|
</xml>
|
||||||
Reference in New Issue
Block a user