Spaces:
Running
Running
Fix API connectivity in Docker Space
Browse filesRoot cause: NEXT_PUBLIC_API_URL was defaulting to 'http://localhost:8000' which made
the browser try to reach localhost instead of using Next.js proxy.
Fixes:
- Remove default value for NEXT_PUBLIC_API_URL in next.config.js
- Only set NEXT_PUBLIC_API_URL if explicitly provided
- In Docker Space, frontend uses relative URLs (empty string)
- Next.js server proxies /api/* to localhost:8000 backend
- Add console.log debugging to trace API URL resolution
- Add comments explaining Docker Space proxy architecture
This ensures:
✅ Production: Browser -> /api/models -> Next.js proxy -> localhost:8000/api/models
✅ Dev: Browser -> http://localhost:8000/api/models (direct)
- Dockerfile +2 -0
- frontend/next.config.js +8 -3
- frontend/src/lib/api.ts +6 -2
Dockerfile
CHANGED
|
@@ -64,6 +64,8 @@ COPY --chown=user:user --from=frontend-builder /build/next.config.js ./frontend/
|
|
| 64 |
COPY --chown=user:user --from=frontend-builder /build/node_modules ./frontend/node_modules
|
| 65 |
|
| 66 |
# Set environment variables for the application
|
|
|
|
|
|
|
| 67 |
ENV BACKEND_HOST=http://localhost:8000 \
|
| 68 |
PORT=7860
|
| 69 |
|
|
|
|
| 64 |
COPY --chown=user:user --from=frontend-builder /build/node_modules ./frontend/node_modules
|
| 65 |
|
| 66 |
# Set environment variables for the application
|
| 67 |
+
# BACKEND_HOST is used by Next.js server for proxying
|
| 68 |
+
# Do NOT set NEXT_PUBLIC_API_URL - let frontend use relative URLs
|
| 69 |
ENV BACKEND_HOST=http://localhost:8000 \
|
| 70 |
PORT=7860
|
| 71 |
|
frontend/next.config.js
CHANGED
|
@@ -2,13 +2,18 @@
|
|
| 2 |
const nextConfig = {
|
| 3 |
output: 'standalone',
|
| 4 |
reactStrictMode: true,
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
async rewrites() {
|
| 9 |
// In Docker Space, proxy /api/* requests to backend on port 8000
|
| 10 |
// This allows frontend (7860) to communicate with backend (8000) internally
|
| 11 |
const API_HOST = process.env.BACKEND_HOST || 'http://localhost:8000';
|
|
|
|
| 12 |
return [
|
| 13 |
{
|
| 14 |
source: '/api/:path*',
|
|
|
|
| 2 |
const nextConfig = {
|
| 3 |
output: 'standalone',
|
| 4 |
reactStrictMode: true,
|
| 5 |
+
// Only set NEXT_PUBLIC_API_URL if explicitly provided
|
| 6 |
+
// In Docker Space, we want it undefined so frontend uses relative URLs (proxied by Next.js)
|
| 7 |
+
...(process.env.NEXT_PUBLIC_API_URL && {
|
| 8 |
+
env: {
|
| 9 |
+
NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
|
| 10 |
+
},
|
| 11 |
+
}),
|
| 12 |
async rewrites() {
|
| 13 |
// In Docker Space, proxy /api/* requests to backend on port 8000
|
| 14 |
// This allows frontend (7860) to communicate with backend (8000) internally
|
| 15 |
const API_HOST = process.env.BACKEND_HOST || 'http://localhost:8000';
|
| 16 |
+
console.log(`[Next.js] Setting up API proxy: /api/* -> ${API_HOST}/api/*`);
|
| 17 |
return [
|
| 18 |
{
|
| 19 |
source: '/api/:path*',
|
frontend/src/lib/api.ts
CHANGED
|
@@ -13,23 +13,27 @@ import type {
|
|
| 13 |
// Use relative URLs in production (Next.js rewrites will proxy to backend)
|
| 14 |
// In local dev, use localhost:8000 for direct backend access
|
| 15 |
const getApiUrl = () => {
|
| 16 |
-
// If explicitly set via env var, use it
|
| 17 |
if (process.env.NEXT_PUBLIC_API_URL) {
|
|
|
|
| 18 |
return process.env.NEXT_PUBLIC_API_URL;
|
| 19 |
}
|
| 20 |
|
| 21 |
// For server-side rendering, always use relative URLs
|
| 22 |
if (typeof window === 'undefined') {
|
|
|
|
| 23 |
return '';
|
| 24 |
}
|
| 25 |
|
| 26 |
-
// On localhost (dev mode), use direct backend URL
|
| 27 |
const hostname = window.location.hostname;
|
| 28 |
if (hostname === 'localhost' || hostname === '127.0.0.1') {
|
|
|
|
| 29 |
return 'http://localhost:8000';
|
| 30 |
}
|
| 31 |
|
| 32 |
// In production (HF Space), use relative URLs (Next.js proxies to backend)
|
|
|
|
| 33 |
return '';
|
| 34 |
};
|
| 35 |
|
|
|
|
| 13 |
// Use relative URLs in production (Next.js rewrites will proxy to backend)
|
| 14 |
// In local dev, use localhost:8000 for direct backend access
|
| 15 |
const getApiUrl = () => {
|
| 16 |
+
// If explicitly set via env var, use it (for development)
|
| 17 |
if (process.env.NEXT_PUBLIC_API_URL) {
|
| 18 |
+
console.log('[API Client] Using explicit API URL:', process.env.NEXT_PUBLIC_API_URL);
|
| 19 |
return process.env.NEXT_PUBLIC_API_URL;
|
| 20 |
}
|
| 21 |
|
| 22 |
// For server-side rendering, always use relative URLs
|
| 23 |
if (typeof window === 'undefined') {
|
| 24 |
+
console.log('[API Client] SSR mode: using relative URLs');
|
| 25 |
return '';
|
| 26 |
}
|
| 27 |
|
| 28 |
+
// On localhost (dev mode), use direct backend URL
|
| 29 |
const hostname = window.location.hostname;
|
| 30 |
if (hostname === 'localhost' || hostname === '127.0.0.1') {
|
| 31 |
+
console.log('[API Client] Localhost dev mode: using http://localhost:8000');
|
| 32 |
return 'http://localhost:8000';
|
| 33 |
}
|
| 34 |
|
| 35 |
// In production (HF Space), use relative URLs (Next.js proxies to backend)
|
| 36 |
+
console.log('[API Client] Production mode: using relative URLs (proxied by Next.js)');
|
| 37 |
return '';
|
| 38 |
};
|
| 39 |
|