diff --git a/README.md b/README.md index a1293ab..d6d49fb 100644 --- a/README.md +++ b/README.md @@ -424,10 +424,13 @@ Note that the `packageDirLevel` query param indicates the number of directories Body: +_integrity field is optional_ + ```json { "service": "my-service", - "url": "http://example.com/path/to/my-service.js" + "url": "http://example.com/path/to/my-service.js", + "integrity": "sha256-example" } ``` @@ -438,6 +441,9 @@ Response: "imports": { "my-service": "http://example.com/path/to/my-service.js", "my-service/": "http://example.com/path/to/" + }, + "integrity": { + "http://example.com/path/to/my-service.js": "sha256-example" } } ``` diff --git a/src/modify.js b/src/modify.js index 006df00..2d8ee9d 100644 --- a/src/modify.js +++ b/src/modify.js @@ -132,7 +132,8 @@ exports.modifyService = function ( serviceName, url, remove, - packageDirLevel = 1 + packageDirLevel = 1, + integrity ) { return modifyLock(env, (json) => { const map = getMapFromManifest(json); @@ -158,6 +159,11 @@ exports.modifyService = function ( ).pathname; map[serviceName + "/"] = address; } + + if (integrity) { + json.integrity = json.integrity ?? {}; + json.integrity[url] = integrity; + } } const alphabetical = !!getConfig().alphabetical; if (alphabetical) { diff --git a/src/web-server.js b/src/web-server.js index a2c2269..da9e220 100644 --- a/src/web-server.js +++ b/src/web-server.js @@ -256,7 +256,7 @@ function healthEndpoint(req, res) { app.patch("/services", function (req, res) { req.body = JSON.parse(req.body); - let service, url; + let service, url, integrity; let env = getEnv(req); if (req.body != undefined && req.body.hasOwnProperty("service")) { service = req.body.service; @@ -273,6 +273,17 @@ app.patch("/services", function (req, res) { } else { return res.status(400).send("url key is missing"); } + if (req.body?.hasOwnProperty("integrity")) { + if ( + typeof req.body.integrity !== "string" || + req.body.integrity.trim().length === 0 + ) { + return res + .status(400) + .send(`Invalid integrity - must be a non-empty string`); + } + integrity = req.body.integrity; + } let packageDirLevel = req.query.packageDirLevel && req.query.packageDirLevel !== "" @@ -296,7 +307,7 @@ app.patch("/services", function (req, res) { verifyValidUrl(req, url) .then(() => { modify - .modifyService(env, service, url, false, packageDirLevel) + .modifyService(env, service, url, false, packageDirLevel, integrity) .then((json) => { res.send(json); }) diff --git a/test/import-map.test.js b/test/import-map.test.js index 36faef1..b43b467 100644 --- a/test/import-map.test.js +++ b/test/import-map.test.js @@ -104,6 +104,26 @@ describe(`/import-map.json`, () => { }); }); + it(`patches services with integrity`, async () => { + const integrity = "sha256-test"; + + const response = await request(app) + .patch("/services") + .query({ + skip_url_check: true, + }) + .set("accept", "json") + .send({ + service: "a", + url: "/a-1-updated.mjs", + integrity, + }) + .expect(200) + .expect("Content-Type", /json/); + + expect(response.body.integrity["/a-1-updated.mjs"]).toBe(integrity); + }); + it(`does add trailing slash package`, async () => { const response = await request(app) .patch("/services")