Skip to content

Conversation

kyokuping
Copy link

This PR adds support for custom HTTP headers, introducing a --http-header CLI flag to accept key=value pairs. These headers can also be specified within the setting.pkl file.

Closes #633

Copy link
Contributor

@HT154 HT154 left a comment

Choose a reason for hiding this comment

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

Thanks for the contribution! 🎉

I have a few primary concerns here:

  • Although rare, it is valid to send a specific header more than once in a request. When there are headers with the same name their order may also matter.
  • How does your implementation handle "reserved" headers that users should not override like Origin or User-Agent?
  • It seems less than ideal to send the same headers to all hosts, eg. if host A requires auth but host B does not, Pkl should not send a configured Authorization header to both hosts. I think a prefix matching scheme like the one used for rewrites is necessary here to ensure the proper security controls are in place.

To this end, I think the Pkl API for this needs to be something along these lines:

headers: Mapping<HttpRewrite, Listing<Pair<String, String>>>

This complicates the CLI a bit, of course, but maybe something like this is reasonable?

--http-header <prefix>='<header name>: <header value>'

@kyokuping kyokuping requested a review from HT154 September 6, 2025 14:45
@HT154
Copy link
Contributor

HT154 commented Sep 17, 2025

Just a heads up, we want reviews from the entire core team because this feature affects the core language and has security implications. One member of the team is currently out on leave so it's going to be a little bit before we can fully review this, but we haven't forgotten about it!

Comment on lines 168 to 171
/// HTTP headers to add to outbound requests targeting specified URLs.
headers: Mapping<HttpRewrite, Listing<Pair<String, String>>>?
}
Copy link
Contributor

Choose a reason for hiding this comment

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

We need the @Since annotation here for documentation purposes. It would also be good to add specificity and examples to the doc comment, similar to rewrites above.

Suggested change
/// HTTP headers to add to outbound requests targeting specified URLs.
headers: Mapping<HttpRewrite, Listing<Pair<String, String>>>?
}
/// HTTP headers to add to outbound requests targeting specified URLs.
@Since { version = "0.30.0" }
headers: Mapping<HttpRewrite, Listing<Pair<String, String>>>?
}

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm also curious if it makes sense to rename HttpRewrite to HttpPrefix (with typealias marked @Deprecated for backwards compatibility) and refactoring the corresponding Java APIs. Interested in input from @bioball and @stackoverflow on this.

Comment on lines 298 to 300
val headerParts = header.split(":", limit = 2)
require(headerParts.size == 2) { "Header '$header' is not in 'name:value' format. " }
PPair(headerParts[0], headerParts[1])
Copy link
Contributor

Choose a reason for hiding this comment

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

curl accepts this same syntax, but also accepts <name>:[ \t]+<value> and appears to strip the leading (but not trailing) whitespace from header values before sending the request. To avoid surprise for users of Pkl, it might be good to do the same. In theory, HTTP servers should be ignoring this leading (and trailing) whitespace when parsing headers so it shouldn't matter, but it might be best to avoid taking chances here.

I'm also wondering if it makes sense to do some validation of characters in headers here (and in the EvaluatorSettings API) to eagerly report invalid characters instead of lazily doing so when a matching request is made for the first time.

Copy link
Contributor

@stackoverflow stackoverflow left a comment

Choose a reason for hiding this comment

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

The design sounds sensible at first glance, but due to the complexity and security issues it may cause it may be a good idea to create a SPICE for it.
What do you think @bioball, @HT154?

Copy link
Member

@bioball bioball left a comment

Choose a reason for hiding this comment

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

Hey, thanks for the PR! I agree with @stackoverflow; it'd be good to have this discussed in a SPICE.

If you'd like to drive this feature, can you write one up? It should be submitted as PR to pkl-evolution.

Your SPICE should start by copy/pasting the template. Your SPICE number would be the next number after the latest proposed SPICE see (https://github.com/apple/pkl-evolution/pulls)

}
}
}
return underlying.send(wrappedRequestBuilder.build(), responseBodyHandler);
Copy link
Member

Choose a reason for hiding this comment

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

The logic of adding headers should be handled in RequestRewritingClient

@kyokuping
Copy link
Author

I will resume working on this PR after getting the SPICE merged!

@kyokuping kyokuping marked this pull request as draft September 25, 2025 04:30
@stackoverflow
Copy link
Contributor

As a heads up: the SPICE can only be merged once this pr is merged and released on a new version. So you only need the SPICE to be approved.

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.

Pkl package using private repo (using authentication)

4 participants