diff --git a/src/server.test.ts b/src/server.test.ts index 5d1dd3e..cb4ad1a 100644 --- a/src/server.test.ts +++ b/src/server.test.ts @@ -40,11 +40,11 @@ test('Reads and writes from the file system', async () => { } // Store #1: Edge access - const server1Ops: string[] = [] + const server1Ops: { type: string; url: string }[] = [] const directory1 = await tmp.dir() const server1 = new BlobsServer({ directory: directory1.path, - onRequest: ({ type }) => server1Ops.push(type), + onRequest: ({ type, url }) => server1Ops.push({ type, url }), token, }) @@ -113,7 +113,13 @@ test('Reads and writes from the file system', async () => { expect(list3.directories).toEqual([]) } - expect(server1Ops).toEqual([ + const urls = server1Ops.map(({ url }) => url) + + expect(urls.every((url) => url.startsWith(`/${siteID}/`))).toBeTruthy() + + const operations = server1Ops.map(({ type }) => type) + + expect(operations).toEqual([ 'list', 'set', 'get', diff --git a/src/server.ts b/src/server.ts index 91a479f..87e9ec6 100644 --- a/src/server.ts +++ b/src/server.ts @@ -25,6 +25,8 @@ export enum Operation { SET = 'set', } +export type OnRequestCallback = (parameters: { type: Operation; url: string }) => void + // TODO: Replace with `promises` import of `node:stream` once we can drop // support for Node 14. const pipeline = promisify(stream.pipeline) @@ -49,7 +51,7 @@ interface BlobsServerOptions { /** * Callback function to be called on every request. */ - onRequest?: (parameters: { type: Operation }) => void + onRequest?: OnRequestCallback /** * Port to run the server on. Defaults to a random port. @@ -68,7 +70,7 @@ export class BlobsServer { private debug: boolean private directory: string private logger: Logger - private onRequest: (parameters: { type: Operation }) => void + private onRequest?: OnRequestCallback private port: number private server?: http.Server private token?: string @@ -79,11 +81,7 @@ export class BlobsServer { this.debug = debug === true this.directory = directory this.logger = logger ?? console.log - this.onRequest = - onRequest ?? - (() => { - // no-op - }) + this.onRequest = onRequest this.port = port || 0 this.token = token this.tokenHash = createHmac('sha256', Math.random.toString()) @@ -91,6 +89,16 @@ export class BlobsServer { .digest('hex') } + private dispatchOnRequestEvent(type: Operation, url: string | URL) { + if (!this.onRequest) { + return + } + + const urlPath = url instanceof URL ? url.pathname + url.search : url + + this.onRequest({ type, url: urlPath }) + } + logDebug(...message: unknown[]) { if (!this.debug) { return @@ -159,7 +167,7 @@ export class BlobsServer { return this.listBlobs({ dataPath, metadataPath, rootPath, req, res, url }) } - this.onRequest({ type: Operation.GET }) + this.dispatchOnRequestEvent(Operation.GET, url) const headers: Record = {} @@ -230,8 +238,6 @@ export class BlobsServer { res: http.ServerResponse url: URL }) { - this.onRequest({ type: Operation.LIST }) - const { dataPath, rootPath, req, res, url } = options const directories = url.searchParams.get('directories') === 'true' const prefix = url.searchParams.get('prefix') ?? '' @@ -240,6 +246,8 @@ export class BlobsServer { directories: [], } + this.dispatchOnRequestEvent(Operation.LIST, url) + try { await BlobsServer.walk({ directories, path: dataPath, prefix, rootPath, result }) } catch (error) { @@ -356,7 +364,7 @@ export class BlobsServer { switch (req.method?.toLowerCase()) { case HTTPMethod.DELETE: { - this.onRequest({ type: Operation.DELETE }) + this.dispatchOnRequestEvent(Operation.DELETE, req.url) return this.delete(req, res) } @@ -366,13 +374,13 @@ export class BlobsServer { } case HTTPMethod.PUT: { - this.onRequest({ type: Operation.SET }) + this.dispatchOnRequestEvent(Operation.SET, req.url) return this.put(req, res) } case HTTPMethod.HEAD: { - this.onRequest({ type: Operation.GET_METADATA }) + this.dispatchOnRequestEvent(Operation.GET_METADATA, req.url) return this.head(req, res) }