From d0def765a2744acba6438e405373c67e4463d0ff Mon Sep 17 00:00:00 2001 From: Daniel Chao Date: Thu, 16 May 2024 08:38:43 -0700 Subject: [PATCH] Make http(s) URIs their own module key (#495) GenericUrl is a catch-all that uses URL.openConnection(). Since we now have special handling of HTTP urls, it makes more sense to put it in its own module key. --- .../src/main/kotlin/org/pkl/cli/CliRepl.kt | 1 + .../kotlin/org/pkl/commons/cli/CliCommand.kt | 1 + .../java/org/pkl/core/EvaluatorBuilder.java | 1 + .../pkl/core/module/ModuleKeyFactories.java | 16 +++++ .../java/org/pkl/core/module/ModuleKeys.java | 58 ++++++++++++++----- .../pkl/core/module/ResolvedModuleKeys.java | 12 ---- .../org/pkl/core/service/ExecutorSpiImpl.java | 1 + .../src/main/kotlin/org/pkl/server/Server.kt | 1 + 8 files changed, 65 insertions(+), 26 deletions(-) diff --git a/pkl-cli/src/main/kotlin/org/pkl/cli/CliRepl.kt b/pkl-cli/src/main/kotlin/org/pkl/cli/CliRepl.kt index f82e01bb..52338930 100644 --- a/pkl-cli/src/main/kotlin/org/pkl/cli/CliRepl.kt +++ b/pkl-cli/src/main/kotlin/org/pkl/cli/CliRepl.kt @@ -45,6 +45,7 @@ internal class CliRepl(private val options: CliEvaluatorOptions) : CliCommand(op ModuleKeyFactories.fromServiceProviders() + listOf( ModuleKeyFactories.file, + ModuleKeyFactories.http, ModuleKeyFactories.pkg, ModuleKeyFactories.projectpackage, ModuleKeyFactories.genericUrl diff --git a/pkl-commons-cli/src/main/kotlin/org/pkl/commons/cli/CliCommand.kt b/pkl-commons-cli/src/main/kotlin/org/pkl/commons/cli/CliCommand.kt index b994c65a..2e078d5a 100644 --- a/pkl-commons-cli/src/main/kotlin/org/pkl/commons/cli/CliCommand.kt +++ b/pkl-commons-cli/src/main/kotlin/org/pkl/commons/cli/CliCommand.kt @@ -164,6 +164,7 @@ abstract class CliCommand(protected val cliOptions: CliBaseOptions) { add(ModuleKeyFactories.projectpackage) addAll(ModuleKeyFactories.fromServiceProviders()) add(ModuleKeyFactories.file) + add(ModuleKeyFactories.http) add(ModuleKeyFactories.genericUrl) } } diff --git a/pkl-core/src/main/java/org/pkl/core/EvaluatorBuilder.java b/pkl-core/src/main/java/org/pkl/core/EvaluatorBuilder.java index 22f0f2b0..3c1d06b8 100644 --- a/pkl-core/src/main/java/org/pkl/core/EvaluatorBuilder.java +++ b/pkl-core/src/main/java/org/pkl/core/EvaluatorBuilder.java @@ -120,6 +120,7 @@ public final class EvaluatorBuilder { builder .addModuleKeyFactories(ModuleKeyFactories.fromServiceProviders()) .addModuleKeyFactory(ModuleKeyFactories.file) + .addModuleKeyFactory(ModuleKeyFactories.http) .addModuleKeyFactory(ModuleKeyFactories.pkg) .addModuleKeyFactory(ModuleKeyFactories.projectpackage) .addModuleKeyFactory(ModuleKeyFactories.genericUrl) diff --git a/pkl-core/src/main/java/org/pkl/core/module/ModuleKeyFactories.java b/pkl-core/src/main/java/org/pkl/core/module/ModuleKeyFactories.java index 4443f378..d02823b1 100644 --- a/pkl-core/src/main/java/org/pkl/core/module/ModuleKeyFactories.java +++ b/pkl-core/src/main/java/org/pkl/core/module/ModuleKeyFactories.java @@ -37,6 +37,9 @@ public final class ModuleKeyFactories { /** A factory for file based module keys. */ public static final ModuleKeyFactory file = new File(); + /** A factory for {@code http:} and {@code https:} module keys. */ + public static final ModuleKeyFactory http = new Http(); + /** A factory for URL based module keys. */ public static final ModuleKeyFactory genericUrl = new GenericUrl(); @@ -150,6 +153,19 @@ public final class ModuleKeyFactories { } } + private static class Http implements ModuleKeyFactory { + private Http() {} + + @Override + public Optional create(URI uri) { + var scheme = uri.getScheme(); + if ("http".equalsIgnoreCase(scheme) || "https".equalsIgnoreCase(scheme)) { + return Optional.of(ModuleKeys.http(uri)); + } + return Optional.empty(); + } + } + private static class GenericUrl implements ModuleKeyFactory { private GenericUrl() {} diff --git a/pkl-core/src/main/java/org/pkl/core/module/ModuleKeys.java b/pkl-core/src/main/java/org/pkl/core/module/ModuleKeys.java index 8cdc3bb2..48f0ddbd 100644 --- a/pkl-core/src/main/java/org/pkl/core/module/ModuleKeys.java +++ b/pkl-core/src/main/java/org/pkl/core/module/ModuleKeys.java @@ -112,6 +112,11 @@ public final class ModuleKeys { return new GenericUrl(url); } + /** Creates a module key for {@code http:} and {@code https:} uris. */ + public static ModuleKey http(URI url) { + return new Http(url); + } + /** Creates a module key for the given package. */ public static ModuleKey pkg(URI uri) throws URISyntaxException { var assetUri = new PackageAssetUri(uri); @@ -446,6 +451,45 @@ public final class ModuleKeys { } } + private static class Http implements ModuleKey { + + private final URI uri; + + Http(URI uri) { + this.uri = uri; + } + + @Override + public URI getUri() { + return uri; + } + + @Override + public boolean hasHierarchicalUris() { + return true; + } + + @Override + public boolean isGlobbable() { + return false; + } + + @Override + public ResolvedModuleKey resolve(SecurityManager securityManager) + throws IOException, SecurityManagerException { + var httpClient = VmContext.get(null).getHttpClient(); + var request = HttpRequest.newBuilder(uri).build(); + var response = httpClient.send(request, BodyHandlers.ofInputStream()); + try (var body = response.body()) { + HttpUtils.checkHasStatusCode200(response); + securityManager.checkResolveModule(response.uri()); + String text = IoUtils.readString(body); + // intentionally use uri instead of response.uri() + return ResolvedModuleKeys.virtual(this, uri, text, true); + } + } + } + private static class GenericUrl implements ModuleKey { final URI uri; @@ -472,20 +516,6 @@ public final class ModuleKeys { public ResolvedModuleKey resolve(SecurityManager securityManager) throws IOException, SecurityManagerException { securityManager.checkResolveModule(uri); - - if (HttpUtils.isHttpUrl(uri)) { - var httpClient = VmContext.get(null).getHttpClient(); - var request = HttpRequest.newBuilder(uri).build(); - var response = httpClient.send(request, BodyHandlers.ofInputStream()); - try (var body = response.body()) { - HttpUtils.checkHasStatusCode200(response); - securityManager.checkResolveModule(response.uri()); - String text = IoUtils.readString(body); - // intentionally use uri instead of response.uri() - return ResolvedModuleKeys.virtual(this, uri, text, true); - } - } - var url = IoUtils.toUrl(uri); var conn = url.openConnection(); conn.connect(); diff --git a/pkl-core/src/main/java/org/pkl/core/module/ResolvedModuleKeys.java b/pkl-core/src/main/java/org/pkl/core/module/ResolvedModuleKeys.java index 757cba1e..647bd9c3 100644 --- a/pkl-core/src/main/java/org/pkl/core/module/ResolvedModuleKeys.java +++ b/pkl-core/src/main/java/org/pkl/core/module/ResolvedModuleKeys.java @@ -18,13 +18,9 @@ package org.pkl.core.module; import java.io.IOException; import java.net.URI; import java.net.URL; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse.BodyHandlers; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import org.pkl.core.runtime.VmContext; -import org.pkl.core.util.HttpUtils; import org.pkl.core.util.IoUtils; /** Utilities for obtaining and using resolved module keys. */ @@ -106,14 +102,6 @@ public final class ResolvedModuleKeys { @Override public String loadSource() throws IOException { - if (HttpUtils.isHttpUrl(url)) { - var httpClient = VmContext.get(null).getHttpClient(); - var request = HttpRequest.newBuilder(uri).build(); - var response = httpClient.send(request, BodyHandlers.ofString()); - HttpUtils.checkHasStatusCode200(response); - return response.body(); - } - return IoUtils.readString(url); } } diff --git a/pkl-core/src/main/java/org/pkl/core/service/ExecutorSpiImpl.java b/pkl-core/src/main/java/org/pkl/core/service/ExecutorSpiImpl.java index f5072b66..077854a0 100644 --- a/pkl-core/src/main/java/org/pkl/core/service/ExecutorSpiImpl.java +++ b/pkl-core/src/main/java/org/pkl/core/service/ExecutorSpiImpl.java @@ -109,6 +109,7 @@ public final class ExecutorSpiImpl implements ExecutorSpi { .addModuleKeyFactory(ModuleKeyFactories.pkg) .addModuleKeyFactory(ModuleKeyFactories.projectpackage) .addModuleKeyFactory(ModuleKeyFactories.file) + .addModuleKeyFactory(ModuleKeyFactories.http) .addModuleKeyFactory(ModuleKeyFactories.genericUrl) .setEnvironmentVariables(options.getEnvironmentVariables()) .setExternalProperties(options.getExternalProperties()) diff --git a/pkl-server/src/main/kotlin/org/pkl/server/Server.kt b/pkl-server/src/main/kotlin/org/pkl/server/Server.kt index 21fa4a22..f703d199 100644 --- a/pkl-server/src/main/kotlin/org/pkl/server/Server.kt +++ b/pkl-server/src/main/kotlin/org/pkl/server/Server.kt @@ -223,6 +223,7 @@ class Server(private val transport: MessageTransport, private val httpClient: Ht add(ModuleKeyFactories.modulePath(modulePathResolver)) add(ModuleKeyFactories.pkg) add(ModuleKeyFactories.projectpackage) + add(ModuleKeyFactories.http) add(ModuleKeyFactories.genericUrl) } }