mirror of
https://github.com/apple/pkl.git
synced 2026-05-25 16:19:20 +02:00
Improve HTTP headers logic (#1584)
* Relax forbidden headers constraints - remove restriction on browser-related headers - allow any glob pattern (no need to end with `/` or `*`, because glob patterns already require users to explicitly declare prefix matches if that's the intention) * Replace `List<Pair<, ...>>`; use `Map<String, ...>` instead * Use glob pattern strings as an API throughout, instead of `Pattern` (e.g. in `HttpClientBuilder`) * Add HTTP headers to message passing API * Add HTTP headers to executor API (introduces `ExecutorSpiOptions4`) * Add tests for Gradle, CLI, and pkl-executor invocations * Improve documentation * Add `isGlobPattern` API to class `String` for in-language validation of http headers * Behavior change: make sure explicitly configured `User-Agent` in `HttpClientBuilder` can be shadowed by headers (allows users to set `--http-header "**=User-Agent: My User Agent"` and for this to be the only user agent). CC @kyokuping
This commit is contained in:
@@ -1614,6 +1614,24 @@ result = someLib.x
|
||||
assertThat(output).isEqualTo("result = 1\n")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `eval configured http headers`(wwRuntimeInfo: WireMockRuntimeInfo) {
|
||||
stubFor(get(anyUrl()).willReturn(ok("result = 1")))
|
||||
val file = URI("${wwRuntimeInfo.httpBaseUrl}/foo.pkl")
|
||||
val output =
|
||||
evalToConsole(
|
||||
CliEvaluatorOptions(
|
||||
CliBaseOptions(
|
||||
sourceModules = listOf(file),
|
||||
httpHeaders = mapOf("**" to mapOf("X-Foo" to listOf("Foo"))),
|
||||
allowedModules =
|
||||
listOf(Pattern.compile("http:"), Pattern.compile("file:"), Pattern.compile("pkl:")),
|
||||
)
|
||||
)
|
||||
)
|
||||
verify(getRequestedFor(urlEqualTo("/foo.pkl")).withHeader("X-Foo", equalTo("Foo")))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `eval file with non-ASCII name`() {
|
||||
val tempDirUri = tempDir.toUri()
|
||||
|
||||
@@ -169,4 +169,60 @@ class CliMainTest {
|
||||
link.createSymbolicLinkPointingTo(dir)
|
||||
return link
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `invalid http header glob pattern`() {
|
||||
val ex =
|
||||
assertThrows<BadParameterValue> {
|
||||
rootCmd.parse(arrayOf("eval", "--http-header", "foo{{}}=bar:baz", "myModule.pkl"))
|
||||
}
|
||||
assertThat(ex.message)
|
||||
.contains("Sub-patterns cannot be nested. To fix, remove or escape the inner `{` character.")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `forbidden http header name`() {
|
||||
val ex =
|
||||
assertThrows<BadParameterValue> {
|
||||
rootCmd.parse(arrayOf("eval", "--http-header", "**=Connection: baz", "myModule.pkl"))
|
||||
}
|
||||
assertThat(ex.message).contains("HTTP header `Connection` is a reserved header")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `bad http header value`() {
|
||||
val ex =
|
||||
assertThrows<BadParameterValue> {
|
||||
rootCmd.parse(arrayOf("eval", "--http-header", "**=X-Foo:🙃", "myModule.pkl"))
|
||||
}
|
||||
assertThat(ex.message).contains("HTTP header value `🙃` has invalid syntax")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `multiple headers`() {
|
||||
val cmd = RootCommand()
|
||||
cmd.parse(
|
||||
arrayOf(
|
||||
"eval",
|
||||
"--http-header",
|
||||
"**=X-Foo:Foo",
|
||||
"--http-header",
|
||||
"**=X-Foo:Foo2",
|
||||
"--http-header",
|
||||
"**=X-Bar:Bar",
|
||||
"--http-header",
|
||||
"https://example.com/**=X-Qux:Qux",
|
||||
"pkl:base",
|
||||
)
|
||||
)
|
||||
|
||||
val evalCmd = cmd.registeredSubcommands().filterIsInstance<EvalCommand>().first()
|
||||
assertThat(evalCmd.baseOptions.httpHeaders)
|
||||
.isEqualTo(
|
||||
mapOf(
|
||||
"**" to mapOf("X-Foo" to listOf("Foo", "Foo2"), "X-Bar" to listOf("Bar")),
|
||||
"https://example.com/**" to mapOf("X-Qux" to listOf("Qux")),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user