Describe the bug
When Etherpad is deployed behind a TLS-terminating reverse proxy, the generated OpenAPI document at /api/openapi.json uses an http:// URL in servers[0].url, even though Etherpad is publicly accessible over HTTPS.
Deployment topology:
Client --HTTPS--> Traefik --HTTP--> Etherpad
Etherpad is configured with:
TRUST_PROXY=true
PUBLIC_URL=https://pad.example.com
The reverse proxy preserves the public host and sends the original protocol, including:
Host: pad.example.com
X-Forwarded-Proto: https
The generated OpenAPI JSON contains:
{
"servers": [
{
"url": "http://pad.example.com/api/1.2.15"
}
]
}
The expected output is:
{
"servers": [
{
"url": "https://pad.example.com/api/1.2.15"
}
]
}
This affects OpenAPI clients, code generators, Swagger UI instances, and other consumers that use servers[0].url as the API base URL.
To Reproduce
Steps to reproduce the behavior:
-
Run Etherpad without enabling Etherpad's native SSL support.
-
Place Traefik or another TLS-terminating reverse proxy in front of Etherpad.
-
Expose Etherpad publicly at https://pad.example.com.
-
Forward requests from the reverse proxy to Etherpad over HTTP.
-
Configure Etherpad with:
TRUST_PROXY=true
PUBLIC_URL=https://pad.example.com
-
Ensure the reverse proxy sends:
Host: pad.example.com
X-Forwarded-Proto: https
-
Request the generated OpenAPI document:
curl -fsS https://pad.example.com/api/openapi.json \
| jq '.servers[0].url'
-
Observe that the result starts with http://:
"http://pad.example.com/api/1.2.15"
The same issue is also present in the version-specific OpenAPI endpoint:
/api/<version>/openapi.json
Expected behavior
The generated OpenAPI document should describe the externally reachable API URL.
When Etherpad trusts the reverse proxy and the original request protocol is HTTPS, servers[0].url should use HTTPS:
{
"servers": [
{
"url": "https://pad.example.com/api/1.2.15"
}
]
}
Direct HTTP installations should continue to generate http:// URLs, and installations where Etherpad itself terminates TLS should continue to generate https:// URLs.
Screenshots
Not applicable. The issue is visible directly in the generated JSON response.
Server (please complete the following information):
- Etherpad version: 3.3.2
- OS: RHEL 9
- Node.js version (
node --version): The one shipped with the docker image
- npm version (
npm --version): The one shipped with the docker image
- Is the server free of plugins: yes
- Are you using any abstraction IE docker? yes the default image is used (https://hub.docker.com/r/etherpad/etherpad)
Desktop (please complete the following information):
- OS: Windows 11
- Browser: Edege/Firefox
- Version 151.0.4129.72/140.13.0esr
Smartphone (please complete the following information):
- Device: Not applicable
- OS: Not applicable
- Browser: Not applicable
- Version: Not applicable
Additional context
The OpenAPI server URL is currently generated in src/node/hooks/express/openapi.ts using logic equivalent to:
url: `${settings.ssl ? 'https' : 'http'}://${req.headers.host}${apiRoot}`,
settings.ssl indicates whether Etherpad itself terminates TLS. It does not describe the protocol used by the client before TLS is terminated by a reverse proxy.
In a typical reverse-proxy deployment:
Client --HTTPS--> Traefik --HTTP--> Etherpad
Etherpad's native SSL setting is disabled, so the generated URL uses http://, despite the original client request using HTTPS.
The OpenAPI URL generation currently appears not to use:
It also appears not to use the configured public URL when constructing servers[0].url.
I am not sure what the optimal fix is for this.
It might make sense to construct the the URL differently.
For example one could use the configured public URL for things like this.
Describe the bug
When Etherpad is deployed behind a TLS-terminating reverse proxy, the generated OpenAPI document at
/api/openapi.jsonuses anhttp://URL inservers[0].url, even though Etherpad is publicly accessible over HTTPS.Deployment topology:
Etherpad is configured with:
The reverse proxy preserves the public host and sends the original protocol, including:
The generated OpenAPI JSON contains:
{ "servers": [ { "url": "http://pad.example.com/api/1.2.15" } ] }The expected output is:
{ "servers": [ { "url": "https://pad.example.com/api/1.2.15" } ] }This affects OpenAPI clients, code generators, Swagger UI instances, and other consumers that use
servers[0].urlas the API base URL.To Reproduce
Steps to reproduce the behavior:
Run Etherpad without enabling Etherpad's native SSL support.
Place Traefik or another TLS-terminating reverse proxy in front of Etherpad.
Expose Etherpad publicly at
https://pad.example.com.Forward requests from the reverse proxy to Etherpad over HTTP.
Configure Etherpad with:
Ensure the reverse proxy sends:
Request the generated OpenAPI document:
Observe that the result starts with
http://:The same issue is also present in the version-specific OpenAPI endpoint:
Expected behavior
The generated OpenAPI document should describe the externally reachable API URL.
When Etherpad trusts the reverse proxy and the original request protocol is HTTPS,
servers[0].urlshould use HTTPS:{ "servers": [ { "url": "https://pad.example.com/api/1.2.15" } ] }Direct HTTP installations should continue to generate
http://URLs, and installations where Etherpad itself terminates TLS should continue to generatehttps://URLs.Screenshots
Not applicable. The issue is visible directly in the generated JSON response.
Server (please complete the following information):
node --version): The one shipped with the docker imagenpm --version): The one shipped with the docker imageDesktop (please complete the following information):
Smartphone (please complete the following information):
Additional context
The OpenAPI server URL is currently generated in
src/node/hooks/express/openapi.tsusing logic equivalent to:settings.sslindicates whether Etherpad itself terminates TLS. It does not describe the protocol used by the client before TLS is terminated by a reverse proxy.In a typical reverse-proxy deployment:
Etherpad's native SSL setting is disabled, so the generated URL uses
http://, despite the original client request using HTTPS.The OpenAPI URL generation currently appears not to use:
It also appears not to use the configured public URL when constructing
servers[0].url.I am not sure what the optimal fix is for this.
It might make sense to construct the the URL differently.
For example one could use the configured public URL for things like this.