Fix Railway ECONNREFUSED error by unifying backend URL resolution
Problem: Next.js frontend in production mode falls back to http://backend:8000 (Docker Compose internal hostname) when BACKEND_URL env var is not set. In Railway's distributed environment, this hostname doesn't exist, causing ECONNREFUSED errors. Solution: Create unified getBackendUrl() function with consistent fallback priority across all server-side proxying files: 1. Explicit BACKEND_URL (for Railway / custom deployment) 2. Development mode -> http://localhost:8000 3. NEXT_PUBLIC_API_URL (may be set in Railway) 4. Docker Compose default -> http://backend:8000 Changes: - New: frontend/lib/backend-url.ts - centralized URL resolution - Updated: frontend/next.config.ts - use getBackendUrl() - Updated: frontend/app/api/chat/route.ts - use getBackendUrl() - Updated: frontend/app/api/auth/google/token/route.ts - use getBackendUrl() Railway users must set BACKEND_URL=https://<backend-service>.up.railway.app Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
69eba15bbb
commit
ffc36edb97
|
|
@ -3,14 +3,11 @@
|
|||
* This proxies the token exchange to the backend
|
||||
*/
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
// Use backend internal URL if available (Railway), fallback to public URL
|
||||
const BACKEND_URL = process.env.BACKEND_URL ||
|
||||
process.env.NEXT_PUBLIC_API_URL ||
|
||||
"http://localhost:8000";
|
||||
import { getBackendUrl } from "@/lib/backend-url";
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const backendUrl = getBackendUrl();
|
||||
const body = await request.json();
|
||||
const { code, redirect_uri } = body;
|
||||
|
||||
|
|
@ -22,7 +19,7 @@ export async function POST(request: NextRequest) {
|
|||
}
|
||||
|
||||
// Forward to backend
|
||||
const backendResponse = await fetch(`${BACKEND_URL}/api/auth/google/token`, {
|
||||
const backendResponse = await fetch(`${backendUrl}/api/auth/google/token`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
import { NextResponse } from "next/server";
|
||||
import { getBackendUrl } from "@/lib/backend-url";
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const isDev = process.env.NODE_ENV === "development";
|
||||
const backendUrl =
|
||||
process.env.BACKEND_URL ||
|
||||
(isDev ? "http://localhost:8000" : "http://backend:8000");
|
||||
const backendUrl = getBackendUrl();
|
||||
|
||||
// Read the complete body from the request
|
||||
const bodyText = await req.text();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* Unified backend URL resolution for server-side proxying.
|
||||
*
|
||||
* Priority:
|
||||
* 1. BACKEND_URL – explicit override (Railway / custom deployment)
|
||||
* 2. Development mode – http://localhost:8000
|
||||
* 3. NEXT_PUBLIC_API_URL – fallback (often set in Railway for client-side too)
|
||||
* 4. Docker Compose default – http://backend:8000
|
||||
*
|
||||
* Used by next.config.ts rewrites and Next.js API route handlers.
|
||||
*/
|
||||
export function getBackendUrl(): string {
|
||||
if (process.env.BACKEND_URL) {
|
||||
return process.env.BACKEND_URL;
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
return "http://localhost:8000";
|
||||
}
|
||||
|
||||
if (process.env.NEXT_PUBLIC_API_URL) {
|
||||
return process.env.NEXT_PUBLIC_API_URL;
|
||||
}
|
||||
|
||||
// Docker Compose internal hostname (only works when both services share a Docker network)
|
||||
return "http://backend:8000";
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import type { NextConfig } from "next";
|
||||
import { getBackendUrl } from "./lib/backend-url";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
output: 'standalone',
|
||||
|
|
@ -56,13 +57,7 @@ const nextConfig: NextConfig = {
|
|||
},
|
||||
|
||||
async rewrites() {
|
||||
// In development: use localhost backend
|
||||
// In production (Railway): use BACKEND_URL env var or fallback to Railway URL
|
||||
const isDev = process.env.NODE_ENV === 'development';
|
||||
// Default to http://backend:8000 in production (Docker) if not set
|
||||
const backendUrl = process.env.BACKEND_URL ||
|
||||
(isDev ? "http://localhost:8000" : "http://backend:8000");
|
||||
|
||||
const backendUrl = getBackendUrl();
|
||||
console.log(`[Next.js] Rewriting API requests to: ${backendUrl}`);
|
||||
|
||||
return [
|
||||
|
|
|
|||
Loading…
Reference in New Issue