ZipFly is a golang HTTP server that streams a ZIP file from a list of URLs extracted from a JSON manifest.
Install Golang (developed with Go 1.17). Clone the repo.
# Build the image
docker build . -t zipfly
# Run the server
docker run -p 127.0.0.1:6969:6969 zipfly ./zipfly
go build
./zipfly
# Available at `localhost:6969`
Variable | Details |
---|---|
PORT | defaults to "6969" |
ENVIRONMENT | defaults to "development" |
VALIDATE_SIGNATURE | whether or not the request should validate the signature |
SIGNING_SECRET | Secret used to sign and validate requests |
PUBLIC_URL |
GET /zip?source=base64_url&filename=zip_filename.zip&signature=url_signature&expires=timestamp
Query string params:
- source (mandatory): base64 encoded URL that must return a JSON manifest containing the URLs of the files to ZIP (see below for the format).
- filename (optional): the filename to give to the zip archive (used in the response Content-Disposition). Overrides the one given by the JSON from the source URL. Defaults to
archive.zip
. - expires (mandatory if VALIDATE_SIGNATURE is on): timestamp representing the URL expiration time.
- signature (mandatory if VALIDATE_SIGNATURE is on): URL signature to validate that the request is from an authorized client.
The body must contain a JSON manifest formed as presented below. VALIDATE_SIGNATURE is on, it must also include the following headers:
- X-Zipfly-Signature
- X-Zipfly-Expires
{
"filename": "final_archive_name.zip",
"files": [
{ "url": "https://server.com/audio1.mp3", "filename": "track1.audio", "compress": true },
{ "url": "https://server.com/cover.jpg", "filename": "in-a-sub-folder/cover.jpg" }
]
}
Archive filename
is optional and used in the response Content-Disposition.
File filename
is used as final path in the ZIP. Folders allowed. Any absolute path is automatically interpreted as relative (prefixed '/' is removed).
File compress
is optional. When true, uses Deflate compression method for the file, else uses Store (no compression).
The signature is a HMAC SHA256 hex digest, using a shared secret (SIGNING_SECRET).
- Build the full URL (with scheme, host, path, query string), including the
expires
param, without thesignature
param. Query string param must be sorted alphabetically. - Compute the HMAC SHA256 hexadecimal digest of the URL with the shared secret.
- Add the
signature
param with the computed digest to the URL query string.
- Concatenate the JSON body to the expiration timestamp using ':' as separator:
expiration_timestamp:json_body
. - Compute its HMAC SHA256 hexadecimal digest.
- Add the headers
X-Zipfly-Signature
andX-Zipfly-Expires
with their respective value.