Categorygithub.com/rntrp/go-fitz-formpost
modulepackage
1.23.7-v20240401
Repository: https://github.com/rntrp/go-fitz-formpost.git
Documentation: pkg.go.dev

# README

Release Go Version Go Report Card Docker Image Tests

Document to Image Formpost Microservice

A microservice based on go-fitz, a Go wrapper for the MuPDF Fitz library. Accepts PDF and EPUB documents via multipart/form-data POST requests, delivers images in response.

Build & Launch

Besides Go 1.22, MuPDF needs to be installed separately.

Locally

Follow build instructions for go-fitz with MuPDF. When linking against shared libraries, one may want to set the CGO_LDFLAGS environment variable.

go-fitz provides prebuilt libraries for common operating systems and acrhitectures. Using those on Ubuntu, macOS or Windows makes building straightforward:

$ go mod download
$ go build -o /go-fitz-formpost

On Alpine Linux this would be:

$ go build -tags musl -o /go-fitz-formpost

Or you can also build and run the application at port 8080:

$ go run .

Alpine still requires the tag:

$ go run -tags musl .

If you are updating the dependencies locally, you may want to update go.sum:

$ go mod download
$ go mod tidy

[!IMPORTANT] Issues with vendoring: Unfortunately go mod vendor does not pull the header files and binaries from the go-fitz repository. This issue is discussed at golang/go/issues/26366. Please stay with go mod download instead.

With Docker

$ docker build --pull --rm -t go-fitz-formpost:latest .
$ docker run --rm -it  -p 8080:8080/tcp go-fitz-formpost:latest

With docker-compose

$ docker-compose up

Usage

Send a multipart/form-data request with a single file named doc to the /convert endpoint. Width and height of the target image is set via the URL query parameters width and height respectively. Optionally, image output format can be specified (jpeg, png, gif, tiff or bmp)

$ curl -F doc=@/path/to/in.pdf -o /path/to/out.png http://localhost:8080/convert?width=200&height=200&format=png

Alternatively, there is also an endpoint serving basic HTML form upload page. It is available under http://localhost:8080 or http://localhost:8080/index.html.

Endpoint Overview

pathmethoddescription
/GETReturns a simple HTML page with form uploads for testing /convert and /pages endpoints.
/index.htmlGETSame as /.
/liveGETLiveness probe endpoint. Returns HTTP 200 while the application is running.
/metricsGETReturns application metrics in Prometheus text-based format collected by the Prometheus Go client library. The endpoint is disabled by default; enabled with FITZ_FORMPOST_ENABLE_PROMETHEUS=true (see Environment Variables below).
/convertPOSTPivotal endpoint within the whole application. Accepts a single document per multipart/form-data request. Converts the document to the requested image format. Target dimensions are specified as part of the URL query string. See Parameters below for further details.
/pagesPOSTAccepts a single document per multipart/form-data request. Returns page count of the document as text/plain; charset=utf-8.
/shutdownPOSTInitiates graceful shutdown of the application when triggered by a POST request with an arbitrary payload. Returns HTTP 204 after the shutdown process has been started. The endpoint is disabled by default; enabled with FITZ_FORMPOST_ENABLE_SHUTDOWN_ENDPOINT=true (see Environment Variables below).

Environment Variables

The application supports configuration via environment variables or a .env file. Environment variables have higher priority.

