Replace embedded flag with same-origin API probe

- Server serves frontend verbatim (drop window.PYSIM_EMBEDDED injection)
- Frontend probes /api/version once; res.ok -> relative base + cleared URL input,
  otherwise fall back to http://127.0.0.1:8080
- sw.js: never intercept/cache /api/* (live card data)
This commit is contained in:
2026-08-15 14:10:24 +03:00
parent 1971eca381
commit 966ada21eb
3 changed files with 19 additions and 11 deletions
+16 -4
View File
@@ -2635,13 +2635,25 @@ function decodeResponse() {
} }
// ===== pysim integration ===== // ===== pysim integration =====
// When served by pysim-otaman-server itself (same origin), the API is relative; // Default to a local server on 127.0.0.1:8080. If this PWA is served by
// otherwise default to the local server on 127.0.0.1:8080. // pysim-otaman-server itself (same origin), detect the co-located API once
let pysimBase = window.PYSIM_EMBEDDED ? '' : 'http://127.0.0.1:8080'; // and switch to a relative base; otherwise keep the default and wait for the
if (window.PYSIM_EMBEDDED) { // user to point at a server.
let pysimBase = 'http://127.0.0.1:8080';
async function pysimDetectSameOrigin() {
try {
const res = await fetch('/api/version', { method: 'GET', cache: 'no-store' });
if (res.ok) {
pysimBase = '';
const urlEl = document.getElementById('pysim-url'); const urlEl = document.getElementById('pysim-url');
if (urlEl) { urlEl.value = ''; urlEl.placeholder = '(same origin)'; } if (urlEl) { urlEl.value = ''; urlEl.placeholder = '(same origin)'; }
}
} catch (e) {
// no co-located API (file://, plain static server) — keep the default
}
} }
pysimDetectSameOrigin();
function esc(str) { function esc(str) {
return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;'); return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
+1
View File
@@ -32,6 +32,7 @@ self.addEventListener('activate', e => {
self.addEventListener('fetch', e => { self.addEventListener('fetch', e => {
if (!e.request.url.startsWith('http')) return; if (!e.request.url.startsWith('http')) return;
if (new URL(e.request.url).pathname.startsWith('/api/')) return; // live data, never cache
if (e.request.method !== 'GET') return; if (e.request.method !== 'GET') return;
const isNavigate = e.request.mode === 'navigate' || e.request.url.endsWith('sw.js'); const isNavigate = e.request.mode === 'navigate' || e.request.url.endsWith('sw.js');
if (isNavigate) { if (isNavigate) {
-5
View File
@@ -36,7 +36,6 @@ _STATIC_MIME = {
'.woff': 'font/woff', '.woff': 'font/woff',
'.woff2': 'font/woff2', '.woff2': 'font/woff2',
} }
_EMBEDDED_MARKER = "<script>window.PYSIM_EMBEDDED='1'</script>"
class StderrApduTracer(ApduTracer): class StderrApduTracer(ApduTracer):
@@ -801,10 +800,6 @@ class PysimHandler(BaseHTTPRequestHandler):
return return
with open(fs_path, 'rb') as f: with open(fs_path, 'rb') as f:
data = f.read() data = f.read()
if rel == 'index.html':
# Tell the frontend it is served by this server (same origin), so
# it can default to a relative API base instead of 127.0.0.1:8080.
data = data.replace(b'</head>', _EMBEDDED_MARKER.encode() + b'</head>', 1)
content_type = _STATIC_MIME.get(os.path.splitext(rel)[1].lower(), 'application/octet-stream') content_type = _STATIC_MIME.get(os.path.splitext(rel)[1].lower(), 'application/octet-stream')
self.send_response(200) self.send_response(200)
self.send_header('Content-Type', content_type) self.send_header('Content-Type', content_type)