feat(api): enhance backend API configuration and routing for multi-domain support
- Updated `next.config.mjs` to implement host-based routing for two domains, allowing seamless API proxying to the appropriate backend based on the host. - Refactored backend API base URL logic in `config.ts` to dynamically determine the correct URL based on the deployment environment, supporting both production and test setups. - Modified `CreateCompany` form to validate website input with a regex pattern and changed input type to text for better user experience.
This commit is contained in:
+24
-1
@@ -34,10 +34,33 @@ const nextConfig = {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
async rewrites() {
|
async rewrites() {
|
||||||
|
// The same build is deployed to two domains, each with its own backend:
|
||||||
|
// - test: opplenz.com -> https://admin.opplenz.com/admin/v1
|
||||||
|
// - production: opplens.com -> https://admin.opplens.com/admin/v1
|
||||||
|
// Routing is host-based so neither deploy needs a custom env. A
|
||||||
|
// `BACKEND_API_BASE_URL` env var (if set) overrides both — handy for local
|
||||||
|
// dev pointing at e.g. http://localhost:8080/admin/v1.
|
||||||
|
const override = process.env.BACKEND_API_BASE_URL;
|
||||||
|
if (override) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
source: "/api/proxy/:path*",
|
source: "/api/proxy/:path*",
|
||||||
destination: `https://admin.opplenz.com/admin/v1/:path*`,
|
destination: `${override}/:path*`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
// Production: any opplens.com host (apex or subdomain like www.).
|
||||||
|
{
|
||||||
|
source: "/api/proxy/:path*",
|
||||||
|
has: [{ type: "host", value: "(.*\\.)?opplens\\.com" }],
|
||||||
|
destination: "https://admin.opplens.com/admin/v1/:path*",
|
||||||
|
},
|
||||||
|
// Default (test opplenz.com + local dev).
|
||||||
|
{
|
||||||
|
source: "/api/proxy/:path*",
|
||||||
|
destination: "https://admin.opplenz.com/admin/v1/:path*",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -210,11 +210,15 @@ const CreateCompany = ({ defaultValues, editMode, id }: IProps) => {
|
|||||||
value: 100,
|
value: 100,
|
||||||
message: FormErrorMessages.maxLength(100),
|
message: FormErrorMessages.maxLength(100),
|
||||||
},
|
},
|
||||||
|
pattern: {
|
||||||
|
value: REGEX.URL,
|
||||||
|
message: FormErrorMessages.invalidPattern,
|
||||||
|
},
|
||||||
})}
|
})}
|
||||||
label="Website"
|
label="Website"
|
||||||
required
|
required
|
||||||
name="website"
|
name="website"
|
||||||
type="url"
|
type="text"
|
||||||
placeholder="https://www.example.com"
|
placeholder="https://www.example.com"
|
||||||
/>
|
/>
|
||||||
{errors.website && (
|
{errors.website && (
|
||||||
|
|||||||
+27
-10
@@ -1,21 +1,38 @@
|
|||||||
import { API_ENDPOINTS } from "./endpoints";
|
import { API_ENDPOINTS } from "./endpoints";
|
||||||
|
|
||||||
|
const TEST_API_BASE_URL = "https://admin.opplenz.com/admin/v1";
|
||||||
|
const PRODUCTION_API_BASE_URL = "https://admin.opplens.com/admin/v1";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Absolute base URL of the backend admin API.
|
* Absolute base URL of the backend admin API for the current deploy.
|
||||||
*
|
*
|
||||||
* Mirrors the rewrite target in `next.config.mjs` (`/api/proxy/* ->
|
* Mirrors the host-based proxy in `next.config.mjs`:
|
||||||
* https://admin.opplenz.com/admin/v1/*`). Axios calls use the relative
|
* - production (`opplens.com`) -> admin.opplens.com/admin/v1
|
||||||
* `/api/proxy/` base so the browser attaches auth headers same-origin, but
|
* - test (`opplenz.com`) + dev -> admin.opplenz.com/admin/v1
|
||||||
* values that are persisted on the backend (e.g. a `profile_image` download
|
*
|
||||||
* URL) must be absolute so they resolve from anywhere — not the proxy path.
|
* Axios calls use the relative `/api/proxy/` base (so the browser attaches auth
|
||||||
|
* headers same-origin and the rewrite picks the right backend), but values that
|
||||||
|
* get persisted on the backend (e.g. a `profile_image` download URL) must be
|
||||||
|
* absolute and domain-correct. Resolved at call time because the host is only
|
||||||
|
* known in the browser.
|
||||||
*/
|
*/
|
||||||
export const BACKEND_API_BASE_URL =
|
export const getBackendApiBaseUrl = (): string => {
|
||||||
process.env.NEXT_PUBLIC_BACKEND_API_BASE_URL ??
|
const override = process.env.NEXT_PUBLIC_BACKEND_API_BASE_URL;
|
||||||
"https://admin.opplenz.com/admin/v1";
|
if (override) return override;
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof window !== "undefined" &&
|
||||||
|
/(^|\.)opplens\.com$/.test(window.location.hostname)
|
||||||
|
) {
|
||||||
|
return PRODUCTION_API_BASE_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TEST_API_BASE_URL;
|
||||||
|
};
|
||||||
|
|
||||||
/** Absolute, directly-loadable URL for a stored GridFS file. */
|
/** Absolute, directly-loadable URL for a stored GridFS file. */
|
||||||
export const buildFileDownloadUrl = (fileId: string) =>
|
export const buildFileDownloadUrl = (fileId: string) =>
|
||||||
`${BACKEND_API_BASE_URL}/${API_ENDPOINTS.FILES.DOWNLOAD(fileId)}`;
|
`${getBackendApiBaseUrl()}/${API_ENDPOINTS.FILES.DOWNLOAD(fileId)}`;
|
||||||
|
|
||||||
/** Pull the GridFS file id out of a stored download URL, if it is one. */
|
/** Pull the GridFS file id out of a stored download URL, if it is one. */
|
||||||
export const extractFileId = (url: string): string | undefined =>
|
export const extractFileId = (url: string): string | undefined =>
|
||||||
|
|||||||
Reference in New Issue
Block a user