variabledefaultdescription
FITZ_FORMPOST_ENVdevelopmentCurrently, this setting only affects the .env file precedence, no actual distinction between execution environments is made. Possible values are development, test and production.
FITZ_FORMPOST_ENV_DIRemptyPath to directory containing the .env file. Absolute paths or paths relative to the application folder are possible. If the variable is left empty, .env file is read from the application folder.
FITZ_FORMPOST_TCP_ADDRESS:8080Application TCP address as described by the Golang's http.Server.Addr field, most prominently in form of host:port. See also net package docs.
FITZ_FORMPOST_TEMP_DIROS temp folderPath to directory, where applications's temporary output files are managed. Absolute paths or paths relative to the application folder are possible. If the variable is left empty, operating system's default temporary directory is used. Please note that the application always writes input multipart data to the OS' temporary directory, regardless of the FITZ_FORMPOST_TEMP_DIR value, unless FITZ_FORMPOST_MEMORY_BUFFER_SIZE is negative. This limitation is inflicted by the mime/multipart Go API and cannot be feasibly altered (yet).
FITZ_FORMPOST_MAX_REQUEST_SIZE-1Maximum size of a multipart request in bytes, which can be processed by the application. Note that the request size amounts to the entire HTTP request body, including multipart boundary delimiters, content disposition headers, line breaks and, indeed, the actual payload. Decent clients which send the Content-Length header also enjoy fail-fast behavior if that value exceeds the provided maximum. Either way, the application counts bytes during upload and returns 413 Request Entity Too Large as soon as the limit is exceeded. By default no request size limit is set.
FITZ_FORMPOST_MEMORY_BUFFER_SIZE10485760Number of bytes stored in memory when uploading multipart data. If the payload size is exceeding this number, then the remaining bytes are dumped onto the filesystem. Accordingly, the size of 0 prompts the application to always write all bytes to a temporary file, whereas any negative value such as -1 will prevent the application from hitting the filesystem and retain the whole request payload in memory. Keep in mind that Go mime/multipart always adds 10 MiB on top of this value for the "non-file parts", i.e. boundaries etc., hence the actual minimum is 10 MiB plus 1 byte. The default value is therefore effectively 20 MiB.
FITZ_FORMPOST_ENABLE_PROMETHEUSfalseExpose application metrics via Prometheus endpoint /metrics.
FITZ_FORMPOST_ENABLE_SHUTDOWN_ENDPOINTfalseEnable shutdown endpoint under /shutdown. A single POST request with arbitrary payload to this endpoint will cause the application to shutdown gracefully.
FITZ_FORMPOST_SHUTDOWN_TIMEOUT0sSpecifies amount of time to wait before ongoing requests are forcefully cancelled in order to perform a graceful shutdown. A zero value lets the application wait indefinetely for all requests to complete. At least one time unit must be specified, e.g. 45s or 5m15s123ms. See Go time.ParseDuration format for further details.
FITZ_FORMPOST_PROCESSING_MODEserializedChoose between serialized, interleaved and inmemory processing modes. See Processing Modes for further details.
FITZ_FORMPOST_RENDERING_DPI300Sets the default DPI resolution at which the source PDF document is rasterized. Higher value improves font and image quality (both vector and large enough raster images) but also increases memory and CPU usage. Lower DPI values may result in upscaling of the intermediate raster image, hence nullifying potential quality surplus of higher target dimensions. Any float64 value between 1 and math.MaxFloat64 is allowed. Traditional values are 72, 150, 200, 300, 600, 1200 and so on.

Processing Modes

valuedescription
serializedStandard processing mode. First, image output is written to a local temporary file. Contents of the file are then transferred as part of the response. The process is repeated for every following page requested. This allows for a single temporary file to be reused, hence minimizing required free disk space.
interleavedSlightly enhanced version of the serialized mode. Two temporary files are created, with two goroutines writing images and transferring the contents interchangeably. While the first goroutine is encoding the document page, the second one is busy with serving the image of the previous page. This helps to increase throughput on such systems where the network speed is slower or merely faster than the encoding performance. This comes at a cost of two temporary files needes to be present on disk during processing. If network speed clearly dominates over encoding, then the advantage is insignificant.
inmemoryProcessing is done completely in memory, hence no temporary files are created. May be susceptible to DoS attacks, if the client issues too many requests while artificially cutting down the network throughput, so that many files remain in memory at the same point in time.

Pure In Memory Configuration

In some deployments such as AWS one may want to avoid hitting the filesystem with temporary files. This is possible with the following environment variables set:

  • FITZ_FORMPOST_MEMORY_BUFFER_SIZE=-1
  • FITZ_FORMPOST_PROCESSING_MODE=inmemory

Please also consider setting a reasonable request payload size limit to mitigate excessive memory usage:

  • FITZ_FORMPOST_MAX_REQUEST_SIZE=134217728 (128 MiB)

Parameters

