diff --git a/src/http-api.ts b/src/http-api.ts index 6fcc20f..4f9c3b3 100644 --- a/src/http-api.ts +++ b/src/http-api.ts @@ -129,10 +129,17 @@ export class HttpApi { // Returns the data for the most recently published record under a given protocol path collection, if one is present this.#api.get('/:did/read/protocols/:protocol/*', async (req, res) => { + if (!req.params[0]) { + return res.status(400).send('protocol path is required'); + } + + const protocolPath = req.params[0].replace(leadTailSlashRegex, ''); + const protocol = req.params.protocol; + const query = await RecordsQuery.create({ filter: { - protocol: req.params.protocol, - protocolPath: (req.params[0] || '').replace(leadTailSlashRegex) + protocol, + protocolPath, }, pagination: { limit: 1 }, dateSort: DateSort.PublishedDescending diff --git a/tests/http-api.spec.ts b/tests/http-api.spec.ts index 003a152..5d59638 100644 --- a/tests/http-api.spec.ts +++ b/tests/http-api.spec.ts @@ -887,6 +887,19 @@ describe('http api', function () { expect(record.recordId).to.equal(recordsWrite.message.recordId); }); + it('removes the trailing slash from the protocol path', async function () { + const recordsQueryCreateSpy = sinon.spy(RecordsQuery, 'create'); + + const urlEncodedProtocol = encodeURIComponent('http://example.com/protocol'); + const protocolUrl = `http://localhost:3000/${alice.did}/read/protocols/${urlEncodedProtocol}/foo/`; // trailing slash + const recordReadResponse = await fetch(protocolUrl); + expect(recordReadResponse.status).to.equal(404); + + expect(recordsQueryCreateSpy.calledOnce).to.be.true; + const recordsQueryFilter = recordsQueryCreateSpy.getCall(0).args[0].filter; + expect(recordsQueryFilter.protocolPath).to.equal('foo'); + }); + it('returns a 404 if record for a given protocol and protocolPath is not published', async function () { // Create and publish a protocol const protocolConfigure = await ProtocolsConfigure.create({ @@ -956,6 +969,15 @@ describe('http api', function () { const recordReadResponse = await fetch(protocolUrl); expect(recordReadResponse.status).to.equal(404); }); + + it('returns a 400 if protocol path is not provided', async function () { + // Fetch a protocol record without providing a protocol path + const urlEncodedProtocol = encodeURIComponent('http://example.com/protocol'); + const protocolUrl = `http://localhost:3000/${alice.did}/read/protocols/${urlEncodedProtocol}/`; // missing protocol path + const recordReadResponse = await fetch(protocolUrl); + expect(recordReadResponse.status).to.equal(400); + expect(await recordReadResponse.text()).to.equal('protocol path is required'); + }); }); describe('/:did/query', function () {