Skip to content

feat(hook): send extra request headers from a command for auth-proxied installs - #98

Open
junoha wants to merge 1 commit into
langfuse:mainfrom
junoha:feat/additional-headers-command
Open

junoha wants to merge 1 commit into
langfuse:mainfrom
junoha:feat/additional-headers-command

Conversation

@junoha

@junoha junoha commented Sep 25, 2026

Copy link
Copy Markdown

Summary

Adds CC_LANGFUSE_HEADERS_COMMAND: a command whose stdout is a JSON object of
header name → value, passed to the SDK's additional_headers. It unblocks
self-hosted Langfuse behind an authenticating proxy, where spans are currently
exported into a login page and reported as success. Unset, nothing changes —
additional_headers=None is already the SDK default.

Closes #97, which has the mechanism and a reproduction.

Change

// ~/.claude/settings.json
"env": { "CC_LANGFUSE_HEADERS_COMMAND": "/path/to/print-proxy-headers" }

additional_headers (langfuse/langfuse-python#1248) already reaches both the
httpx client and the LangfuseSpanProcessor, so one seam covers every request
the hook makes. A command rather than a static value because the proxy token
rotates; each hook run is a fresh process, so no callable headers are needed.
Precedent: git's credential.helper and GIT_ASKPASS.

Notes for review

  • capture_output=True keeps the helper's stdout out of the hook's own stdout,
    which Claude Code parses as the hook protocol.
  • timeout=HEADERS_COMMAND_TIMEOUT (10s): the Stop hook runs every turn, so a
    wedged helper cannot hold the turn open.
  • Fail-open through the existing info(), and nothing sensitive is logged: key
    names on success, exception type and exit status on failure, because str() of
    a CalledProcessError repeats the command line.
  • A non-object and an empty object are both rejected, each with its own message.
  • shell=True is the same trust level as the hook command itself: user config,
    not remote input.
  • Headers are not filtered, so Authorization can be overridden deliberately.

Verification

  • uv run --group dev pytest → 294 passed on Python 3.10 and 3.13; ruff clean;
    echo '{}' | uv run --script hooks/langfuse_hook.py exits 0.
  • 15 cases in tests/unit/test_additional_headers.py cover the headers reaching
    the SDK, the wizard option as a fallback, every failure mode (non-zero exit,
    timeout, missing helper, bad JSON, non-object, empty object, no output) being
    fail-open, and neither header values nor the command line reaching the log.
  • In use against a self-hosted v4 behind an OIDC proxy: with the cookie in
    additional_headers traces arrive, without it they silently do not.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

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.

No way to send extra request headers — Langfuse behind an authenticating proxy cannot be reached

1 participant