parametermandatoryvalue
widthyesMin: 1; Max: 65500 (theoretical).
heightyesMin: 1; Max: 65500 (theoretical).
formatyesjpg, jpeg, png, gif, tif, tiff, bmp.
fromnoMin: 1; Max: 8388606 (theoretical). This parameter specifies either the sole page of the document to generate image from, or the first page of a page range if the parameter archive is provided. Default is 1.
tonoMin: 1; Max: 8388606 (theoretical). The last page of a page range. Must be larger or equal to from if provided. Setting this parameter also makes archive mandatory. Default is the last page of the document.
archiveyes/noSpecifies how the images of the specified page range should be bundled together. This parameter becomes mandatory, if from is provided. zip and tar are possible values for a ZIP archive and a tarball respectively. Images are placed directly within the root directory having filename pattern imgNNNNNNN.ext.
qualitynoFrom 1 to 100 for JPEG (default 95); 0 to 9 for PNG (default 6).
resizenoImage resizing mode for cases when the source document has a different aspect ratio than specified by the target dimensions.
resamplenoResampling algorithm, affects both quality and performance.

Image Resizing Modes

valuedescription
fitImage is scaled within the specified width-height box ("fit") preserving the aspect ratio of the image. Scaled images with an aspect ratio differing from the specified dimensions have therefore either less width or height. Note: if the source image is smaller than the targeted bounding box, the resulting image will retain its source dimensions. Use fit-upscale in case the source image should be upscaled. fit is the default mode.
fit-blackSame as fit, but the left out pixels are filled with black color. Such images have horizontal or vertical black bars on the opposite sides of the image, a practice also known as "letterboxing" or "pillarboxing", respectively. Note: if the source image is smaller than the targeted bounding box, the resulting image will be surrounded by black bars, i.e. "windowboxed". Use fit-upscale-black if the source image should be upscaled.
fit-whiteSame as fit-black, but the bars are now white.
fit-upscaleSame as fit, but upscales the source image so either image width or height fits the targeted bounding box.
fit-upscale-blackSame as fit-black, but upscales the source image avoiding windowboxing.
fit-upscale-whiteSame as fit-upscale-black, but the bars are now white.
fillImage is scaled to fill the entire width-height box preserving the aspect ratio of the image. If the image has a different aspect ratio, than specified by the target dimensions, then the image is cropped around the center of the image from both sides. Taller images are equally cropped at the top and bottom, accordingly wider ones are cropped left and right.
fill-top-leftSame as fill, but taller images are cropped from the top, hence the outsized bottom part is left out. Wider images are cropped from the left. This option may come in handy when processing both portrait and landscape oriented documents.
fill-topSame as fill, but taller images are cropped from the top, hence the bottom part is left out. Wider images are still cropped at the center.
fill-top-rightSame as fill-top-left, but wider images are cropped from the right.
fill-leftSame as fill, but wider images are cropped from the right. Taller images are still cropped at the center.
fill-rightSame as fill-left, but wider images are cropped only from the right.
fill-bottom-leftThe opposite of fill-top-right: Taller images are cropped from the bottom, wider images cropped from the left.
fill-bottomThe opposite of fill-top: Taller images are cropped from the bottom, wider images at the center.
fill-bottom-rightThe opposite of fill-top-left: Taller images are cropped from the bottom, wider images cropped from the right.
stretchThe image is stretched to fill the target width and height without preserving the aspect ratio.

Resampling Algorithms

The following resampling algorithms are provided by the Golang Imaging library, which has a decent basic overview of available resampling algorithms in its readme file. Wikipedia and ImageMagick 6 Docs are also a good starting point for understanding the differences between particular algorithms and performance implications.

valuedescription
boxBox sampling (default)
nearestNearest-neighbor interpolation
linearLinear interpolation
hermiteHermite cubic interpolation, i.e. BC-spline with B=0 and C=0
mitchellMitchell–Netravali cubic interpolation, i.e. BC-spline with ImageMagick parameters B=⅓ and C=⅓
catmullCatmull–Rom spline with B=0 and C=½, also used in GIMP
bsplineB-spline, i.e. cubic interpolation with Paint.NET parameters B=1 and C=0
bartlettBartlett window sinc resampling (3 lobes)
lanczosLanczos sinc approximation (3 lobes)
hannHann window sinc resampling (3 lobes)
hammingHamming window sinc resampling (3 lobes)
blackmanBlackman window sinc resampling (3 lobes)
welchWelch parabolic window sinc resampling (3 lobes)
cosineCosine window sinc resampling (3 lobes)

License

Inherits AGPLv3 from go-fitz and MuPDF.