fix: Fixed api url on web
This commit is contained in:
+3
-4
@@ -30,10 +30,9 @@ WORKDIR /app
|
||||
ENV NODE_ENV=production
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
|
||||
# Control-plane URL the Next server proxies /api, /auth and /install to. Runtime,
|
||||
# not build time: next.config.js is evaluated when server.js boots in standalone
|
||||
# mode, so this is overridable per deployment without a rebuild.
|
||||
ENV API_URL=http://localhost:8080
|
||||
# No control-plane address here on purpose: this app proxies nothing. /api,
|
||||
# /auth, /install, /update and /public are routed to the server by the reverse
|
||||
# proxy in front of both.
|
||||
|
||||
RUN addgroup --system --gid 1001 nodejs && \
|
||||
adduser --system --uid 1001 nextjs
|
||||
|
||||
@@ -12,8 +12,21 @@ type FetchResult =
|
||||
| { kind: "not-found" }
|
||||
| { kind: "unavailable" };
|
||||
|
||||
async function fetchSnapshot(host: string, forwardedFor: string, pageId: string): Promise<FetchResult> {
|
||||
const base = process.env.API_URL ?? process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:8080";
|
||||
/*
|
||||
* The control plane this call is made to is the visitor's own host.
|
||||
*
|
||||
* This app proxies nothing and holds no address for the server (see
|
||||
* next.config.ts): /public is routed to it by the reverse proxy, exactly as
|
||||
* /api and /auth are for the browser. So the SSR fetch goes back through that
|
||||
* proxy at <slug>.vantage.<tld>, which is a per-tenant address by
|
||||
* construction — and X-Forwarded-Host below is still what selects the tenant,
|
||||
* because the hop from this process cannot set Host.
|
||||
*/
|
||||
function apiBase(proto: string, host: string): string {
|
||||
return `${proto}://${host}`;
|
||||
}
|
||||
|
||||
async function fetchSnapshot(base: string, host: string, forwardedFor: string, pageId: string): Promise<FetchResult> {
|
||||
|
||||
// The instance is resolved server-side from the visitor's host, so it has
|
||||
// to be forwarded explicitly — this is a server-to-server call and its own
|
||||
@@ -95,7 +108,8 @@ export default async function PublicStatusPage({
|
||||
.filter((v): v is string => !!v)
|
||||
.join(", ");
|
||||
|
||||
const result = await fetchSnapshot(host, forwardedFor, pageId);
|
||||
const proto = h.get("x-forwarded-proto")?.split(",")[0].trim() || "https";
|
||||
const result = await fetchSnapshot(apiBase(proto, host), host, forwardedFor, pageId);
|
||||
if (result.kind === "not-found") notFound();
|
||||
|
||||
return (
|
||||
|
||||
+16
-40
@@ -1,11 +1,21 @@
|
||||
import type { NextConfig } from "next";
|
||||
|
||||
// Read at runtime, not baked in. The rewrites below run in the Next server
|
||||
// process, never in the browser, so this never needed the NEXT_PUBLIC_ prefix
|
||||
// that pins a value into the image at build time. NEXT_PUBLIC_API_URL is still
|
||||
// honoured so an existing deployment passing it keeps working.
|
||||
const apiUrl = process.env.API_URL ?? process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:8080";
|
||||
|
||||
/*
|
||||
* This app proxies nothing.
|
||||
*
|
||||
* /api, /auth, /install, /update and /public are the Go server's, and routing
|
||||
* them there is the reverse proxy's job — the same proxy that already
|
||||
* terminates TLS in front of this process. Next used to rewrite them itself
|
||||
* from an API_URL naming the control plane, which meant every deployment had
|
||||
* two possible request paths for the same URL and one environment variable
|
||||
* that silently broke a whole prefix when it named the wrong host: pointed at
|
||||
* the marketing site, /public/status/... 404'd as a page that does not exist,
|
||||
* indistinguishable from a status page that does not exist.
|
||||
*
|
||||
* Browser calls are same-origin and relative (see lib/api.ts), and the public
|
||||
* status page's server-side fetch is made against the visitor's own host, so
|
||||
* nothing in this app needs to know the control plane's address any more.
|
||||
*/
|
||||
const nextConfig: NextConfig = {
|
||||
output: "standalone",
|
||||
async redirects() {
|
||||
@@ -22,40 +32,6 @@ const nextConfig: NextConfig = {
|
||||
},
|
||||
];
|
||||
},
|
||||
async rewrites() {
|
||||
return [
|
||||
{
|
||||
source: "/api/:path*",
|
||||
destination: `${apiUrl}/api/:path*`,
|
||||
},
|
||||
{
|
||||
source: "/auth/:path*",
|
||||
destination: `${apiUrl}/auth/:path*`,
|
||||
},
|
||||
{
|
||||
source: "/install",
|
||||
destination: `${apiUrl}/install`,
|
||||
},
|
||||
{
|
||||
source: "/install.ps1",
|
||||
destination: `${apiUrl}/install.ps1`,
|
||||
},
|
||||
{
|
||||
source: "/update",
|
||||
destination: `${apiUrl}/update`,
|
||||
},
|
||||
{
|
||||
source: "/update.ps1",
|
||||
destination: `${apiUrl}/update.ps1`,
|
||||
},
|
||||
{
|
||||
// The public status page refreshes itself in the browser, so
|
||||
// the public prefix has to be proxied the same way /api is.
|
||||
source: "/public/:path*",
|
||||
destination: `${apiUrl}/public/:path*`,
|
||||
},
|
||||
];
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
||||
Reference in New Issue
Block a user