fix(teilen): Basis-Adresse per Lebendprobe prüfen, sonst fragen (D81-Nachtrag)

Auf einer Instanz ohne eigenes Backend (GitHub Pages) endete Teilen mit
HTTP 405: Die Vorgabe "eigene Herkunft" (D76-Nachtrag 8) stimmt nur auf der
produktiven Installation. serverBaseOrAsk() prüft die Vorgabe jetzt mit
GET /api/v1/info (D77), bevor gePOSTet wird, und fragt sonst nach der
Server-Adresse; gemerkt wird nur eine Adresse, die die Probe besteht.
Von Pages aus trägt man werkbaum.javagil.de ein — CORS erlaubt es.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
mhoennig
2026-08-27 05:23:19 +02:00
co-authored by Claude Fable 5
parent 4be6ecb984
commit 67d0ef421b
5 changed files with 79 additions and 6 deletions
+25 -5
View File
@@ -4866,27 +4866,47 @@ function displayName(){
const SERVER_PARAM = 'server';
const LS_SERVER = 'werkbaum-server';
/* Antwortet unter dieser Basis wirklich ein Werkbaum-Backend? Die Lebendprobe
`/api/v1/info` (D77), bevor blind gePOSTet wird. */
async function probeServer(basis){
try{
const info = await fetchJson(live.infoUrl(basis));
return !!(info && info.name);
}catch(_){ return false; }
}
/* Wohin? Reihenfolge und Begründung stehen in live.js. Was dort nicht
hingehört, ist der letzte Ausweg: fragen und die Antwort merken ein
Dialog ist keine entscheidbare Regel. */
function serverBaseOrAsk(){
Dialog ist keine entscheidbare Regel.
Die Vorgabe eigene Herkunft" stimmt nur, wo das Backend wirklich dahinter
liegt (produktive Installation, D77) auf GitHub Pages oder einer anderen
statischen Instanz gibt es keins, und der POST endete dort mit einem
kryptischen 405 (D81-Nachtrag). Deshalb wird die Vorgabe erst per
Lebendprobe geprüft und sonst GEFRAGT; gemerkt wird nur eine Adresse, die
die Probe besteht ein Tippfehler klemmt sich so nicht fest. Eine
eingegebene Adresse, die nicht antwortet, wird trotzdem versucht: Der
POST-Fehlerpfad nennt dann ehrlich, was nicht erreichbar war. */
async function serverBaseOrAsk(){
const offen = liveState ? liveState.urls.doc : null;
let gemerkt = null;
try{ gemerkt = localStorage.getItem(LS_SERVER); }catch(_){}
const basis = live.serverBase(urlParam(SERVER_PARAM) || gemerkt, offen, location.href);
if(basis) return basis;
if(basis && await probeServer(basis)) return basis;
const eingabe = window.prompt(t('docToServerAsk'), 'https://');
if(!eingabe) return null;
const geprueft = live.serverBase(eingabe, null, location.href);
if(geprueft){ try{ localStorage.setItem(LS_SERVER, geprueft); }catch(_){} }
if(geprueft && await probeServer(geprueft)){
try{ localStorage.setItem(LS_SERVER, geprueft); }catch(_){}
}
return geprueft;
}
async function putOnServer(){
const d = activeDoc();
if(!d) return;
const basis = serverBaseOrAsk();
const basis = await serverBaseOrAsk();
if(!basis) return;
try{
+8
View File
@@ -77,6 +77,14 @@ export function documentsUrl(base){
return String(base).replace(/\/+$/, '') + '/api/v1/documents';
}
/* Lebendprobe (D77): antwortet hier wirklich ein Werkbaum-Backend? Vor dem
Teilen gefragt, denn die Vorgabe „eigene Herkunft" stimmt nur auf der
produktiven Installation — auf einer statischen Instanz (GitHub Pages)
bekäme der POST sonst ein kryptisches 405 (D81-Nachtrag). */
export function infoUrl(base){
return String(base).replace(/\/+$/, '') + '/api/v1/info';
}
/* ------------------------------------------------------------------ Zeilen */
/* Zeilenenden auf LF (SPEC §12). Der Server normalisiert beim Speichern
+7 -1
View File
@@ -1,7 +1,7 @@
import {describe, it, expect} from 'vitest';
import {
liveUrls, normalize, lines, text, computeOps, applyOps,
mapLine, caretToLineCol, lineColToCaret, feedAction, serverBase, documentsUrl,
mapLine, caretToLineCol, lineColToCaret, feedAction, serverBase, documentsUrl, infoUrl,
} from '../src/live.js';
describe('Adressen', () => {
@@ -195,6 +195,12 @@ describe('Basis-Adresse des Backends', () => {
.toBe('https://werkbaum.example/api/v1/documents');
});
it('die Lebendprobe fragt /api/v1/info an der Basis (D81-Nachtrag)', () => {
expect(infoUrl('https://werkbaum.example')).toBe('https://werkbaum.example/api/v1/info');
expect(infoUrl('https://werkbaum.example/unterverzeichnis/'))
.toBe('https://werkbaum.example/unterverzeichnis/api/v1/info');
});
it('der ?server=-Parameter hat Vorrang', () => {
expect(serverBase('http://localhost:8080', 'https://fremd.example/api/v1/documents/x', seite))
.toBe('http://localhost:8080');