diff --git a/README.md b/README.md index 02ecb0c..544a29a 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ Features - The `.git-pages/manifest.json` path returns a [ProtoJSON](https://protobuf.dev/programming-guides/json/) representation of the deployed site manifest. It enumerates site structure, redirect rules, and errors that were not severe enough to abort publishing. * In response to a `PUT` or `POST` request, the server retrieves updates a site with new content. The URL of the request must be the root URL of the site that is being published. - If the `PUT` method receives an `application/x-www-form-urlencoded` body, it contains a repository URL to be shallowly cloned. The `X-Pages-Branch` header contains the branch to be checked out; the `pages` branch is used if the header is absent. - - If the `PUT` method receives an `application/x-tar` or `application/zip` body, it contains an archive to be extracted. + - If the `PUT` method receives an `application/x-tar`, `application/x-tar+gzip`, `application/x-tar+zstd`, or `application/zip` body, it contains an archive to be extracted. - The `POST` method requires an `application/json` body containing a Forgejo/Gitea/Gogs/GitHub webhook event payload. Requests where the `ref` key contains anything other than `refs/heads/pages` are ignored, and only the `pages` branch is used. The `repository.clone_url` key contains a repository URL to be shallowly cloned. - If the received contents is empty, performs the same action as `DELETE`. * In response to a `DELETE` request, the server unpublishes a site. The URL of the request must be the root URL of the site that is being unpublished. Site data remains stored for an indeterminate period of time, but becomes completely inaccessible. diff --git a/flake.nix b/flake.nix index 0365fb7..1f696c0 100644 --- a/flake.nix +++ b/flake.nix @@ -42,7 +42,7 @@ "-s -w" ]; - vendorHash = "sha256-8hT8TC7I1jdfve9WOdwN3C51sjbLSRvwIj7a/1qCmVA="; + vendorHash = "sha256-4S4ccnyBuYMFRrFHAxy5N1JeNj9n43xO7+wg5hlCdL0="; fixupPhase = '' # Apparently `go install` doesn't support renaming the binary, so country girls make do. diff --git a/go.mod b/go.mod index 9b0a174..045ed20 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/go-git/go-billy/v6 v6.0.0-20250627091229-31e2a16eef30 github.com/go-git/go-git/v6 v6.0.0-20250910120214-3a68d0404116 github.com/honeybadger-io/honeybadger-go v0.8.0 + github.com/klauspost/compress v1.18.0 github.com/maypok86/otter/v2 v2.2.1 github.com/minio/minio-go/v7 v7.0.95 github.com/pelletier/go-toml/v2 v2.2.4 @@ -30,7 +31,6 @@ require ( github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/google/uuid v1.6.0 // indirect github.com/kevinburke/ssh_config v1.4.0 // indirect - github.com/klauspost/compress v1.18.0 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/minio/crc64nvme v1.0.2 // indirect github.com/minio/md5-simd v1.1.2 // indirect diff --git a/src/extract.go b/src/extract.go index 1e853ab..dd9a334 100644 --- a/src/extract.go +++ b/src/extract.go @@ -4,11 +4,13 @@ import ( "archive/tar" "archive/zip" "bytes" + "compress/gzip" "errors" "fmt" "io" "strings" + "github.com/klauspost/compress/zstd" "google.golang.org/protobuf/proto" ) @@ -69,6 +71,26 @@ func ExtractTar(reader io.Reader) (*Manifest, error) { return &manifest, nil } +func ExtractTarGzip(reader io.Reader) (*Manifest, error) { + stream, err := gzip.NewReader(reader) + if err != nil { + return nil, err + } + defer stream.Close() + + return ExtractTar(stream) +} + +func ExtractTarZstd(reader io.Reader) (*Manifest, error) { + stream, err := zstd.NewReader(reader) + if err != nil { + return nil, err + } + defer stream.Close() + + return ExtractTar(stream) +} + var errZipBomb = errors.New("zip file size limit exceeded") func ExtractZip(reader io.Reader) (*Manifest, error) { diff --git a/src/update.go b/src/update.go index beca052..7abe4db 100644 --- a/src/update.go +++ b/src/update.go @@ -114,7 +114,13 @@ func UpdateFromArchive( switch contentType { case "application/x-tar": log.Printf("update %s: (tar)", webRoot) - manifest, err = ExtractTar(reader) // yellow? definitely yellow. + manifest, err = ExtractTar(reader) // yellow? + case "application/x-tar+gzip": + log.Printf("update %s: (tar.gz)", webRoot) + manifest, err = ExtractTarGzip(reader) // definitely yellow. + case "application/x-tar+zstd": + log.Printf("update %s: (tar.zst)", webRoot) + manifest, err = ExtractTarZstd(reader) case "application/zip": log.Printf("update %s: (zip)", webRoot) manifest, err = ExtractZip(reader)