Skip to content

fix(config): use internal app hostname for StatusPageApiInternalUrl#2565

Open
suvvvv wants to merge 1 commit into
OneUptime:masterfrom
suvvvv:fix/statuspage-internal-url-hostname
Open

fix(config): use internal app hostname for StatusPageApiInternalUrl#2565
suvvvv wants to merge 1 commit into
OneUptime:masterfrom
suvvvv:fix/statuspage-internal-url-hostname

Conversation

@suvvvv

@suvvvv suvvvv commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

What

StatusPageApiInternalUrl is used for server-to-server (in-cluster) calls — e.g. the status page SEO lookup the app makes about itself. It was built from AppApiClientUrl, which uses the public HOST and HTTP_PROTOCOL:

export const StatusPageApiInternalUrl: URL = URL.fromString(
  AppApiClientUrl.toString(),         // <- public HOST + HTTP_PROTOCOL
).addRoute(new Route("/status-page"));

In Kubernetes / any multi-host deployment, the pod then tries to reach its own public ingress from the inside:

APIException: Request failed to https://my_domain/api/status-page/seo/...
connect ETIMEDOUT 10.10.10.10:443

Fix

Build it from AppApiHostname (SERVER_APP_HOSTNAME:APP_PORT) over http, matching the internal-URL pattern already used by MailService, SmsService, StatusPageCertificateService, etc.:

export const StatusPageApiInternalUrl: URL = new URL(
  Protocol.HTTP,
  AppApiHostname,
  new Route(`${AppApiRoute.toString()}/status-page`),
);

The path stays /api/status-page — only the host and protocol move from public to internal, which is exactly what the existing comment on this constant already claimed it did.

Tests

New Common/Tests/Server/EnvironmentConfig.test.ts (re-imports EnvironmentConfig with controlled env via jest.resetModules() + import()):

  1. The internal URL uses the internal hostname (oneuptime-app:3002), not the public HOST.
  2. It targets the /api/status-page internal route.
  3. It stays on http:// even when HTTP_PROTOCOL=https (in-cluster traffic shouldn't go through TLS/ingress).

Tests 1 and 3 fail without the source change, confirming they are real regression guards. Prettier-clean and type-checks pass.

node node_modules/.bin/jest --runInBand ./Tests/Server/EnvironmentConfig.test.ts
# 3 passed

Fixes #2475

StatusPageApiInternalUrl is used for server-to-server (in-cluster) calls
such as the status page SEO lookup the app makes about itself. It was
built from AppApiClientUrl, which uses the public HOST and HTTP_PROTOCOL.
In Kubernetes/multi-host deployments this makes the pod call its own
public ingress, causing `APIException: ... connect ETIMEDOUT`.

Build it from AppApiHostname (SERVER_APP_HOSTNAME:APP_PORT) over http
instead, matching the internal-URL pattern already used by MailService,
SmsService, etc. The /api/status-page path is unchanged, so only the host
and protocol move from public to internal — which is what the existing
comment on this constant already claimed it did.

Adds tests asserting the internal URL uses the internal hostname (not the
public host), targets /api/status-page, and stays on http even when the
public protocol is https.

Fixes OneUptime#2475

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@simlarsen

Copy link
Copy Markdown
Contributor

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

StatusPageApiInternalUrl uses public HOST instead of internal service hostname

2 participants