Hono
Fast, lightweight file uploads with Hono using Web Standards - no adapter needed!
Using pushduck with Hono
Hono is a fast, lightweight web framework built on Web Standards. Since Hono uses Request and Response objects natively, pushduck handlers work directly without any adapters!
Web Standards Native: Hono exposes c.req.raw as a Web Standard Request object, making pushduck integration seamless with zero overhead.
Quick Setup
Install dependencies
npm install pushduckyarn add pushduckpnpm add pushduckbun add pushduckConfigure upload router
import { createUploadConfig } from 'pushduck/server';
const { s3, createS3Router } = createUploadConfig()
.provider("cloudflareR2",{
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
region: 'auto',
endpoint: process.env.AWS_ENDPOINT_URL!,
bucket: process.env.S3_BUCKET_NAME!,
accountId: process.env.R2_ACCOUNT_ID!,
})
.build();
export const uploadRouter = createS3Router({
imageUpload: s3.image().maxFileSize("5MB"),
documentUpload: s3.file().maxFileSize("10MB")
});
export type AppUploadRouter = typeof uploadRouter;Create Hono app with upload routes
import { Hono } from 'hono';
import { uploadRouter } from './lib/upload';
const app = new Hono();
// Direct usage - no adapter needed!
app.all('/api/upload/*', (c) => {
return uploadRouter.handlers(c.req.raw);
});
export default app;Basic Integration
Simple Upload Route
import { Hono } from 'hono';
import { uploadRouter } from './lib/upload';
const app = new Hono();
// Method 1: Combined handler (recommended)
app.all('/api/upload/*', (c) => {
return uploadRouter.handlers(c.req.raw);
});
// Method 2: Separate handlers (if you need method-specific logic)
app.get('/api/upload/*', (c) => uploadRouter.handlers.GET(c.req.raw));
app.post('/api/upload/*', (c) => uploadRouter.handlers.POST(c.req.raw));
export default app;With Middleware
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { logger } from 'hono/logger';
import { uploadRouter } from './lib/upload';
const app = new Hono();
// Global middleware
app.use('*', logger());
app.use('*', cors({
origin: ['http://localhost:3000', 'https://your-domain.com'],
allowMethods: ['GET', 'POST'],
allowHeaders: ['Content-Type'],
}));
// Upload routes
app.all('/api/upload/*', (c) => uploadRouter.handlers(c.req.raw));
// Health check
app.get('/health', (c) => c.json({ status: 'ok' }));
export default app;Advanced Configuration
Authentication with Hono
import { createUploadConfig } from 'pushduck/server';
import { verify } from 'hono/jwt';
const { s3, createS3Router } = createUploadConfig()
.provider("cloudflareR2",{
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
region: 'auto',
endpoint: process.env.AWS_ENDPOINT_URL!,
bucket: process.env.S3_BUCKET_NAME!,
accountId: process.env.R2_ACCOUNT_ID!,
})
.paths({
prefix: 'uploads',
generateKey: (file, metadata) => {
return `${metadata.userId}/${Date.now()}/${file.name}`;
}
})
.build();
export const uploadRouter = createS3Router({
// Private uploads with JWT authentication
privateUpload: s3
.image()
.maxFileSize("5MB")
.middleware(async ({ req }) => {
const authHeader = req.headers.get('authorization');
if (!authHeader?.startsWith('Bearer ')) {
throw new Error('Authorization required');
}
const token = authHeader.substring(7);
try {
const payload = await verify(token, process.env.JWT_SECRET!);
return {
userId: payload.sub as string,
userRole: payload.role as string
};
} catch (error) {
throw new Error('Invalid token');
}
}),
// Public uploads (no auth)
publicUpload: s3
.image()
.maxFileSize("2MB")
// No middleware = public access
});
export type AppUploadRouter = typeof uploadRouter;Deployment Options
import { Hono } from 'hono';
import { uploadRouter } from './lib/upload';
const app = new Hono();
app.all('/api/upload/*', (c) => uploadRouter.handlers(c.req.raw));
export default app;name = "my-upload-api"
main = "src/index.ts"
compatibility_date = "2023-12-01"
[env.production]
vars = { NODE_ENV = "production" }# Deploy to Cloudflare Workers
npx wrangler deployimport { Hono } from 'hono';
import { uploadRouter } from './lib/upload';
const app = new Hono();
app.all('/api/upload/*', (c) => uploadRouter.handlers(c.req.raw));
export default {
port: 3000,
fetch: app.fetch,
};# Run with Bun
bun run server.tsimport { serve } from '@hono/node-server';
import { Hono } from 'hono';
import { uploadRouter } from './lib/upload';
const app = new Hono();
app.all('/api/upload/*', (c) => uploadRouter.handlers(c.req.raw));
const port = 3000;
console.log(`Server is running on port ${port}`);
serve({
fetch: app.fetch,
port
});# Run with Node.js
npm run devimport { Hono } from 'hono';
import { uploadRouter } from './lib/upload.ts';
const app = new Hono();
app.all('/api/upload/*', (c) => uploadRouter.handlers(c.req.raw));
Deno.serve(app.fetch);# Run with Deno
deno run --allow-net --allow-env server.tsPerformance Benefits
🚀 Zero Overhead
Direct Web Standards integration
No adapter layer means zero performance overhead - pushduck handlers run directly in Hono.
⚡ Fast Runtime
Hono's lightweight design
Hono is one of the fastest web frameworks, perfect for high-performance upload APIs.
🌐 Edge Ready
Deploy anywhere
Works on Cloudflare Workers, Bun, Node.js, and Deno with the same code.
📦 Small Bundle
Minimal dependencies
Hono + pushduck creates incredibly lightweight upload services.
Perfect Match: Hono's Web Standards foundation and pushduck's universal design create a powerful, fast, and lightweight file upload solution that works everywhere.