Skip to content

feat: add browser proxy helpers: forward_export_request and logfire_proxy#1697

Merged
alexmojaki merged 27 commits intopydantic:mainfrom
AlanPonnachan:feature/browser-proxy
Feb 26, 2026
Merged

feat: add browser proxy helpers: forward_export_request and logfire_proxy#1697
alexmojaki merged 27 commits intopydantic:mainfrom
AlanPonnachan:feature/browser-proxy

Conversation

@AlanPonnachan
Copy link
Copy Markdown
Contributor

@AlanPonnachan AlanPonnachan commented Feb 9, 2026

Closes #1640

Description

This PR adds experimental helper functions to simplify setting up a backend proxy for browser monitoring.

Problem:
To send traces/logs from a browser (frontend) to Logfire, the browser needs to authenticate. However, exposing the Logfire Write Token in frontend code is insecure. The recommended solution is to send data to the backend, which then forwards it to Logfire with the token injected.

Solution (Updated):
This PR introduces two new functions in logfire.experimental.forwarding to make this pattern trivial to implement while allowing maximum flexibility for production security:

  1. forward_export_request(...): A low-level function that takes request details (method, path, headers, body), strips sensitive client headers, injects the server's configured Logfire token, and securely forwards it to the Logfire API.
  2. logfire_proxy: An asynchronous Starlette/FastAPI handler. By exposing this as a standalone handler rather than a baked-in method, developers can mount it to their own routes. This makes it easy to add FastAPI dependencies (like custom authentication, CORS, or rate-limiting) to protect the endpoint.

Usage Example

FastAPI

from fastapi import FastAPI
import logfire
from logfire.experimental.forwarding import logfire_proxy

app = FastAPI()
logfire.configure()

# Mount the proxy handler. The browser OTel SDK can now send traces to /logfire-proxy/v1/traces
# Note: You can easily add dependencies here for authentication: dependencies=[Depends(verify_session)]
app.add_route('/logfire-proxy/{path:path}', logfire_proxy, methods=['POST'])

Implementation Details

  • Security: forward_export_request strictly validates that the method is POST and the target path starts with /v1/traces, /v1/logs, or /v1/metrics. It also normalizes paths to prevent directory traversal attacks.
  • Headers: Hop-by-hop headers (like Host, Content-Length) and sensitive headers (like client-side Authorization or Cookie) are stripped before forwarding.
  • DoS Mitigation: The logfire_proxy handler enforces a configurable body size limit (default 50MB) checking both the Content-Length header early and the actual body read late.
  • Observability: The outbound proxy request is wrapped in logfire.suppress_instrumentation() so the proxy doesn't generate infinite traces of its own exported telemetry.

Changes

  • New Module: Created logfire/experimental/forwarding.py to encapsulate the forwarding logic and ASGI handler, keeping the core Logfire class clean.
  • Tests: Added tests/test_experimental_forwarding.py covering path traversal, limits, method restrictions, explicit configs.

@alexmojaki alexmojaki self-requested a review February 9, 2026 17:26
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

AlanPonnachan and others added 3 commits February 10, 2026 23:07
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@codecov
Copy link
Copy Markdown

codecov bot commented Feb 14, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

devin-ai-integration[bot]

This comment was marked as resolved.

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@AlanPonnachan
Copy link
Copy Markdown
Contributor Author

@alexmojaki comments are resolved and all tests are passing.

new_headers['Authorization'] = token

try:
response = requests.request(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ideally this would use a session created in logfire.configure, which in particular would handle retrying. let that be a followup.

method=method,
url=url,
headers=new_headers,
data=body,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

possible followup: gzip compression

devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 17 additional findings in Devin Review.

Open in Devin Review

@AlanPonnachan
Copy link
Copy Markdown
Contributor Author

@alexmojaki

@alexmojaki alexmojaki merged commit 6d429f3 into pydantic:main Feb 26, 2026
18 checks passed
@alexmojaki alexmojaki changed the title feat: add browser proxy helpers: forward_request and `instrument_fastapi_proxy feat: add browser proxy helpers: forward_export_request and logfire_proxy Feb 26, 2026
@alexmojaki
Copy link
Copy Markdown
Collaborator

Thanks! Please also write some documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make it easier to proxy from the browser to the logfire backend

2 participants