additional image changes
This commit is contained in:
@@ -10,6 +10,7 @@ S3_ACCESS_KEY_ID=
|
||||
S3_SECRET_ACCESS_KEY=
|
||||
S3_PUBLIC_BASE_URL=
|
||||
S3_KEY_PREFIX=bird-photos
|
||||
PHOTO_DELIVERY_MODE=proxy
|
||||
FRONTEND_URL=http://localhost:3000
|
||||
BACKEND_URL=http://localhost:5000
|
||||
VITE_API_BASE_URL=http://localhost:5000/api
|
||||
|
||||
@@ -124,8 +124,9 @@ Set these when Wasabi image storage is ready:
|
||||
- `S3_SECRET_ACCESS_KEY=<secret-key>`
|
||||
- `S3_PUBLIC_BASE_URL=<optional CDN or public bucket base URL; leave blank for private signed URLs>`
|
||||
- `S3_KEY_PREFIX=bird-photos`
|
||||
- `PHOTO_DELIVERY_MODE=proxy`
|
||||
|
||||
Use a dedicated private bucket and access key for FlockPal images. Grant only the S3 permissions the app needs for that bucket. When `S3_PUBLIC_BASE_URL` is blank, FlockPal stores private object keys and returns short-lived signed URLs for bird photos.
|
||||
Use a dedicated private bucket and access key for FlockPal images. Grant only the S3 permissions the app needs for that bucket. When `S3_PUBLIC_BASE_URL` is blank, FlockPal stores private object keys. `PHOTO_DELIVERY_MODE=proxy` streams images through the backend after validating the app photo token; `PHOTO_DELIVERY_MODE=redirect` validates the app token and redirects to a short-lived Wasabi signed URL.
|
||||
|
||||
Migrate existing Postgres-stored bird photos after deploying S3 image storage:
|
||||
|
||||
|
||||
+25
-1
@@ -134,6 +134,7 @@ const trustProxy = process.env.TRUST_PROXY?.trim() ?? '';
|
||||
const milestoneRemindersEnabled = (process.env.MILESTONE_REMINDERS_ENABLED ?? 'true').toLowerCase() !== 'false';
|
||||
const milestoneReminderTimeZone = process.env.MILESTONE_REMINDER_TIME_ZONE?.trim() || 'America/New_York';
|
||||
const milestoneReminderCheckIntervalMs = 60 * 60 * 1000;
|
||||
const photoDeliveryMode = process.env.PHOTO_DELIVERY_MODE === 'redirect' ? 'redirect' : 'proxy';
|
||||
|
||||
if (trustProxy) {
|
||||
app.set('trust proxy', trustProxy === 'true' ? true : Number(trustProxy) || trustProxy);
|
||||
@@ -2766,8 +2767,31 @@ app.get('/api/birds/:birdId/photo', async (req: Request, res: Response, next: Ne
|
||||
expiresInSeconds: 5 * 60,
|
||||
});
|
||||
|
||||
res.setHeader('Cache-Control', 'private, max-age=300');
|
||||
res.setHeader('Cache-Control', 'private, max-age=900');
|
||||
|
||||
if (photoDeliveryMode === 'redirect') {
|
||||
res.redirect(302, signedUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
const imageResponse = await fetch(signedUrl);
|
||||
|
||||
if (!imageResponse.ok) {
|
||||
res.status(imageResponse.status).json({ error: 'Unable to load bird photo.' });
|
||||
return;
|
||||
}
|
||||
|
||||
const contentType = imageResponse.headers.get('content-type') || bird.photo_content_type || 'application/octet-stream';
|
||||
const contentLength = imageResponse.headers.get('content-length');
|
||||
const imageBuffer = Buffer.from(await imageResponse.arrayBuffer());
|
||||
|
||||
res.setHeader('Content-Type', contentType);
|
||||
|
||||
if (contentLength) {
|
||||
res.setHeader('Content-Length', contentLength);
|
||||
}
|
||||
|
||||
res.send(imageBuffer);
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ services:
|
||||
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:-}
|
||||
S3_PUBLIC_BASE_URL: ${S3_PUBLIC_BASE_URL:-}
|
||||
S3_KEY_PREFIX: ${S3_KEY_PREFIX:-bird-photos}
|
||||
PHOTO_DELIVERY_MODE: ${PHOTO_DELIVERY_MODE:-proxy}
|
||||
FRONTEND_URL: ${FRONTEND_URL:?set FRONTEND_URL for production}
|
||||
BACKEND_URL: ${BACKEND_URL:?set BACKEND_URL for production}
|
||||
ADMIN_EMAILS: ${ADMIN_EMAILS:-}
|
||||
@@ -127,6 +128,7 @@ services:
|
||||
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:-}
|
||||
S3_PUBLIC_BASE_URL: ${S3_PUBLIC_BASE_URL:-}
|
||||
S3_KEY_PREFIX: ${S3_KEY_PREFIX:-bird-photos}
|
||||
PHOTO_DELIVERY_MODE: ${PHOTO_DELIVERY_MODE:-proxy}
|
||||
FRONTEND_URL: ${FRONTEND_URL:?set FRONTEND_URL for production}
|
||||
BACKEND_URL: ${BACKEND_URL:?set BACKEND_URL for production}
|
||||
ADMIN_EMAILS: ${ADMIN_EMAILS:-}
|
||||
|
||||
@@ -49,6 +49,7 @@ services:
|
||||
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:-}
|
||||
S3_PUBLIC_BASE_URL: ${S3_PUBLIC_BASE_URL:-}
|
||||
S3_KEY_PREFIX: ${S3_KEY_PREFIX:-bird-photos}
|
||||
PHOTO_DELIVERY_MODE: ${PHOTO_DELIVERY_MODE:-proxy}
|
||||
FRONTEND_URL: ${FRONTEND_URL:-http://localhost:3000}
|
||||
BACKEND_URL: ${BACKEND_URL:-http://localhost:5000}
|
||||
ADMIN_EMAILS: ${ADMIN_EMAILS:-}
|
||||
@@ -120,6 +121,7 @@ services:
|
||||
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:-}
|
||||
S3_PUBLIC_BASE_URL: ${S3_PUBLIC_BASE_URL:-}
|
||||
S3_KEY_PREFIX: ${S3_KEY_PREFIX:-bird-photos}
|
||||
PHOTO_DELIVERY_MODE: ${PHOTO_DELIVERY_MODE:-proxy}
|
||||
FRONTEND_URL: ${FRONTEND_URL:-http://localhost:3000}
|
||||
BACKEND_URL: ${BACKEND_URL:-http://localhost:5000}
|
||||
ADMIN_EMAILS: ${ADMIN_EMAILS:-}
|
||||
|
||||
Reference in New Issue
Block a user