Created
November 2, 2023 23:30
-
-
Save tsibley/fcbe564e7d31dca730affeeff67aaf90 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit b8de8d5d3dbce28d12b5d946c2f6f1cbf7becfbb | |
Author: Thomas Sibley <tsibley@fredhutch.org> | |
Date: Mon Oct 30 13:46:58 2023 -0700 | |
wip! version extractor | |
XXX FIXME: how far to take @ as not a given? i.e. update canonicalizeDataset to make the caller add the version? | |
XXX FIXME: default to extracting a version? | |
XXX FIXME: move core version extractor into a function we pass? | |
XXX FIXME: use route matching instead to make versionExtractor like: req => req.params.versionDescriptor? | |
XXX FIXME: adjust setDatasetFromPrefix | |
diff --git a/src/app.js b/src/app.js | |
index 51a198ca..db337741 100644 | |
--- a/src/app.js | |
+++ b/src/app.js | |
@@ -213,7 +213,7 @@ const coreBuildRoutes = coreBuildPaths.map(path => [ | |
app.use([coreBuildRoutes, "/narratives/*"], setSource(req => new CoreSource())); // eslint-disable-line no-unused-vars | |
app.routeAsync(coreBuildRoutes) | |
- .all(setDataset(req => req.path, true), canonicalizeDataset(path => `/${path}`)) | |
+ .all(setDataset(req => req.path, req => req.path.match(/@(.*)$/)?.[1]), canonicalizeDataset(path => `/${path}`)) | |
.getAsync(getDataset) | |
.putAsync(putDataset) | |
.deleteAsync(deleteDataset) | |
diff --git a/src/endpoints/sources.js b/src/endpoints/sources.js | |
index 8b12a388..5d61543b 100644 | |
--- a/src/endpoints/sources.js | |
+++ b/src/endpoints/sources.js | |
@@ -33,12 +33,12 @@ const setSource = (sourceExtractor) => (req, res, next) => { | |
* stashes it in the request context. | |
* | |
* @param {pathExtractor} pathExtractor - Function to extract a dataset path from the request | |
- * @param {Boolean} extractVersion - (Attempt to) extract a version descriptor from the extracted path | |
+ * @param {versionExtractor} [versionExtractor] - Function to extract a version descriptor from the request | |
* @returns {expressMiddleware} | |
*/ | |
-const setDataset = (pathExtractor, extractVersion=false) => (req, res, next) => { | |
+const setDataset = (pathExtractor, versionExtractor = req => LATEST) => (req, res, next) => { | |
console.log("middleware::setDataset") | |
- req.context.dataset = req.context.source.dataset(...pathParts(pathExtractor(req), extractVersion)); | |
+ req.context.dataset = req.context.source.dataset(pathParts(pathExtractor(req)), versionExtractor(req)); | |
next(); | |
}; | |
@@ -202,11 +202,10 @@ const optionsNarrative = options.forAuthzObject(req => req.context.narrative); | |
* and stashes it in the request context. | |
* | |
* @param {pathExtractor} pathExtractor - Function to extract a narrative path from the request | |
- * @param {Boolean} extractVersion - (Attempt to) extract a version descriptor from the extracted path | |
* @returns {expressMiddleware} | |
*/ | |
-const setNarrative = (pathExtractor, extractVersion=false) => (req, res, next) => { | |
- req.context.narrative = req.context.source.narrative(...pathParts(pathExtractor(req), extractVersion)); | |
+const setNarrative = (pathExtractor) => (req, res, next) => { | |
+ req.context.narrative = req.context.source.narrative(pathParts(pathExtractor(req))); | |
next(); | |
}; | |
@@ -261,45 +260,27 @@ const putNarrative = contentTypesConsumed([ | |
/** | |
- * Split a dataset or narrative `path` into an array of parts and a version | |
- * descriptor. | |
+ * Split a dataset or narrative `path` into an array of parts. | |
* | |
* If `path` is a tangletree path (i.e. refers to two datasets), returns only | |
* the parts for the first dataset. | |
* | |
- * By default the returned version descriptor is LATEST. If `extractVersion` is | |
- * true, we attempt to extract a version descriptor from the provided path, | |
- * falling back to LATEST if one is not present. | |
+ * If `path` contains a version descriptor (i.e. @…), it is removed. | |
* | |
* @param {String} path | |
- * @param {Boolean} extractVersion | |
- * @returns {[String[], String]} | |
+ * @returns {String[]} | |
*/ | |
-function pathParts(path = "", extractVersion = false) { | |
- // Use only the first dataset in a tangletree (dual dataset) path. | |
- let normalizedPath = path.split(":")[0] | |
+function pathParts(path = "") { | |
+ const normalizedPath = path | |
+ .split(":")[0] // Use only the first dataset in a tangletree (dual dataset) path. | |
+ .replace(/@.*$/, "") // Ignore version descriptor. | |
+ .replace(/^\/+/, "") // Ignore leading slashes | |
+ .replace(/\/+$/, "") // …and trailing slashes. | |
+ ; | |
- /* A part of the path starting with "@" is the version descriptor - this | |
- will later be translated to the appropriate S3 version ID / GitHub SHA, | |
- but we use human readable descriptors in the URL path. */ | |
- let versionDescriptor = LATEST; // default; | |
- if (extractVersion) { | |
- const match = normalizedPath.match(/^(.+)@(.+)$/) | |
- if (match) { | |
- [normalizedPath, versionDescriptor] = match.slice(1,3); | |
- } | |
- } | |
+ if (!normalizedPath) return []; | |
- // Ignore leading & trailing slashes (after version descriptor removal) | |
- normalizedPath = normalizedPath | |
- .replace(/\/+$/, "") | |
- .replace(/^\/+/, ""); | |
- | |
- if (!normalizedPath) return [[], LATEST]; | |
- | |
- console.log(`function::pathParts(${path}, ${extractVersion}) -> `, normalizedPath.split("/"), versionDescriptor) | |
- | |
- return [normalizedPath.split("/"), versionDescriptor] | |
+ return normalizedPath.split("/"); | |
} | |
@@ -369,6 +350,12 @@ function receiveSubresource(subresourceExtractor) { | |
* @returns {String} Path for {@link Source#dataset} or {@link Source#narrative} | |
*/ | |
+/** | |
+ * @callback versionExtractor | |
+ * @param {express.request} req | |
+ * @returns {?String} Version descriptor for {@link Source#dataset} or {@link Source#narrative} | |
+ */ | |
+ | |
/* Confused about the duplication below? It's the documented way to handle | |
* overloaded (e.g. arity-dependent) function signatures.¹ Note that it relies | |
* on the "nestled" or "cuddled" end and start comment markers. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment