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:
co-authored by
Claude Fable 5
parent
4be6ecb984
commit
67d0ef421b
@@ -17,6 +17,10 @@ the git history of `docs/examples/werkbaum.werkbaum`. A day can therefore carry
|
||||
a link without having a note (someone forgot to write one) — but never the
|
||||
reverse.
|
||||
|
||||
## 2026-08-27
|
||||
|
||||
- Fix: sharing from an instance without its own backend (GitHub Pages) failed with HTTP 405 — the share button now probes the default address and asks for the server instead
|
||||
|
||||
## 2026-08-26
|
||||
|
||||
- The document picker moved into the app header: `Werkbaum › name` opens the menu — on the phone it is reachable from both panes, and the name takes over the subtitle line
|
||||
|
||||
@@ -7006,3 +7006,38 @@ stellt Text und Knopfzustände zurück, ohne das Menü zu schließen; Löschen
|
||||
eines nicht-aktiven Dokuments lässt den Editor unangetastet; auf dem Telefon
|
||||
ist der Wähler aus dem Diagramm-Bereich erreichbar und der Wechsel rendert
|
||||
183 Knoten, langer Name füllt die 335-px-Chipzeile mit Ellipse.
|
||||
|
||||
**Nachtrag — vor dem Teilen wird die Basis-Adresse per Lebendprobe geprüft.**
|
||||
Gemeldet vom ersten echten Druck auf den neuen Teilen-Knopf: „Server-Dokument
|
||||
nicht geladen: https://mhoennig.github.io/api/v1/documents (HTTP 405)." Die
|
||||
Ursache liegt nicht im Knopf, sondern in der Vorgabe aus D76-Nachtrag 8: Die
|
||||
Basis-Adresse ist die **eigene Herkunft** — richtig auf der produktiven
|
||||
Installation (dort liegt `/api/` per Proxy dahinter, D77), falsch auf jeder
|
||||
statischen Instanz. GitHub Pages beantwortet den POST mit 405, und die
|
||||
Meldung führte auf die falsche Fährte („ist die Adresse eine
|
||||
Dokument-Adresse?"). Der Fehler war schon vor D81 da; der Knopf in der
|
||||
Titelzeile hat ihn nur sichtbar gemacht — im Menü hat ihn dort schlicht
|
||||
niemand gedrückt.
|
||||
|
||||
**Gefixt mit der Lebendprobe, die es schon gibt:** `GET /api/v1/info` (D77,
|
||||
gebaut genau als „antwortet hier die Anwendung?"). `serverBaseOrAsk()` prüft
|
||||
die Vorgabe damit, **bevor** gePOSTet wird; besteht sie nicht, wird
|
||||
**gefragt** — der vorhandene Dialog samt gemerkter Antwort. Gemerkt wird nur
|
||||
eine Adresse, die die Probe besteht: Ein Tippfehler klemmt sich nicht fest
|
||||
(und eine gemerkte Adresse, deren Backend verschwindet, heilt sich beim
|
||||
nächsten Teilen von selbst — Probe scheitert, es wird neu gefragt). Eine
|
||||
eingegebene Adresse, die nicht antwortet, wird trotzdem versucht — der
|
||||
POST-Fehlerpfad nennt dann ehrlich, was nicht erreichbar war, statt dass der
|
||||
Dialog stumm wieder aufgeht.
|
||||
|
||||
**Von Pages aus funktioniert das Teilen damit wirklich:** Das Backend erlaubt
|
||||
CORS `*` (D76-Nachtrag 7) — wer auf `mhoennig.github.io` arbeitet und im
|
||||
Dialog `https://werkbaum.javagil.de` einträgt, legt sein Dokument dort ab.
|
||||
Gemessen aus dem Browser: Die Probe gegen die stabile Instanz besteht
|
||||
cross-origin.
|
||||
|
||||
**Nachgemessen** am Dev-Server (dieselbe Lage wie Pages: keine eigene
|
||||
`/api/`): Teilen öffnet jetzt den Adress-Dialog statt der 405-Warnung,
|
||||
Abbruch tut nichts; die Probe gegen das echte Backend liefert
|
||||
`{name:"editor-backend"}`. `infoUrl()` liegt headless in live.js (39
|
||||
Live-Tests, +1).
|
||||
|
||||
+25
-5
@@ -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{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user