Releases: gmoon/s3proxy
Release list
Release v4.2.1
v4.2.1
Docs-only patch. No code or API changes since 4.2.0.
- Refreshes the npm README so the Docker examples use
forkzero/s3proxy:latest
(with a note to pin a version for production) instead of a stale patch tag.
The 4.2.0 README still showed the old pin because the fix landed after that
release, and npm only refreshes a package's README on a new publish.
If you are on 4.2.0 there is nothing to upgrade for; this release exists purely
to correct the published documentation.
Release v4.2.0
v4.2.0
Added
-
proxy.fetchWeb(request: Request): Promise<Response>— a Web-standard
adapter overfetch()for Web runtimes (Hono, Bun, Cloudflare Workers, Deno).
It takes a WHATWGRequestand returns a WHATWGResponse, so Web-runtime
consumers stop hand-rolling theRequest->HttpRequestandReadable->
ReadableStreamconversion.// Hono app.on(['GET', 'HEAD'], '/*', (c) => proxy.fetchWeb(c.req.raw)); // Bun / Deno / Cloudflare Workers export default { fetch: (req: Request) => proxy.fetchWeb(req) };
It is the Web counterpart of
pipe()/middleware(). Likefetch()(and
unlikepipe()), it throws the typedS3ProxyErroron 404/403/416, so your
framework's own error handler owns the error-body format. Uses the runtime's
globalRequest/Response— no new dependency.
Developer tooling
make artillery-local— fast local-source load-test loop: runs the shared
@forkzero/s3-website-test-kitagainst atsxexample server on your local
src/, with no build and no Docker image.make artillery-dockerremains the
container-parity path.
Internal
- Load-test configs and scenarios extracted to the published, target-agnostic
@forkzero/s3-website-test-kit
package (shared withforkzero/s3proxy-docker), replacing the in-repo
shared-testing/directory.
Compatibility
No breaking changes. ESM-only, Node.js 22.13+, AWS SDK v3.
Full API reference and examples in the
README; upgrade notes in
MIGRATION.md.
Release v4.1.0
v4.1.0
This is the first published 4.x release. 4.0.0 was never shipped to npm, so if
you are upgrading from 3.x this is a major, breaking release — read the
"Breaking changes" section below. Full details and code examples are in
MIGRATION.md.
s3proxy still does the same thing: stream S3 objects to HTTP responses without
buffering them on your server. v4 fixes v3's error contract and splits the
288-line class into a parser, a gateway, and an orchestrator.
Breaking changes (3.x -> 4.x)
- Typed errors instead of empty 200 streams. In v3 a missing key returned a
fully-formed empty stream with status 200; AccessDenied, InvalidRange, and
NoSuchBucket were absorbed the same way. v4 throws typed errors —
S3NotFound(404),S3Forbidden(403),S3InvalidRange(416),
InvalidRequest(400) — all extendingS3ProxyError(withstatusCodeand
the underlying SDK error ascause). These throw fromfetch()before
res.writeHead, so a v3stream.on('error')handler will no longer see
them; wrap theawaitin try/catch instead. proxy.get(req, res)/proxy.head(req, res)/proxy.healthCheckStream(res)
removed. These mutated the response as a side effect. v4 ships one pure
entry point,proxy.fetch(req), returning{ stream, status, headers }.
Usereq.method = 'HEAD'for HEAD, andproxy.healthCheck()(throws on
failure) for health endpoints.- Response shape renamed: v3's
s3stream/statusCodeare nowstream/
status(headersunchanged). - Parser helpers are free functions.
S3Proxy.parseRequest/
mapHeaderToParam/stripLeadingSlashmoved to package-root exports:
import { parseRequest } from 's3proxy'.parseRequestnow throws
InvalidRequestfor malformed percent-encoding and null-byte keys. S3Proxy.isNonFatalErrorremoved — useinstanceof S3ProxyError.HttpRequestis now a structural type ({ url, method?, headers, path?, query? }), no longer extendsIncomingMessage.
Added
verifyOnInit: false— skip the health check oninit()so a transient
S3 hiccup can't crashloop a pod before readiness probes take over.proxy.pipe(req, res)— fetch an object and stream it straight to an HTTP
response. Recovers v3's one-callproxy.get(req, res)ergonomics without
the empty-200 bug: a missing or forbidden object renders an honest
404/403/416.proxy.middleware()— an Express/Connect-style request handler built on
pipe():app.get('/*splat', proxy.middleware()). Forwards unexpected
errors tonextwhen present.proxy.staticSite(options)— replicates S3 static website hosting:
index-document resolution (/and/dir/->index.html) and, when
errorDocumentis set, serving that key under the original 4xx status for
missing/forbidden objects. An opt-in layer overfetch()— it can't mask a
real failure.
Fixed
- Header passthrough. v4.0 rebuilt response headers from the typed SDK
output and silently droppedx-amz-meta-*custom metadata plus several
S3-specific headers (server-side encryption, KMS key id, version id, storage
class, website redirect, expiration, restore). All are forwarded again, so
callers that round-trip custom metadata work as they did in v3.
Health checks
The v3 healthCheckStream(res) wrapper is gone; v4 exposes the primitive
proxy.healthCheck() (pings the bucket, throws S3ProxyError on failure) and
you render the response. For a load-balancer /health endpoint, try/catch and
return 200 or the error's status. For orchestrators (ECS/Kubernetes), construct
with verifyOnInit: false so init() does not ping S3 at boot — a transient
hiccup then can't crashloop the pod before dashboards surface why — and let a
/ready handler call healthCheck() to drive readiness. See the README
"Health Checks" and "verifyOnInit for orchestrators" sections for full
examples.
Requirements
- ESM-only, Node.js 22.13+, AWS SDK v3.
Staying on v3
npm install s3proxy@^3.0.0 keeps the old behavior; it just doesn't get the
typed-error contract, the parser/gateway split, or verifyOnInit.
Release v3.0.0 - TypeScript Migration & ESM-Only Architecture
🚀 TypeScript Migration & ESM-Only Architecture
This release migrates s3proxy from JavaScript to TypeScript and adopts an ESM-only architecture, bringing modern development practices, improved type safety, and enhanced developer experience.
🔄 Breaking Changes
Node.js Version Requirement
- Before: Node.js 18+
- After: Node.js 22.13.0+ (required for ESM and modern features)
Import Syntax
// ❌ v2.x (CommonJS) - No longer supported
const { S3Proxy } = require('s3proxy');
// ✅ v3.x (ESM) - New syntax
import { S3Proxy } from 's3proxy';Package Type
- Projects must use ESM or dynamic imports
- Add
"type": "module"to package.json for full ESM support - CommonJS projects can use:
const { S3Proxy } = await import('s3proxy');
✅ What's New
- TypeScript First: Full type safety and enhanced IDE support
- ESM-Only: Modern module system for better performance
- Framework Agnostic: Works with Express, Fastify, Lambda, and more
- Comprehensive Testing: 24 validation tests + performance testing
- Production Ready: Proven with load testing (920MB transferred, 0 failures)
📚 Migration Guide
See the README for complete migration instructions from v2.x to v3.x.
All existing functionality is preserved with improved reliability, maintainability, and developer experience!
Upgrade dependencies
Upgraded dependencies, including devDependencies not listed here:
- "@aws-sdk/client-s3": "^3.321.1",
+ "@aws-sdk/client-s3": "^3.405.0",
- "url": "^0.11.0"
+ "url": "^0.11.1"Upgrade to AWS SDK v3
Using AWS SDK v3 instead of v2. There are some potentially breaking changes so this is a major release.
Update Dependencies
Update dependencies per #62
aws-sdk ^2.1199.0 → ^2.1295.0
chai ^4.3.6 → ^4.3.7
eslint ^8.22.0 → ^8.31.0
eslint-plugin-import ^2.26.0 → ^2.27.4
express ^4.18.1 → ^4.18.2
helmet ^5.1.1 → ^6.0.1
mega-linter-runner ^6.6.0 → ^6.18.0
mocha ^10.0.0 → ^10.2.0
mocha-junit-reporter ^2.0.2 → ^2.2.0
nock ^13.2.9 → ^13.3.0
npm-check-updates ^16.0.5 → ^16.6.2
sinon ^14.0.0 → ^15.0.1
start-server-and-test ^1.14.0 → ^1.15.2
wait-on ^6.0.1 → ^7.0.1
Update dependencies; refactor examples/docker
- Updated package.json dependencies, except express-request-id which is pegged to 1.4.1 due to floatdrop/express-request-id#23
- Updated examples/docker/Dockerfile to depend on https://hub.docker.com/repository/docker/forkzero/s3proxy