# SPDX-FileCopyrightText: 2026 Bart Broere # SPDX-License-Identifier: GPL-3.0-or-later """HTTP server for the neo4j-browser static files and Neo4j discovery. Needs the ``browser`` extra: ``pip install 'peo[browser]'``. """ from starlette.applications import Starlette from starlette.datastructures import MutableHeaders from starlette.middleware import Middleware from starlette.responses import RedirectResponse, Response from starlette.routing import Mount, Route from starlette.staticfiles import StaticFiles from .discovery import discovery_document class BrowserFiles(StaticFiles): """neo4j-browser's build: index.html must be revalidated, the hashed assets can be cached.""" def file_response(self, full_path, *args, **kwargs): response = super().file_response(full_path, *args, **kwargs) response.headers["Cache-Control"] = ("no-cache" if str(full_path).endswith(".html") else "public, max-age=86400") return response def nosniff(app): async def wrapped(scope, receive, send): async def send_with_header(message): if message["type"] == "http.response.start": MutableHeaders(scope=message)["X-Content-Type-Options"] = "nosniff" await send(message) await app(scope, receive, send_with_header) return wrapped def create_app(browser_dir: str, bolt_port: int) -> Starlette: async def root(request): if "text/html" in request.headers.get("accept", ""): return RedirectResponse("/browser/", status_code=302) return Response(discovery_document(request.headers, bolt_port), media_type="application/json") async def browser(request): return RedirectResponse("/browser/", status_code=301) return Starlette( routes=[ Route("/", root), Route("/browser", browser), Mount("/browser", BrowserFiles(directory=browser_dir, html=True)), ], middleware=[Middleware(nosniff)], )