mirror of
https://github.com/apple/pkl.git
synced 2026-04-22 16:28:34 +02:00
Add support for HTTP rewrites (#1062)
This adds a new configuration option for the HTTP client to replace URI prefixes when making outbound calls. Follows the design of https://github.com/apple/pkl-evolution/pull/17
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -140,6 +140,9 @@ data class CliBaseOptions(
|
||||
/** Hostnames, IP addresses, or CIDR blocks to not proxy. */
|
||||
val httpNoProxy: List<String>? = null,
|
||||
|
||||
/** URL prefixes to rewrite. */
|
||||
val httpRewrites: Map<URI, URI>? = null,
|
||||
|
||||
/** External module reader process specs */
|
||||
val externalModuleReaders: Map<String, ExternalReader> = mapOf(),
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.pkl.commons.cli
|
||||
|
||||
import java.net.URI
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.util.regex.Pattern
|
||||
@@ -166,29 +167,36 @@ abstract class CliCommand(protected val cliOptions: CliBaseOptions) {
|
||||
|
||||
protected val useColor: Boolean by lazy { cliOptions.color?.hasColor() ?: false }
|
||||
|
||||
private val proxyAddress by lazy {
|
||||
private val proxyAddress: URI? by lazy {
|
||||
cliOptions.httpProxy
|
||||
?: project?.evaluatorSettings?.http?.proxy?.address
|
||||
?: settings.http?.proxy?.address
|
||||
}
|
||||
|
||||
private val noProxy by lazy {
|
||||
private val noProxy: List<String>? by lazy {
|
||||
cliOptions.httpNoProxy
|
||||
?: project?.evaluatorSettings?.http?.proxy?.noProxy
|
||||
?: settings.http?.proxy?.noProxy
|
||||
}
|
||||
|
||||
private val externalModuleReaders by lazy {
|
||||
private val httpRewrites: Map<URI, URI>? by lazy {
|
||||
cliOptions.httpRewrites
|
||||
?: project?.evaluatorSettings?.http?.rewrites
|
||||
?: settings.http?.rewrites()
|
||||
}
|
||||
|
||||
private val externalModuleReaders: Map<String, PklEvaluatorSettings.ExternalReader> by lazy {
|
||||
(project?.evaluatorSettings?.externalModuleReaders ?: emptyMap()) +
|
||||
cliOptions.externalModuleReaders
|
||||
}
|
||||
|
||||
private val externalResourceReaders by lazy {
|
||||
private val externalResourceReaders: Map<String, PklEvaluatorSettings.ExternalReader> by lazy {
|
||||
(project?.evaluatorSettings?.externalResourceReaders ?: emptyMap()) +
|
||||
cliOptions.externalResourceReaders
|
||||
}
|
||||
|
||||
private val externalProcesses by lazy {
|
||||
private val externalProcesses:
|
||||
Map<PklEvaluatorSettings.ExternalReader, ExternalReaderProcess> by lazy {
|
||||
// Share ExternalReaderProcess instances between configured external resource/module readers
|
||||
// with the same spec. This avoids spawning multiple subprocesses if the same reader implements
|
||||
// both reader types and/or multiple schemes.
|
||||
@@ -232,6 +240,7 @@ abstract class CliCommand(protected val cliOptions: CliBaseOptions) {
|
||||
if ((proxyAddress ?: noProxy) != null) {
|
||||
setProxy(proxyAddress, noProxy ?: listOf())
|
||||
}
|
||||
httpRewrites?.let(::setRewrites)
|
||||
// Lazy building significantly reduces execution time of commands that do minimal work.
|
||||
// However, it means that HTTP client initialization errors won't surface until an HTTP
|
||||
// request is made.
|
||||
|
||||
@@ -235,6 +235,39 @@ class BaseOptions : OptionGroup() {
|
||||
.single()
|
||||
.split(",")
|
||||
|
||||
val httpRewrites: Map<URI, URI> by
|
||||
option(
|
||||
names = arrayOf("--http-rewrite"),
|
||||
metavar = "from=to",
|
||||
help = "URL prefixes that should be rewritten.",
|
||||
)
|
||||
.convert { it ->
|
||||
val uris = it.split("=", limit = 2)
|
||||
require(uris.size == 2) { "Rewrites must be in the form of <from>=<to>" }
|
||||
try {
|
||||
val (fromSpec, toSpec) = uris
|
||||
val fromUri = URI(fromSpec).also { IoUtils.validateRewriteRule(it) }
|
||||
val toUri = URI(toSpec).also { IoUtils.validateRewriteRule(it) }
|
||||
fromUri to toUri
|
||||
} catch (e: IllegalArgumentException) {
|
||||
fail(e.message!!)
|
||||
} catch (e: URISyntaxException) {
|
||||
val message = buildString {
|
||||
append("Rewrite target `${e.input}` has invalid syntax (${e.reason}).")
|
||||
if (e.index > -1) {
|
||||
append("\n\n")
|
||||
append(e.input)
|
||||
append("\n")
|
||||
append(" ".repeat(e.index))
|
||||
append("^")
|
||||
}
|
||||
}
|
||||
fail(message)
|
||||
}
|
||||
}
|
||||
.multiple()
|
||||
.toMap()
|
||||
|
||||
val externalModuleReaders: Map<String, ExternalReader> by
|
||||
option(
|
||||
names = arrayOf("--external-module-reader"),
|
||||
@@ -289,6 +322,7 @@ class BaseOptions : OptionGroup() {
|
||||
caCertificates = caCertificates,
|
||||
httpProxy = proxy,
|
||||
httpNoProxy = noProxy ?: emptyList(),
|
||||
httpRewrites = httpRewrites.ifEmpty { null },
|
||||
externalModuleReaders = externalModuleReaders,
|
||||
externalResourceReaders = externalResourceReaders,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user