refactor(env): update NEXT_PUBLIC_API_URL to use 'auto' for better flexibility
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { getLocalAuthToken, isLocalAuthMode } from "@/auth/localAuth";
|
||||
import { getApiBaseUrl } from "@/lib/api-base";
|
||||
|
||||
type ClerkSession = {
|
||||
getToken: () => Promise<string>;
|
||||
@@ -39,11 +40,7 @@ export const customFetch = async <T>(
|
||||
url: string,
|
||||
options: RequestInit,
|
||||
): Promise<T> => {
|
||||
const rawBaseUrl = process.env.NEXT_PUBLIC_API_URL;
|
||||
if (!rawBaseUrl) {
|
||||
throw new Error("NEXT_PUBLIC_API_URL is not set.");
|
||||
}
|
||||
const baseUrl = rawBaseUrl.replace(/\/+$/, "");
|
||||
const baseUrl = getApiBaseUrl();
|
||||
|
||||
const headers = new Headers(options.headers);
|
||||
const hasBody = options.body !== undefined && options.body !== null;
|
||||
|
||||
@@ -7,17 +7,18 @@ import { setLocalAuthToken } from "@/auth/localAuth";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { getApiBaseUrl } from "@/lib/api-base";
|
||||
|
||||
const LOCAL_AUTH_TOKEN_MIN_LENGTH = 50;
|
||||
|
||||
async function validateLocalToken(token: string): Promise<string | null> {
|
||||
const rawBaseUrl = process.env.NEXT_PUBLIC_API_URL;
|
||||
if (!rawBaseUrl) {
|
||||
return "NEXT_PUBLIC_API_URL is not set.";
|
||||
let baseUrl: string;
|
||||
try {
|
||||
baseUrl = getApiBaseUrl();
|
||||
} catch {
|
||||
return "Unable to resolve backend URL.";
|
||||
}
|
||||
|
||||
const baseUrl = rawBaseUrl.replace(/\/+$/, "");
|
||||
|
||||
let response: Response;
|
||||
try {
|
||||
response = await fetch(`${baseUrl}/api/v1/users/me`, {
|
||||
|
||||
27
frontend/src/lib/api-base.test.ts
Normal file
27
frontend/src/lib/api-base.test.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { getApiBaseUrl } from "./api-base";
|
||||
|
||||
describe("getApiBaseUrl", () => {
|
||||
afterEach(() => {
|
||||
vi.unstubAllEnvs();
|
||||
});
|
||||
|
||||
it("returns normalized explicit URL", () => {
|
||||
vi.stubEnv("NEXT_PUBLIC_API_URL", "https://api.example.com///");
|
||||
|
||||
expect(getApiBaseUrl()).toBe("https://api.example.com");
|
||||
});
|
||||
|
||||
it("auto-resolves from browser host when set to auto", () => {
|
||||
vi.stubEnv("NEXT_PUBLIC_API_URL", "auto");
|
||||
|
||||
expect(getApiBaseUrl()).toBe("http://localhost:8000");
|
||||
});
|
||||
|
||||
it("auto-resolves from browser host when unset", () => {
|
||||
vi.stubEnv("NEXT_PUBLIC_API_URL", "");
|
||||
|
||||
expect(getApiBaseUrl()).toBe("http://localhost:8000");
|
||||
});
|
||||
});
|
||||
@@ -1,11 +1,22 @@
|
||||
export function getApiBaseUrl(): string {
|
||||
const raw = process.env.NEXT_PUBLIC_API_URL;
|
||||
if (!raw) {
|
||||
throw new Error("NEXT_PUBLIC_API_URL is not set.");
|
||||
const raw = process.env.NEXT_PUBLIC_API_URL?.trim();
|
||||
if (raw && raw.toLowerCase() !== "auto") {
|
||||
const normalized = raw.replace(/\/+$/, "");
|
||||
if (!normalized) {
|
||||
throw new Error("NEXT_PUBLIC_API_URL is invalid.");
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
const normalized = raw.replace(/\/+$/, "");
|
||||
if (!normalized) {
|
||||
throw new Error("NEXT_PUBLIC_API_URL is invalid.");
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
const protocol = window.location.protocol === "https:" ? "https" : "http";
|
||||
const host = window.location.hostname;
|
||||
if (host) {
|
||||
return `${protocol}://${host}:8000`;
|
||||
}
|
||||
}
|
||||
return normalized;
|
||||
|
||||
throw new Error(
|
||||
"NEXT_PUBLIC_API_URL is not set and cannot be auto-resolved outside the browser.",
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user