Self-hosted PDF compression service built to run in a docker container. Uses Ghostscript to compress PDF files and exposes an API and webhook calles for interacting with it. Support for direct interactions with S3. This service is not intended to be user-facing, but being called by backend services.
Instead of embedding Ghostscript directly, you can put compression behind a service. Allowing for dedicated servers for compressiong and better horizontal scaling.
This is ideal for microservices architectures, serverless apps, or backend processing workers.
Also it's cool?
- Inline - sync request/response.
- Webhook - async processing with sccess / error callbacks to a webhook.
- S3 - compress files stored in S3 and write results back into buckets via pre-signed urls.
Secure API access using 3rd party signed JSON Web Tokens.
Runs in a containerized environment for ease of deployment and scaling.
Keep in mind the service keeps track of running tasks and will not allow more than WORKERS number of tasks at once (defaults to 10). This should be adjusted based on server resources. Any requests that happen when queue is full will be DROPPED with 503.
POST /process/inline
Compress a PDF and return it directly in the response. The body should be either binary application/pdf or multipart/form-data with file field.
- quality - One of
screen | ebook | printer | prepress | defaultpresets used in ghostscript.
- Trace - Unique ID for this request (Not much point of it for inline, but added for consistency)
- 200 OK - compressed PDF binary.
- 4xx/5xx - error object.
POST /process/webhook
Compress a PDF and get back to your service via webhook on success / error. The body should be either binary application/pdf or multipart/form-data with file field.
- quality - One of
screen | ebook | printer | prepress | defaultpresets used in ghostscript.
- ghostscript-reply-to - Url for success webhook.
- ghostscript-report-to - Url for error webhook.
- trace - (Optional) Unique ID for the task. Will be generated if not provided.
- Trace - Provided or generated unique ID for the task.
{
trace: "123"
}
- Trace - Provided or generated unique ID for the task.
POST /process/s3
Tell the service to compress a PDF either sent as body or stored in S3 and write result directly into S3 via presigned url.
multipart/form-data body with either source field which contains pre-signed URL to a file in S3 storage or file field with raw file to compress. file field has priority if both are provided.
Requires destination field with pre-signed URL to upload the file into S3. Keep in mind the URL has to have long enough expiry time.
Uses webhooks to get back and report to your app. There's no inline request/response support for S3.
- quality - One of
screen | ebook | printer | prepress | defaultpresets used in ghostscript.
- ghostscript-reply-to - Url for success webhook.
- ghostscript-report-to - Url for error webhook.
- trace - (Optional) Unique ID for the task. Will be generated if not provided.
- Trace - Provided or generated unique ID for the task.
{
trace: "123"
}
PDF Ghostpress supports JWT (JSON Web Token) authentication.
To enable JWT authentication, set env variable JWT_ENABLE to true and create a public.key file inside /srv/certs volume. private.key is not required for JWT to work, but if provided, the container will create and log a signed token on startup.
Important: JWT authentication is optional.
If no valid public RSA key is found, authentication will be DISABLED.
Enabling JWT Authentication will enable it for ALL endpoints excluding /health.
The service doesn't care about any token contents. As long as it's signed and valid it'll accept it.
Include the token as a Bearer token:
Authorization: Bearer <signed_jwt_token>
import { createSigner } from "fast-jwt"
const signer = createSigner({
key: privateKey,
iss: "internal-service"
expiresIn: 60 * 60 * 1000 // 1 hour
})
const token = await signer({
'quack': 'Quack!' // this doesn't matter
})
console.log(token)More info on using the container is on the docker hub
I'll appreciate any issues and contributions.
Due to inclusion of Ghostscript (AGPL), distribution must comply with AGPL terms.