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.
This commit is contained in:
Daniel Chao
2024-05-16 08:38:43 -07:00
committed by GitHub
parent 5f4d475d84
commit d0def765a2
8 changed files with 65 additions and 26 deletions

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -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)

View File

@@ -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<ModuleKey> 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() {}

View File

@@ -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();

View File

@@ -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);
}
}

View File

@@ -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())

View File

@@ -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)
}
}