360 / app.py
Neon-AI's picture
Update app.py
d52d7f3 verified
import streamlit as st
import asyncio
import json
from playwright.async_api import async_playwright
st.set_page_config(page_title="Network Inspector", layout="wide")
st.title("πŸ” Network Request Inspector")
st.caption("Paste a Goal.com match URL to intercept all API calls")
# persist results across reruns
if "logs" not in st.session_state:
st.session_state.logs = []
url = st.text_input("Match URL", placeholder="https://www.goal.com/en-ng/match/...")
if st.button("Inspect") and url:
with st.spinner("Loading page and intercepting requests..."):
async def intercept(target_url):
requests_log = []
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
context = await browser.new_context(
user_agent="Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15"
)
page = await context.new_page()
async def handle_request(request):
if request.resource_type in ("xhr", "fetch"):
requests_log.append({
"method": request.method,
"url": request.url,
"type": request.resource_type,
})
async def handle_response(response):
if response.request.resource_type in ("xhr", "fetch"):
for r in requests_log:
if r["url"] == response.url and "status" not in r:
r["status"] = response.status
try:
body = await response.text()
r["preview"] = body[:500]
except Exception:
r["preview"] = "(could not read body)"
break
page.on("request", handle_request)
page.on("response", handle_response)
await page.goto(target_url, wait_until="domcontentloaded", timeout=90000)
await page.wait_for_timeout(8000)
await browser.close()
return requests_log
st.session_state.logs = asyncio.run(intercept(url))
if st.session_state.logs:
logs = st.session_state.logs
st.success(f"Captured {len(logs)} XHR/fetch requests")
filter_text = st.text_input("Filter URLs (e.g. commentary, api, sportfeeds)", "")
filtered = [r for r in logs if filter_text.lower() in r["url"].lower()] if filter_text else logs
st.write(f"Showing {len(filtered)} requests")
for r in filtered:
status = r.get("status", "?")
color = "🟒" if status == 200 else "πŸ”΄"
with st.expander(f"{color} [{r['method']}] {r['url'][:120]} (HTTP {status})"):
st.code(r["url"], language="text")
if "preview" in r:
st.subheader("Response preview")
try:
st.json(json.loads(r["preview"]))
except Exception:
st.text(r["preview"])