From 29174c91088d66a91737293eb01c7c45e234adc5 Mon Sep 17 00:00:00 2001 From: consultoria-as Date: Sat, 4 Apr 2026 02:13:36 +0000 Subject: [PATCH] fix(pos): fix proxy Content-Type forwarding and SW auth caching Proxy was using resp.raw.headers (urllib3) which could miss Content-Type; switched to resp.headers. SW now skips /pos/api/auth/ to prevent stale token caching, scopes fetch to /pos/ only, and bumps cache to v2. Co-Authored-By: Claude Opus 4.6 (1M context) --- dashboard/server.py | 18 ++++++++++++------ pos/static/pwa/sw.js | 18 +++++++++++++++++- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/dashboard/server.py b/dashboard/server.py index 0ad460f..7f7afd0 100644 --- a/dashboard/server.py +++ b/dashboard/server.py @@ -185,25 +185,31 @@ def index(): # ── POS Proxy — forward /pos/* to POS server on port 5001 ── @app.route('/pos/', defaults={'path': ''}) -@app.route('/pos/', methods=['GET', 'POST', 'PUT', 'DELETE']) +@app.route('/pos/', methods=['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS']) def pos_proxy(path): import requests as req target = f'http://127.0.0.1:5001/pos/{path}' # Forward the request try: - headers = {k: v for k, v in request.headers if k.lower() not in ('host', 'content-length')} + # Forward all headers except hop-by-hop ones + excluded_req = {'host', 'content-length'} + headers = {k: v for k, v in request.headers if k.lower() not in excluded_req} resp = req.request( method=request.method, url=target, headers=headers, params=request.args, data=request.get_data(), - timeout=30 + timeout=30, + allow_redirects=False ) - # Build response + # Build response — use resp.headers (not resp.raw.headers) for correct Content-Type from flask import Response - excluded = {'content-encoding', 'transfer-encoding', 'connection'} - resp_headers = [(k, v) for k, v in resp.raw.headers.items() if k.lower() not in excluded] + excluded_resp = {'content-encoding', 'transfer-encoding', 'connection', + 'keep-alive', 'proxy-authenticate', 'proxy-authorization', + 'te', 'trailers', 'upgrade'} + resp_headers = [(k, v) for k, v in resp.headers.items() + if k.lower() not in excluded_resp] return Response(resp.content, status=resp.status_code, headers=resp_headers) except Exception as e: return jsonify({'error': f'POS server unavailable: {str(e)}'}), 502 diff --git a/pos/static/pwa/sw.js b/pos/static/pwa/sw.js index 43176d1..0be1b2d 100644 --- a/pos/static/pwa/sw.js +++ b/pos/static/pwa/sw.js @@ -1,7 +1,7 @@ // /home/Autopartes/pos/static/pwa/sw.js // Nexus POS — Service Worker v1 -const CACHE_NAME = 'nexus-pos-v1'; +const CACHE_NAME = 'nexus-pos-v2'; const APP_SHELL = [ '/pos/login', @@ -64,6 +64,22 @@ self.addEventListener('activate', function (event) { self.addEventListener('fetch', function (event) { var url = new URL(event.request.url); + // Only handle requests within /pos/ scope + if (url.pathname.indexOf('/pos/') === -1) { + return; + } + + // Never cache auth endpoints — tokens must always come from the server + if (url.pathname.indexOf('/pos/api/auth/') !== -1) { + return; + } + + // Don't cache login page — always fetch fresh to avoid stale redirects + if (url.pathname === '/pos/login' || url.pathname === '/pos/login/') { + event.respondWith(networkFirst(event.request)); + return; + } + // API calls → network-first if (url.pathname.indexOf('/pos/api/') !== -1) { event.respondWith(networkFirst(event.request));