openvibers/openvibe.ai Commits
A page that is not here goes to the same path on Exchange (#508)
Changes
@@@ -361,12 +361,14 @@ function createApp({ choices = null, searchFetch = null, config, db, registry, pres.type('text/plain').send(`User-agent: *\nAllow: /llms.txt\nAllow: /api/v1/creations\nAllow: /api/v1/creations.md\nDisallow: /\nDisallow: /runs\nDisallow: /console\nDisallow: /auth/\nDisallow: /api/\n\n# The human site is OpenVibe.Exchange; the API stays here.\nSitemap: ${EXCHANGE}/sitemap.xml\n`);});-- // A browser asking for a page that is not here goes to the Exchange home: the human site moved, and a-- // stale link should land on the product, not a 404. An API or session path still answers as it did.++ // A browser asking for a page that is not here goes to the same path on Exchange: the human site moved, so a++ // stale link lands on the page of that name, and a page that never existed is Exchange's honest 404 (11-12: sending++ // every miss to the home was a soft 404 the release browser check failed on). An API or session path still answers++ // as it did.const MACHINE_PATH = /^\/(?:api|v1|internal|metrics|shared|release\.json|release-metrics|auth|console|runs|favicon\.ico|robots\.txt)(?:\/|$)/;app.use((req, res) => {if (req.method === 'GET' && !MACHINE_PATH.test(req.path) && req.accepts(['application/json', 'text/html']) === 'text/html') {-- return res.redirect(301, `${EXCHANGE}/`);++ return res.redirect(301, `${EXCHANGE}${req.originalUrl.startsWith('/') ? req.originalUrl : '/'}`);}return http.sendProblem(res, 404, 'ai.not_found', { detail: `no route ${req.method} ${req.path}`, ctx: req.ov });});@@@ -1,7 +1,7 @@'use strict';// The public pages of ai.openvibe.services moved to openvibe.exchange on 2026-11-07. This origin keeps the API,// a run's receipt and the operator console; every human page answers 301 on an exact map (an unknown human path--// goes to the Exchange home), and no API path is ever redirected. The text/plain API index for curl stays.++// goes to the same path on Exchange), and no API path is ever redirected. The text/plain API index for curl stays.const assert = require('assert');const fs = require('fs');const path = require('path');@@@ -69,9 +69,10 @@ t.test('/llms.txt stays on AI and carries the creation catalogue', async () => {assert.ok(r.text.includes('Write a blog post'), 'lists a live creation');});--t.test('an unknown human page goes to the Exchange home; an unknown API path stays a problem document', async () => {-- await moved('/prices-and-latency', '/');-- await moved('/some-old-post', '/');++t.test('an unknown human page goes to the same path on Exchange (its page, or its honest 404); an unknown API path stays a problem document', async () => {++ await moved('/prices-and-latency', '/prices-and-latency');++ await moved('/some-old-post?ref=x', '/some-old-post?ref=x');++ await moved('/__ovcheck-404', '/__ovcheck-404');for (const p of ['/api/nope', '/v1/nope', '/api/v1/nope']) {const r = await request(h.base, 'GET', p, { headers: { Accept: BROWSER }, redirect: 'manual' });assert.strictEqual(r.status, 404, p);
@@ -361,12 +361,14 @@ function createApp({ choices = null, searchFetch = null, config, db, registry, p
@@ -361,12 +361,14 @@ function createApp({ choices = null, searchFetch = null, config, db, registry, p
res.type('text/plain').send(`User-agent: *\nAllow: /llms.txt\nAllow: /api/v1/creations\nAllow: /api/v1/creations.md\nDisallow: /\nDisallow: /runs\nDisallow: /console\nDisallow: /auth/\nDisallow: /api/\n\n# The human site is OpenVibe.Exchange; the API stays here.\nSitemap: ${EXCHANGE}/sitemap.xml\n`);
res.type('text/plain').send(`User-agent: *\nAllow: /llms.txt\nAllow: /api/v1/creations\nAllow: /api/v1/creations.md\nDisallow: /\nDisallow: /runs\nDisallow: /console\nDisallow: /auth/\nDisallow: /api/\n\n# The human site is OpenVibe.Exchange; the API stays here.\nSitemap: ${EXCHANGE}/sitemap.xml\n`);
});
});
- // A browser asking for a page that is not here goes to the Exchange home: the human site moved, and a
- // stale link should land on the product, not a 404. An API or session path still answers as it did.
+ // A browser asking for a page that is not here goes to the same path on Exchange: the human site moved, so a
+ // stale link lands on the page of that name, and a page that never existed is Exchange's honest 404 (11-12: sending
+ // every miss to the home was a soft 404 the release browser check failed on). An API or session path still answers
+ // as it did.
const MACHINE_PATH = /^\/(?:api|v1|internal|metrics|shared|release\.json|release-metrics|auth|console|runs|favicon\.ico|robots\.txt)(?:\/|$)/;
const MACHINE_PATH = /^\/(?:api|v1|internal|metrics|shared|release\.json|release-metrics|auth|console|runs|favicon\.ico|robots\.txt)(?:\/|$)/;
app.use((req, res) => {
app.use((req, res) => {
if (req.method === 'GET' && !MACHINE_PATH.test(req.path) && req.accepts(['application/json', 'text/html']) === 'text/html') {
if (req.method === 'GET' && !MACHINE_PATH.test(req.path) && req.accepts(['application/json', 'text/html']) === 'text/html') {
- return res.redirect(301, `${EXCHANGE}/`);
+ return res.redirect(301, `${EXCHANGE}${req.originalUrl.startsWith('/') ? req.originalUrl : '/'}`);
}
}
return http.sendProblem(res, 404, 'ai.not_found', { detail: `no route ${req.method} ${req.path}`, ctx: req.ov });
return http.sendProblem(res, 404, 'ai.not_found', { detail: `no route ${req.method} ${req.path}`, ctx: req.ov });
});
});
@@ -1,7 +1,7 @@
@@ -1,7 +1,7 @@
'use strict';
'use strict';
// The public pages of ai.openvibe.services moved to openvibe.exchange on 2026-11-07. This origin keeps the API,
// The public pages of ai.openvibe.services moved to openvibe.exchange on 2026-11-07. This origin keeps the API,
// a run's receipt and the operator console; every human page answers 301 on an exact map (an unknown human path
// a run's receipt and the operator console; every human page answers 301 on an exact map (an unknown human path
-// goes to the Exchange home), and no API path is ever redirected. The text/plain API index for curl stays.
+// goes to the same path on Exchange), and no API path is ever redirected. The text/plain API index for curl stays.
const assert = require('assert');
const assert = require('assert');
const fs = require('fs');
const fs = require('fs');
const path = require('path');
const path = require('path');
@@ -69,9 +69,10 @@ t.test('/llms.txt stays on AI and carries the creation catalogue', async () => {
@@ -69,9 +69,10 @@ t.test('/llms.txt stays on AI and carries the creation catalogue', async () => {
assert.ok(r.text.includes('Write a blog post'), 'lists a live creation');
assert.ok(r.text.includes('Write a blog post'), 'lists a live creation');
});
});
-t.test('an unknown human page goes to the Exchange home; an unknown API path stays a problem document', async () => {
- await moved('/prices-and-latency', '/');
- await moved('/some-old-post', '/');
+t.test('an unknown human page goes to the same path on Exchange (its page, or its honest 404); an unknown API path stays a problem document', async () => {
+ await moved('/prices-and-latency', '/prices-and-latency');
+ await moved('/some-old-post?ref=x', '/some-old-post?ref=x');
+ await moved('/__ovcheck-404', '/__ovcheck-404');
for (const p of ['/api/nope', '/v1/nope', '/api/v1/nope']) {
for (const p of ['/api/nope', '/v1/nope', '/api/v1/nope']) {
const r = await request(h.base, 'GET', p, { headers: { Accept: BROWSER }, redirect: 'manual' });
const r = await request(h.base, 'GET', p, { headers: { Accept: BROWSER }, redirect: 'manual' });
assert.strictEqual(r.status, 404, p);
assert.strictEqual(r.status, 404, p);