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:
@@ -47,6 +47,7 @@ dependencies {
|
||||
}
|
||||
|
||||
testImplementation(projects.pklCommonsTest)
|
||||
testImplementation(libs.wiremock)
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
|
||||
@@ -487,6 +487,7 @@ public class PklPlugin implements Plugin<Project> {
|
||||
task.getTestPort().set(spec.getTestPort());
|
||||
task.getHttpProxy().set(spec.getHttpProxy());
|
||||
task.getHttpNoProxy().set(spec.getHttpNoProxy());
|
||||
task.getHttpHeaders().set(spec.getHttpHeaders());
|
||||
task.getHttpRewrites().set(spec.getHttpRewrites());
|
||||
task.getExternalModuleReaders()
|
||||
.set(providers.provider(() -> spec.getExternalModuleReaders().getAsMap()));
|
||||
|
||||
@@ -17,6 +17,8 @@ package org.pkl.gradle.spec;
|
||||
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.gradle.api.NamedDomainObjectContainer;
|
||||
import org.gradle.api.file.ConfigurableFileCollection;
|
||||
import org.gradle.api.file.DirectoryProperty;
|
||||
@@ -61,6 +63,8 @@ public interface BasePklSpec {
|
||||
|
||||
MapProperty<URI, URI> getHttpRewrites();
|
||||
|
||||
MapProperty<String, Map<String, List<String>>> getHttpHeaders();
|
||||
|
||||
NamedDomainObjectContainer<ExternalReaderSpec> getExternalModuleReaders();
|
||||
|
||||
NamedDomainObjectContainer<ExternalReaderSpec> getExternalResourceReaders();
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.nio.file.Paths;
|
||||
import java.time.Duration;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
@@ -50,7 +51,6 @@ import org.gradle.api.tasks.PathSensitivity;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.commons.cli.CliBaseOptions;
|
||||
import org.pkl.core.Pair;
|
||||
import org.pkl.core.evaluatorSettings.Color;
|
||||
import org.pkl.gradle.spec.ExternalReaderSpec;
|
||||
import org.pkl.gradle.utils.PluginUtils;
|
||||
@@ -167,7 +167,7 @@ public abstract class BasePklTask extends DefaultTask {
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
public abstract ListProperty<Pair<Pattern, List<Pair<String, String>>>> getHttpHeaders();
|
||||
public abstract MapProperty<String, Map<String, List<String>>> getHttpHeaders();
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
|
||||
@@ -15,6 +15,15 @@
|
||||
*/
|
||||
package org.pkl.gradle
|
||||
|
||||
import com.github.tomakehurst.wiremock.client.WireMock.equalTo
|
||||
import com.github.tomakehurst.wiremock.client.WireMock.get
|
||||
import com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor
|
||||
import com.github.tomakehurst.wiremock.client.WireMock.ok
|
||||
import com.github.tomakehurst.wiremock.client.WireMock.stubFor
|
||||
import com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo
|
||||
import com.github.tomakehurst.wiremock.client.WireMock.verify
|
||||
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo
|
||||
import com.github.tomakehurst.wiremock.junit5.WireMockTest
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.readText
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
@@ -24,6 +33,7 @@ import org.junit.jupiter.api.io.TempDir
|
||||
import org.pkl.commons.readString
|
||||
import org.pkl.commons.test.PackageServer
|
||||
|
||||
@WireMockTest
|
||||
class EvaluatorsTest : AbstractTest() {
|
||||
@Test
|
||||
fun `render Pcf`() {
|
||||
@@ -907,6 +917,28 @@ class EvaluatorsTest : AbstractTest() {
|
||||
assertThat(secondRun.output).contains(CONFIG_CACHE_REUSED)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `http headers`(wwRuntimeInfo: WireMockRuntimeInfo) {
|
||||
stubFor(get(urlEqualTo("/foo.pkl")).willReturn(ok("foo = 1")))
|
||||
writeBuildFile(
|
||||
"pcf",
|
||||
"""
|
||||
httpHeaders = [
|
||||
"**": ["X-Foo": ["Foo"]]
|
||||
]
|
||||
allowedModules = ["http:", "pkl:", "repl:", "file:"]
|
||||
"""
|
||||
.trimIndent(),
|
||||
)
|
||||
writePklFile(
|
||||
"""
|
||||
res = import("${wwRuntimeInfo.httpBaseUrl}/foo.pkl")
|
||||
"""
|
||||
)
|
||||
runTask("evalTest")
|
||||
verify(getRequestedFor(urlEqualTo("/foo.pkl")).withHeader("X-Foo", equalTo("Foo")))
|
||||
}
|
||||
|
||||
private fun writeBuildFile(
|
||||
// don't use `org.pkl.core.OutputFormat`
|
||||
// because test compile class path doesn't contain pkl-core
|
||||
|
||||
Reference in New Issue
Block a user