diff --git a/Stocks/WebService/app.py b/Stocks/WebService/app.py index 37cca90..bd3d3db 100644 --- a/Stocks/WebService/app.py +++ b/Stocks/WebService/app.py @@ -12,7 +12,7 @@ app = Flask(__name__) # ---- Config ---- SHARED_SECRET = os.environ.get("PROXY_SECRET", "") DB_PATH = os.environ.get("DB_PATH", "/data/cache.db") -CURRENT_TTL_SECONDS = 15 * 60 # re-check "today" every 15 min in case NAV just> +CURRENT_TTL_SECONDS = 15 * 60 # re-check "today" every 15 min in case NAV just posted _db_lock = threading.Lock() @@ -32,12 +32,6 @@ def get_db(): _current_cache = {} # ticker -> (price, resolved_date, fetched_at) _current_cache_lock = threading.Lock() -@app.after_request -def add_cors_headers(response): - response.headers["Access-Control-Allow-Origin"] = "*" - response.headers["Access-Control-Allow-Methods"] = "GET, OPTIONS" - response.headers["Access-Control-Allow-Headers"] = "Content-Type" - return response def check_auth(): key = request.args.get("key", "") @@ -50,8 +44,8 @@ def fetch_yahoo_price(ticker, target_date): period1 = int((target_date - timedelta(days=10)).timestamp()) url = f"https://query1.finance.yahoo.com/v8/finance/chart/{ticker}" - headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWe> - r = requests.get(url, params={"period1": period1, "period2": period2, "inte> + headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"} + r = requests.get(url, params={"period1": period1, "period2": period2, "interval": "1d"}, headers=headers, timeout=10) if r.status_code != 200: return None, f"yahoo http {r.status_code}" @@ -76,7 +70,7 @@ def fetch_yahoo_price(ticker, target_date): if best is None: return None, "no trading day found in window" - return {"resolved_date": best[0].strftime("%Y-%m-%d"), "price": round(best[> + return {"resolved_date": best[0].strftime("%Y-%m-%d"), "price": round(best[1], 4)}, None @app.route("/current") @@ -92,7 +86,7 @@ def current_price(): with _current_cache_lock: cached = _current_cache.get(ticker) if cached and (now - cached[2]) < CURRENT_TTL_SECONDS: - return jsonify({"ticker": ticker, "price": cached[0], "resolved_dat> + return jsonify({"ticker": ticker, "price": cached[0], "resolved_date": cached[1], "cached": True}) result, err = fetch_yahoo_price(ticker, datetime.utcnow()) if err: @@ -101,7 +95,8 @@ def current_price(): with _current_cache_lock: _current_cache[ticker] = (result["price"], result["resolved_date"], now) - return jsonify({"ticker": ticker, "price": result["price"], "resolved_date"> + return jsonify({"ticker": ticker, "price": result["price"], "resolved_date": result["resolved_date"], "cached": False}) + @app.route("/historical") def historical_price(): @@ -118,20 +113,20 @@ def historical_price(): except ValueError: return jsonify({"error": "date must be YYYY-MM-DD"}), 400 - # If someone asks "historical" for today/future, treat it like /current ins> + # If someone asks "historical" for today/future, treat it like /current instead if target_date.date() >= datetime.utcnow().date(): return current_price() with _db_lock: conn = get_db() row = conn.execute( - "SELECT resolved_date, price FROM historical_cache WHERE ticker=? A> + "SELECT resolved_date, price FROM historical_cache WHERE ticker=? AND requested_date=?", (ticker, date_str), ).fetchone() conn.close() if row: - return jsonify({"ticker": ticker, "requested_date": date_str, "resolved> + return jsonify({"ticker": ticker, "requested_date": date_str, "resolved_date": row[0], "price": row[1], "cached": True}) result, err = fetch_yahoo_price(ticker, target_date) if err: @@ -140,13 +135,13 @@ def historical_price(): with _db_lock: conn = get_db() conn.execute( - "INSERT OR REPLACE INTO historical_cache (ticker, requested_date, r> + "INSERT OR REPLACE INTO historical_cache (ticker, requested_date, resolved_date, price) VALUES (?, ?, ?, ?)", (ticker, date_str, result["resolved_date"], result["price"]), ) conn.commit() conn.close() - return jsonify({"ticker": ticker, "requested_date": date_str, "resolved_dat> + return jsonify({"ticker": ticker, "requested_date": date_str, "resolved_date": result["resolved_date"], "price": result["price"], "cached": False}) @app.route("/health")