add support for custom HTTP headers#13
Conversation
Adds generic `--header 'Name: Value'` flag (repeatable) and a per-profile persistent file `~/.ucp/profiles/<name>/headers.json` with `default` + `businesses[<origin>]` sections — shape mirrors git's `[http]` / `[http "<URL>"]`. Seed a built-in `User-Agent: @shopify/ucp-cli/<version>` at lowest priority on every outbound fetch (mcp-client + cache), overridable from every other source. Four-source merge, higher wins on case-insensitive header-name conflict: built-in → config.default → config.businesses[origin] → --header. Non-conflicting headers from every source ship. Reserved framing headers (Content-Type, Accept, Host, hop-by-hop, MCP-Protocol-Version) are silently dropped from user sources. Sensitive values (Authorization, Cookie, suffix -Token / -Key / -Secret / -Password) are redacted in verbose traces.
b2b524c to
917c375
Compare
|
Reviewed the custom-header flow in this PR. The resolver/merge/redaction layer looks solid, and operation dispatch plus One gap I noticed: the top-level const discoverResult = await discoverImpl(businessUrl, {
force: c.options.refresh,
profileUrl: requireProfileUrl(session.profile.profileUrl),
})So a merchant that requires auth/tenant headers even for ucp discover --business https://merchant.example --header "Authorization: Bearer $TOKEN"That seems like the one place where the feature promise and CLI surface diverge. Suggested fix: add the same repeatable I did not test against private merchants or send credentials; this is just a static review of the public PR diff. |
1. Single outbound HTTP entry point (src/core/http-client.ts).
`ucpFetch(url, opts)` owns:
- built-in User-Agent at lowest priority (overridable from any source),
- merging caller-supplied resolved headers,
- applying dispatcher-owned framing headers (Content-Type, Accept) last,
- verbose-mode trace of the redacted outbound header bag.
mcpRpc, fetchCached, and the doctor profile-URL probe all route through
ucpFetch. The doctor probe now identifies as @shopify/ucp-cli/<version>
in merchant logs like every other fetch.
2. Single header-resolution helper (`resolveCallHeaders` in src/cli.ts).
Replaces three near-identical inline blocks. Consumed by opRun,
inputSchemaOperation, and the discover command. Future commands have
one obvious function to call.
|
@TateLyman great catch sir, ty! Fixed and centralized the logic so we have a unified path. |
Adds generic
--header 'Name: Value'flag (repeatable) and aper-profile persistent file
~/.ucp/profiles/<name>/headers.jsonwithdefault+businesses[<origin>]sections — shape mirrors git's[http]/[http "<URL>"]. Seed a built-inUser-Agent: @shopify/ucp-cli/<version>at lowest priority on everyoutbound fetch (mcp-client + cache), overridable from every other source.
Four-source merge, higher wins on case-insensitive header-name conflict:
built-in → config.default → config.businesses[origin] → --header.
Non-conflicting headers from every source ship.
Reserved framing headers (Content-Type, Accept, Host, hop-by-hop,
MCP-Protocol-Version) are silently dropped from user sources. Sensitive
values (Authorization, Cookie, suffix -Token / -Key / -Secret /
-Password) are redacted in verbose traces.