← back to Approvals Viewer
approvals-viewer: skip auth for loopback (fixes blank page)
ecc4f6c656082cb9d98527bbd5d3b053374f22dc · 2026-07-28 09:19:35 -0700 · Steve Abrams
Chrome drops the userinfo credential on the follow-up /api/drafts fetch, so the
data call 401'd and the page rendered blank. Loopback (this Mac) is now trusted
and served without auth; remote callers still need basic auth admin/DW2024!.
Files touched
Diff
commit ecc4f6c656082cb9d98527bbd5d3b053374f22dc
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue Jul 28 09:19:35 2026 -0700
approvals-viewer: skip auth for loopback (fixes blank page)
Chrome drops the userinfo credential on the follow-up /api/drafts fetch, so the
data call 401'd and the page rendered blank. Loopback (this Mac) is now trusted
and served without auth; remote callers still need basic auth admin/DW2024!.
---
server.js | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/server.js b/server.js
index 885c2a0..8d00b82 100644
--- a/server.js
+++ b/server.js
@@ -166,11 +166,16 @@ load();
}
http.createServer((req, res) => {
- // basic auth
- const hdr = req.headers.authorization || '';
- const [, b64] = hdr.split(' ');
- const [u, p] = Buffer.from(b64 || '', 'base64').toString().split(':');
- if (u !== USER || p !== PASS) { res.writeHead(401, { 'WWW-Authenticate': 'Basic realm=approvals' }); return res.end('auth required'); }
+ // Loopback (this Mac) is trusted — no auth, so the browser fetch never 401s.
+ // Any non-local caller still needs basic auth admin/DW2024!.
+ const ip = (req.socket.remoteAddress || '').replace('::ffff:', '');
+ const isLocal = ip === '127.0.0.1' || ip === '::1' || ip === 'localhost';
+ if (!isLocal) {
+ const hdr = req.headers.authorization || '';
+ const [, b64] = hdr.split(' ');
+ const [u, p] = Buffer.from(b64 || '', 'base64').toString().split(':');
+ if (u !== USER || p !== PASS) { res.writeHead(401, { 'WWW-Authenticate': 'Basic realm=approvals' }); return res.end('auth required'); }
+ }
if (req.url === '/' ) { res.writeHead(200, { 'Content-Type': 'text/html' }); return res.end(page()); }
if (req.url === '/api/drafts') { res.writeHead(200, { 'Content-Type': 'application/json' }); return res.end(JSON.stringify(drafts())); }
← be8f9d3 approvals-viewer: yes/no board for the pending-approval queu
·
back to Approvals Viewer
·
approvals-viewer: fix blank page — nested-quote SyntaxError a0197a4 →