|
|
@@ -3,15 +3,21 @@ using Astralis;
|
|
|
namespace UsmWeb {
|
|
|
|
|
|
/**
|
|
|
- * `GET /repo/{name}/{file}.usmc` — streams a package archive from that
|
|
|
- * repository's `public/` directory with an exact content-length, exactly
|
|
|
- * what a USM client fetching through this app expects (the bytes match
|
|
|
- * the listing's sha512).
|
|
|
+ * `GET /repo/{name}/{file}` — streams a package archive (`.usmc`) or a
|
|
|
+ * pre-built artifact (`.dcba`) from that repository's `public/`
|
|
|
+ * directory with an exact content-length, exactly what a USM client
|
|
|
+ * fetching through this app expects (the bytes match the listings'
|
|
|
+ * checksums).
|
|
|
*
|
|
|
- * The route pattern matches any third segment, so it must be registered
|
|
|
- * after the exact `/repo/{name}/PACKAGES.usml` and
|
|
|
- * `/repo/{name}/repo.usmr` routes; requests that do not name a `.usmc`
|
|
|
+ * The suffix also selects the repository kind: `.usmc` is served only
|
|
|
+ * from USM source repositories and `.dcba` only from DCBA artifact
|
|
|
+ * repositories — asking the wrong kind answers 404, since the file
|
|
|
+ * has no meaning there. Requests that do not name a recognized file
|
|
|
* inside `public/` answer 404.
|
|
|
+ *
|
|
|
+ * The route pattern matches any third segment, so it must be registered
|
|
|
+ * after the exact `/repo/{name}/PACKAGES.usml`, `/repo/{name}/repo.usmr`,
|
|
|
+ * `/repo/{name}/ARTIFACTS.usml` and `/repo/{name}/repo.dcbar` routes.
|
|
|
*/
|
|
|
public class PackageDownloadEndpoint : Object, Endpoint {
|
|
|
|
|
|
@@ -23,7 +29,13 @@ namespace UsmWeb {
|
|
|
route_context.mapped_parameters.try_get("name", out name);
|
|
|
route_context.mapped_parameters.try_get("file", out file);
|
|
|
|
|
|
- if (!file.has_suffix(".usmc") || file.contains("/") || file.contains("..")) {
|
|
|
+ if (file.contains("/") || file.contains("..")) {
|
|
|
+ return new HttpStringResult("Not Found", StatusCode.NOT_FOUND);
|
|
|
+ }
|
|
|
+
|
|
|
+ bool is_usmc = file.has_suffix(".usmc");
|
|
|
+ bool is_dcba = file.has_suffix(".dcba");
|
|
|
+ if (!is_usmc && !is_dcba) {
|
|
|
return new HttpStringResult("Not Found", StatusCode.NOT_FOUND);
|
|
|
}
|
|
|
|
|
|
@@ -38,10 +50,25 @@ namespace UsmWeb {
|
|
|
return new HttpStringResult(@"No repository named \"$name\"", StatusCode.NOT_FOUND);
|
|
|
}
|
|
|
|
|
|
- var path = ((!)entry).package_location(file);
|
|
|
+ var kind = ((!)entry).kind;
|
|
|
+ if (is_usmc && kind != RepositoryKind.USM) {
|
|
|
+ return new HttpStringResult(
|
|
|
+ @"No package \"$file\" in \"$name\": that repository is a DCBA artifact repository and carries no .usmc packages",
|
|
|
+ StatusCode.NOT_FOUND);
|
|
|
+ }
|
|
|
+ if (is_dcba && kind != RepositoryKind.DCBA) {
|
|
|
+ return new HttpStringResult(
|
|
|
+ @"No artifact \"$file\" in \"$name\": that repository is a USM source repository and carries no .dcba artifacts",
|
|
|
+ StatusCode.NOT_FOUND);
|
|
|
+ }
|
|
|
+
|
|
|
+ var path = is_dcba
|
|
|
+ ? ((!)entry).artifact_location(file)
|
|
|
+ : ((!)entry).package_location(file);
|
|
|
var handle = File.new_for_path(path);
|
|
|
if (!handle.query_exists()) {
|
|
|
- return new HttpStringResult("No such package", StatusCode.NOT_FOUND);
|
|
|
+ return new HttpStringResult(is_dcba ? "No such artifact" : "No such package",
|
|
|
+ StatusCode.NOT_FOUND);
|
|
|
}
|
|
|
|
|
|
var info = yield handle.query_info_async(
|