openvibers/openvibe.live Commits
WHIP: build the session Location on the host the client reached us on
Changes
@@@ -46,7 +46,16 @@ function normalizeOrigin(value) {}function buildWhipResourceUrl(req, streamId, resourceId) {-- const baseUrl = normalizeOrigin(config.whip?.publicUrl || config.webrtc?.publicUrl || config.baseUrl) || `${req.protocol}://${req.get('host')}`;++ // The session resource lives on the host the client just reached us on. Encoders keep++ // the WHIP URL they were configured with (openvibe.live, whip.openvibe.live, …) long++ // after the advertised host changes, and a Location on a different host would send++ // their PATCH/DELETE somewhere they may not resolve or allowlist. Only fall back to++ // the configured public origin when the request carries no usable Host.++ const requestOrigin = (typeof req?.get === 'function' && req.get('host'))++ ? normalizeOrigin(`${req.protocol || 'https'}://${req.get('host')}`)++ : null;++ const baseUrl = requestOrigin++ || normalizeOrigin(config.whip?.publicUrl || config.webrtc?.publicUrl || config.baseUrl);try {return new URL(`/whip/${streamId}/${resourceId}`, baseUrl).toString();} catch {@@@ -49,7 +49,15 @@ const req = {};const headers = buildWhipResponseHeaders(req, '123', 'resource-abc');--assert.strictEqual(headers.Location, 'http://localhost:3000/whip/123/resource-abc');++// The session resource must live on the host the encoder reached us on, so configs that++// still point at an older hostname (openvibe.live, whip.openvibe.live) keep working after++// the advertised WHIP host moves.++assert.strictEqual(headers.Location, 'https://whip.example.com/whip/123/resource-abc');++// Without a usable Host header, fall back to the configured public origin.++assert.strictEqual(++ buildWhipResponseHeaders({ protocol: 'https', get: () => undefined }, '123', 'resource-abc').Location,++ 'http://localhost:3000/whip/123/resource-abc'++);// A browser can only read the resource URL (and our error code) if both are exposed.assert.strictEqual(headers['Access-Control-Expose-Headers'], 'Location, X-WHIP-ERROR');assert.ok(!Object.prototype.hasOwnProperty.call(headers, 'Link'));
@@ -46,7 +46,16 @@ function normalizeOrigin(value) {
@@ -46,7 +46,16 @@ function normalizeOrigin(value) {
}
}
function buildWhipResourceUrl(req, streamId, resourceId) {
function buildWhipResourceUrl(req, streamId, resourceId) {
- const baseUrl = normalizeOrigin(config.whip?.publicUrl || config.webrtc?.publicUrl || config.baseUrl) || `${req.protocol}://${req.get('host')}`;
+ // The session resource lives on the host the client just reached us on. Encoders keep
+ // the WHIP URL they were configured with (openvibe.live, whip.openvibe.live, …) long
+ // after the advertised host changes, and a Location on a different host would send
+ // their PATCH/DELETE somewhere they may not resolve or allowlist. Only fall back to
+ // the configured public origin when the request carries no usable Host.
+ const requestOrigin = (typeof req?.get === 'function' && req.get('host'))
+ ? normalizeOrigin(`${req.protocol || 'https'}://${req.get('host')}`)
+ : null;
+ const baseUrl = requestOrigin
+ || normalizeOrigin(config.whip?.publicUrl || config.webrtc?.publicUrl || config.baseUrl);
try {
try {
return new URL(`/whip/${streamId}/${resourceId}`, baseUrl).toString();
return new URL(`/whip/${streamId}/${resourceId}`, baseUrl).toString();
} catch {
} catch {
@@ -49,7 +49,15 @@ const req = {
@@ -49,7 +49,15 @@ const req = {
};
};
const headers = buildWhipResponseHeaders(req, '123', 'resource-abc');
const headers = buildWhipResponseHeaders(req, '123', 'resource-abc');
-assert.strictEqual(headers.Location, 'http://localhost:3000/whip/123/resource-abc');
+// The session resource must live on the host the encoder reached us on, so configs that
+// still point at an older hostname (openvibe.live, whip.openvibe.live) keep working after
+// the advertised WHIP host moves.
+assert.strictEqual(headers.Location, 'https://whip.example.com/whip/123/resource-abc');
+// Without a usable Host header, fall back to the configured public origin.
+assert.strictEqual(
+ buildWhipResponseHeaders({ protocol: 'https', get: () => undefined }, '123', 'resource-abc').Location,
+ 'http://localhost:3000/whip/123/resource-abc'
+);
// A browser can only read the resource URL (and our error code) if both are exposed.
// A browser can only read the resource URL (and our error code) if both are exposed.
assert.strictEqual(headers['Access-Control-Expose-Headers'], 'Location, X-WHIP-ERROR');
assert.strictEqual(headers['Access-Control-Expose-Headers'], 'Location, X-WHIP-ERROR');
assert.ok(!Object.prototype.hasOwnProperty.call(headers, 'Link'));
assert.ok(!Object.prototype.hasOwnProperty.call(headers, 'Link'));