fix: priority ^~ /uploads/ routing in Nginx and share strapi_uploads volume with backend

This commit is contained in:
Vishva
2026-08-04 11:09:28 +05:30
parent d66df5ed43
commit 923c50bfac
3 changed files with 64 additions and 33 deletions
+1
View File
@@ -71,6 +71,7 @@ services:
volumes:
- backend_uploads:/app/server/uploads
- backend_data:/app/server/data
- strapi_uploads:/app/strapi-cms/public/uploads
depends_on:
- strapi-cms
networks:
+35 -21
View File
@@ -2,6 +2,8 @@ server {
listen 80;
server_name localhost;
client_max_body_size 100M;
root /usr/share/nginx/html;
index index.html;
@@ -11,7 +13,39 @@ server {
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# Explicit handling for static assets (JavaScript, CSS, images, fonts)
# Priority prefix location for uploads - proxies to Express backend container
location ^~ /uploads/ {
proxy_pass http://backend:3005/uploads/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# Priority prefix location for backend API
location ^~ /api/ {
proxy_pass http://backend:3005/api/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Prevent 504 Gateway Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# Explicit handling for static JS, CSS, images, and fonts
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|map)$ {
try_files $uri /citpl_website$uri =404;
expires 30d;
@@ -39,26 +73,6 @@ server {
try_files $uri $uri/ /preview.html;
}
# Proxy backend API requests to the Express backend container
location /api/ {
proxy_pass http://backend:3005/api/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Proxy media upload requests to backend
location /uploads/ {
proxy_pass http://backend:3005/uploads/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
+28 -12
View File
@@ -344,7 +344,7 @@ export default function BlogDetailPage({ blog, allBlogs = [], isMobile, onNaviga
</div>
{/* HERO FEATURED IMAGE */}
{blog.image && (
{(blog.image || blog.coverImage || blog.ogImage) && (
<div style={{
width: '100%',
height: isMobile ? '250px' : '520px',
@@ -356,9 +356,24 @@ export default function BlogDetailPage({ blog, allBlogs = [], isMobile, onNaviga
boxShadow: '0 25px 60px rgba(0, 0, 0, 0.75)'
}}>
<img
src={assetUrl(blog.image)}
src={assetUrl(blog.image || blog.coverImage || blog.ogImage)}
alt={blog.title}
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
onError={(e) => {
const titleLower = (blog.title || '').toLowerCase();
const catLower = (blog.category || '').toLowerCase();
let fallback = '/assets/arvindh_agentic_ai.jpg';
if (titleLower.includes('llm')) fallback = '/assets/arvindh_llm_financial.jpg';
else if (titleLower.includes('supply chain')) fallback = '/assets/arvindh_supply_chain.jpg';
else if (titleLower.includes('prodmax')) fallback = '/assets/prodmax_dashboard.png';
else if (titleLower.includes('vr') || titleLower.includes('incidents')) fallback = '/assets/whyus_vr_man.jpg';
else if (titleLower.includes('scada') || titleLower.includes('plc') || titleLower.includes('speed vs')) fallback = '/assets/arvindh_agentic_ai.jpg';
else if (catLower.includes('ai')) fallback = '/assets/arvindh_agentic_ai.jpg';
const resolvedFallback = assetUrl(fallback);
if (e.currentTarget.src !== resolvedFallback) {
e.currentTarget.src = resolvedFallback;
}
}}
/>
</div>
)}
@@ -646,14 +661,12 @@ export default function BlogDetailPage({ blog, allBlogs = [], isMobile, onNaviga
</ol>
);
}
const imgMatch = block.match(/!\[(.*?)\]\((.*?)\)/);
if (imgMatch) {
const caption = imgMatch[1] ? imgMatch[1].trim() : '';
let rawImgUrl = imgMatch[2];
let resolvedSrc = assetUrl(rawImgUrl);
if (rawImgUrl.startsWith('http://localhost:1337/uploads/')) {
resolvedSrc = assetUrl(rawImgUrl.replace('http://localhost:1337', ''));
}
const mdImgMatch = block.match(/!\[(.*?)\]\((.*?)\)/);
const htmlImgMatch = block.match(/<img[^>]+src=["']([^"']+)["'][^>]*>/i);
if (mdImgMatch || htmlImgMatch) {
const caption = mdImgMatch ? (mdImgMatch[1] ? mdImgMatch[1].trim() : '') : '';
const rawImgUrl = mdImgMatch ? mdImgMatch[2] : htmlImgMatch[1];
const resolvedSrc = assetUrl(rawImgUrl);
const isFilename = caption && /\.(jpg|jpeg|png|gif|webp|svg|bmp)$/i.test(caption);
const displayCaption = caption && !isFilename ? caption : null;
@@ -671,9 +684,12 @@ export default function BlogDetailPage({ blog, allBlogs = [], isMobile, onNaviga
boxShadow: '0 15px 35px rgba(0,0,0,0.5)'
}}
onError={(e) => {
if (rawImgUrl.includes('/uploads/')) {
if (rawImgUrl && rawImgUrl.includes('/uploads/')) {
const uploadPath = rawImgUrl.substring(rawImgUrl.indexOf('/uploads/'));
e.currentTarget.src = `http://localhost:1337${uploadPath}`;
const fallback = assetUrl(uploadPath);
if (e.currentTarget.src !== fallback) {
e.currentTarget.src = fallback;
}
}
}}
/>