diff --git a/packages/cli/test/helpers/http-server.js b/packages/cli/test/helpers/http-server.js index 375d2e834..8de014092 100644 --- a/packages/cli/test/helpers/http-server.js +++ b/packages/cli/test/helpers/http-server.js @@ -23,29 +23,38 @@ export async function createServer(router) { * @param {http.ServerResponse} response */ const listener = async (request, response) => { - const chunks = [] - for await (const chunk of request) { - chunks.push(chunk) - } + try { + const chunks = [] + for await (const chunk of request) { + chunks.push(chunk) + } + + const handler = router[request.url ?? '/'] + if (!handler) { + response.writeHead(404) + response.end() + return undefined + } + + const { headers, body } = await handler({ + headers: /** @type {Readonly>} */ ( + request.headers + ), + body: Buffer.concat(chunks), + }) - const handler = router[request.url ?? '/'] - if (!handler) { - response.writeHead(404) + response.writeHead(200, headers) + response.write(body) + response.end() + return undefined + } catch (error) { + process.stderr.write(`Error handling request: ${error}\n`) + if (!response.headersSent) { + response.writeHead(500) + } response.end() return undefined } - - const { headers, body } = await handler({ - headers: /** @type {Readonly>} */ ( - request.headers - ), - body: Buffer.concat(chunks), - }) - - response.writeHead(200, headers) - response.write(body) - response.end() - return undefined } const server = http.createServer(listener).listen() diff --git a/packages/cli/test/helpers/receipt-http-server.js b/packages/cli/test/helpers/receipt-http-server.js index e04f0efec..c8e8b765d 100644 --- a/packages/cli/test/helpers/receipt-http-server.js +++ b/packages/cli/test/helpers/receipt-http-server.js @@ -24,11 +24,20 @@ export async function createReceiptsServer() { * @param {http.ServerResponse} response */ const listener = async (request, response) => { - const taskCid = request.url?.split('/')[1] ?? '' - const body = await generateReceipt(taskCid) - response.writeHead(200) - response.end(body) - return undefined + try { + const taskCid = request.url?.split('/')[1] ?? '' + const body = await generateReceipt(taskCid) + response.writeHead(200) + response.end(body) + return undefined + } catch (error) { + process.stderr.write(`Error handling request: ${error}\n`) + if (!response.headersSent) { + response.writeHead(500) + } + response.end() + return undefined + } } const server = http.createServer(listener).listen() @@ -64,7 +73,6 @@ const generateReceipt = async (taskCid) => { fx: { fork: [locationClaim], }, - /** @ts-expect-error not a UCAN Link */ ran: parseLink(taskCid), result: { ok: { diff --git a/packages/encrypt-upload-client/test/mocks/key-manager.js b/packages/encrypt-upload-client/test/mocks/key-manager.js index 2a3faf2dc..c416e74e6 100644 --- a/packages/encrypt-upload-client/test/mocks/key-manager.js +++ b/packages/encrypt-upload-client/test/mocks/key-manager.js @@ -109,49 +109,56 @@ export function createMockKeyManagerServer( }) const httpServer = createServer(async (req, res) => { - res.setHeader('Access-Control-Allow-Origin', '*') - res.setHeader('Access-Control-Allow-Methods', '*') - res.setHeader('Access-Control-Allow-Headers', '*') - if (req.method === 'OPTIONS') return res.end() - - if (req.method === 'POST') { - const bodyBuffer = Buffer.concat(await collect(req)) - - const reqHeaders = /** @type {Record} */ ( - Object.fromEntries(Object.entries(req.headers)) - ) - - const { headers, body, status } = await ucantoServer.request({ - body: new Uint8Array( - bodyBuffer.buffer, - bodyBuffer.byteOffset, - bodyBuffer.byteLength - ), - headers: reqHeaders, - }) + try { + res.setHeader('Access-Control-Allow-Origin', '*') + res.setHeader('Access-Control-Allow-Methods', '*') + res.setHeader('Access-Control-Allow-Headers', '*') + if (req.method === 'OPTIONS') return res.end() + + if (req.method === 'POST') { + const bodyBuffer = Buffer.concat(await collect(req)) + + const reqHeaders = /** @type {Record} */ ( + Object.fromEntries(Object.entries(req.headers)) + ) + + const { headers, body, status } = await ucantoServer.request({ + body: new Uint8Array( + bodyBuffer.buffer, + bodyBuffer.byteOffset, + bodyBuffer.byteLength + ), + headers: reqHeaders, + }) - for (const [key, value] of Object.entries(headers)) { - res.setHeader(key, value) + for (const [key, value] of Object.entries(headers)) { + res.setHeader(key, value) + } + res.writeHead(status ?? 200) + res.end(body) + } else { + res.end() + } + } catch (error) { + process.stderr.write(`Error handling request: ${error}\n`) + if (!res.headersSent) { + res.writeHead(500) } - res.writeHead(status ?? 200) - res.end(body) - } else { res.end() } }) return new Promise((resolve, reject) => { - httpServer.listen(port, (/** @type {Error | undefined} */ err) => { - if (err) { - reject(err) - } else { - const protocol = useHttps ? 'https' : 'http' - resolve({ - server: httpServer, - url: `${protocol}://localhost:${port}`, - close: () => new Promise((resolve) => httpServer.close(resolve)), - }) - } + httpServer.on('error', (err) => { + reject(err) + }) + httpServer.listen(port, () => { + const protocol = useHttps ? 'https' : 'http' + resolve({ + server: httpServer, + url: `${protocol}://localhost:${port}`, + close: () => new Promise((resolve) => httpServer.close(resolve)), + }) }) }) } diff --git a/packages/upload-api/src/test/external-service/content-claims.js b/packages/upload-api/src/test/external-service/content-claims.js index 590529b3e..e447c8af0 100644 --- a/packages/upload-api/src/test/external-service/content-claims.js +++ b/packages/upload-api/src/test/external-service/content-claims.js @@ -79,20 +79,28 @@ export const activate = async ({ http } = {}) => { } const httpServer = http.createServer(async (req, res) => { - const chunks = [] - for await (const chunk of req) { - chunks.push(chunk) - } + try { + const chunks = [] + for await (const chunk of req) { + chunks.push(chunk) + } - const { status, headers, body } = await server.request({ - // @ts-expect-error - headers: req.headers, - body: new Uint8Array(await new Blob(chunks).arrayBuffer()), - }) + const { status, headers, body } = await server.request({ + // @ts-expect-error + headers: req.headers, + body: new Uint8Array(await new Blob(chunks).arrayBuffer()), + }) - res.writeHead(status ?? 200, headers) - res.write(body) - res.end() + res.writeHead(status ?? 200, headers) + res.write(body) + res.end() + } catch (error) { + process.stderr.write(`Error handling request: ${error}\n`) + if (!res.headersSent) { + res.writeHead(500) + } + res.end() + } }) await new Promise((resolve) => httpServer.listen(resolve)) // @ts-expect-error diff --git a/packages/upload-api/src/test/external-service/indexing-service.js b/packages/upload-api/src/test/external-service/indexing-service.js index 988961136..29b80d9ae 100644 --- a/packages/upload-api/src/test/external-service/indexing-service.js +++ b/packages/upload-api/src/test/external-service/indexing-service.js @@ -109,20 +109,28 @@ export const activate = async ({ http } = {}) => { } const httpServer = http.createServer(async (req, res) => { - const chunks = [] - for await (const chunk of req) { - chunks.push(chunk) - } + try { + const chunks = [] + for await (const chunk of req) { + chunks.push(chunk) + } - const { status, headers, body } = await server.request({ - // @ts-expect-error - headers: req.headers, - body: new Uint8Array(await new Blob(chunks).arrayBuffer()), - }) + const { status, headers, body } = await server.request({ + // @ts-expect-error + headers: req.headers, + body: new Uint8Array(await new Blob(chunks).arrayBuffer()), + }) - res.writeHead(status ?? 200, headers) - res.write(body) - res.end() + res.writeHead(status ?? 200, headers) + res.write(body) + res.end() + } catch (error) { + process.stderr.write(`Error handling request: ${error}\n`) + if (!res.headersSent) { + res.writeHead(500) + } + res.end() + } }) await new Promise((resolve) => httpServer.listen(resolve)) // @ts-expect-error diff --git a/packages/upload-api/src/test/storage/blobs-storage.js b/packages/upload-api/src/test/storage/blobs-storage.js index 646df68da..58f253695 100644 --- a/packages/upload-api/src/test/storage/blobs-storage.js +++ b/packages/upload-api/src/test/storage/blobs-storage.js @@ -25,40 +25,50 @@ export class BlobsStorage { const content = new Map() if (http) { const server = http.createServer(async (request, response) => { - const { pathname } = new URL(request.url || '/', url) - if (request.method === 'PUT') { - const buffer = new Uint8Array( - parseInt(request.headers['content-length'] || '0') - ) - let offset = 0 - for await (const chunk of request) { - buffer.set(chunk, offset) - offset += chunk.length - } - const hash = await sha256.digest(buffer) - const checksum = base64pad.baseEncode(hash.digest) - - if (checksum !== request.headers['x-amz-checksum-sha256']) { - response.writeHead(400, `checksum mismatch`) + try { + const { pathname } = new URL(request.url || '/', url) + if (request.method === 'PUT') { + const buffer = new Uint8Array( + parseInt(request.headers['content-length'] || '0') + ) + let offset = 0 + for await (const chunk of request) { + buffer.set(chunk, offset) + offset += chunk.length + } + const hash = await sha256.digest(buffer) + const checksum = base64pad.baseEncode(hash.digest) + + if (checksum !== request.headers['x-amz-checksum-sha256']) { + response.writeHead(400, `checksum mismatch`) + } else { + content.set(pathname, buffer) + response.writeHead(200) + } + } else if (request.method === 'GET') { + const data = content.get(pathname) + if (data) { + response.writeHead(200) + response.write(data) + } else { + response.writeHead(404) + } } else { - content.set(pathname, buffer) - response.writeHead(200) + response.writeHead(405) } - } else if (request.method === 'GET') { - const data = content.get(pathname) - if (data) { - response.writeHead(200) - response.write(data) - } else { - response.writeHead(404) + + response.end() + // otherwise it keep connection lingering + response.destroy() + } catch (error) { + process.stderr.write(`Error handling request: ${error}\n`) + if (!response.headersSent) { + response.writeHead(500) } - } else { - response.writeHead(405) + response.end() + // otherwise it keep connection lingering + response.destroy() } - - response.end() - // otherwise it keep connection lingering - response.destroy() }) await new Promise((resolve) => server.listen(resolve)) diff --git a/packages/upload-api/src/test/storage/car-store-bucket.js b/packages/upload-api/src/test/storage/car-store-bucket.js index 327992780..d56f0c94e 100644 --- a/packages/upload-api/src/test/storage/car-store-bucket.js +++ b/packages/upload-api/src/test/storage/car-store-bucket.js @@ -15,34 +15,44 @@ export class CarStoreBucket { const content = new Map() if (http) { const server = http.createServer(async (request, response) => { - if (request.method === 'PUT') { - const buffer = new Uint8Array( - parseInt(request.headers['content-length'] || '0') - ) - let offset = 0 + try { + if (request.method === 'PUT') { + const buffer = new Uint8Array( + parseInt(request.headers['content-length'] || '0') + ) + let offset = 0 - for await (const chunk of request) { - buffer.set(chunk, offset) - offset += chunk.length - } + for await (const chunk of request) { + buffer.set(chunk, offset) + offset += chunk.length + } - const hash = await sha256.digest(buffer) - const checksum = base64pad.baseEncode(hash.digest) + const hash = await sha256.digest(buffer) + const checksum = base64pad.baseEncode(hash.digest) - if (checksum !== request.headers['x-amz-checksum-sha256']) { - response.writeHead(400, `checksum mismatch`) + if (checksum !== request.headers['x-amz-checksum-sha256']) { + response.writeHead(400, `checksum mismatch`) + } else { + const { pathname } = new URL(request.url || '/', url) + content.set(pathname, buffer) + response.writeHead(200) + } } else { - const { pathname } = new URL(request.url || '/', url) - content.set(pathname, buffer) - response.writeHead(200) + response.writeHead(405) } - } else { - response.writeHead(405) - } - response.end() - // otherwise it keep connection lingering - response.destroy() + response.end() + // otherwise it keep connection lingering + response.destroy() + } catch (error) { + process.stderr.write(`Error handling request: ${error}\n`) + if (!response.headersSent) { + response.writeHead(500) + } + response.end() + // otherwise it keep connection lingering + response.destroy() + } }) await new Promise((resolve) => server.listen(resolve)) diff --git a/packages/upload-client/test/helpers/bucket-server.js b/packages/upload-client/test/helpers/bucket-server.js index 9db6842fd..581279f5a 100644 --- a/packages/upload-client/test/helpers/bucket-server.js +++ b/packages/upload-client/test/helpers/bucket-server.js @@ -12,4 +12,15 @@ const server = createServer((req, res) => { res.end() }) -server.listen(port, () => console.log(`Listening on :${port}`)) +server + .listen(port, () => { + process.stdout.write(`Listening on :${port}\n`) + }) + .on('error', (err) => { + process.stderr.write( + `Failed to start server on port ${port}: ${err.message}\n` + ) + process.exit(1) + }) + +process.on('SIGTERM', () => process.exit(0)) diff --git a/packages/upload-client/test/helpers/receipts-server.js b/packages/upload-client/test/helpers/receipts-server.js index 424f8b486..18296c450 100644 --- a/packages/upload-client/test/helpers/receipts-server.js +++ b/packages/upload-client/test/helpers/receipts-server.js @@ -18,27 +18,45 @@ const encodeReceipt = async (taskCid) => { } const server = createServer(async (req, res) => { - res.setHeader('Access-Control-Allow-Origin', '*') - res.setHeader('Access-Control-Allow-Methods', '*') - res.setHeader('Access-Control-Allow-Headers', '*') + try { + res.setHeader('Access-Control-Allow-Origin', '*') + res.setHeader('Access-Control-Allow-Methods', '*') + res.setHeader('Access-Control-Allow-Headers', '*') - const taskCid = req.url?.split('/')[1] - if (!taskCid) { - res.writeHead(204) + const taskCid = req.url?.split('/')[1] + if (!taskCid) { + res.writeHead(204) + res.end() + } else if (taskCid === 'unavailable') { + res.writeHead(404) + res.end() + } else if (taskCid === 'failed') { + const body = await encodeReceipt((await randomCAR(128)).cid.toString()) + res.writeHead(200) + res.end(body) + } else { + const body = await encodeReceipt(taskCid) + res.writeHead(200) + res.end(body) + } + } catch (error) { + process.stderr.write(`Error handling request: ${error}\n`) + if (!res.headersSent) { + res.writeHead(500) + } res.end() - } else if (taskCid === 'unavailable') { - res.writeHead(404) - res.end() - } else if (taskCid === 'failed') { - const body = await encodeReceipt((await randomCAR(128)).cid.toString()) - res.writeHead(200) - res.end(body) - } else { - const body = await encodeReceipt(taskCid) - res.writeHead(200) - res.end(body) } }) -server.listen(port, () => console.log(`Listening on :${port}`)) +server + .listen(port, () => { + process.stdout.write(`Listening on :${port}\n`) + }) + .on('error', (err) => { + process.stderr.write( + `Failed to start server on port ${port}: ${err.message}\n` + ) + process.exit(1) + }) + process.on('SIGTERM', () => process.exit(0)) diff --git a/packages/w3up-client/test/helpers/bucket-server.js b/packages/w3up-client/test/helpers/bucket-server.js index 671a311f6..f5fbad69e 100644 --- a/packages/w3up-client/test/helpers/bucket-server.js +++ b/packages/w3up-client/test/helpers/bucket-server.js @@ -7,31 +7,39 @@ const status = process.env.STATUS ? parseInt(process.env.STATUS) : 200 const data = new Map() const server = createServer(async (req, res) => { - res.setHeader('Access-Control-Allow-Origin', '*') - res.setHeader('Access-Control-Allow-Methods', '*') - res.setHeader('Access-Control-Allow-Headers', '*') - if (req.method === 'OPTIONS') return res.end() - if (req.method === 'POST' && req.url === '/reset') { - data.clear() - return res.end() - } + try { + res.setHeader('Access-Control-Allow-Origin', '*') + res.setHeader('Access-Control-Allow-Methods', '*') + res.setHeader('Access-Control-Allow-Headers', '*') + if (req.method === 'OPTIONS') return res.end() + if (req.method === 'POST' && req.url === '/reset') { + data.clear() + return res.end() + } - res.statusCode = status - if (status === 200) { - const key = new URL(req.url ?? '', 'http://localhost').pathname - if (req.method === 'GET') { - const body = data.get(key) - if (!body) { - res.statusCode = 404 - } else { - res.write(body) + res.statusCode = status + if (status === 200) { + const key = new URL(req.url ?? '', 'http://localhost').pathname + if (req.method === 'GET') { + const body = data.get(key) + if (!body) { + res.statusCode = 404 + } else { + res.write(body) + } + } else if (req.method === 'PUT') { + const body = Buffer.concat(await collect(req)) + data.set(key, body) } - } else if (req.method === 'PUT') { - const body = Buffer.concat(await collect(req)) - data.set(key, body) } + res.end() + } catch (error) { + process.stderr.write(`Error handling request: ${error}\n`) + if (!res.headersSent) { + res.writeHead(500) + } + res.end() } - res.end() }) /** @param {import('node:stream').Readable} stream */ @@ -46,7 +54,15 @@ const collect = (stream) => { ) } -// eslint-disable-next-line no-console -server.listen(port, () => console.log(`Listening on :${port}`)) +server + .listen(port, () => { + process.stdout.write(`Listening on :${port}\n`) + }) + .on('error', (err) => { + process.stderr.write( + `Failed to start server on port ${port}: ${err.message}\n` + ) + process.exit(1) + }) process.on('SIGTERM', () => process.exit(0)) diff --git a/packages/w3up-client/test/helpers/gateway-server.js b/packages/w3up-client/test/helpers/gateway-server.js index 277e840fa..b55b1bcc3 100644 --- a/packages/w3up-client/test/helpers/gateway-server.js +++ b/packages/w3up-client/test/helpers/gateway-server.js @@ -8,37 +8,46 @@ import { gateway } from '@storacha/upload-api/test/utils' const port = 5001 const server = createServer(async (req, res) => { - res.setHeader('Access-Control-Allow-Origin', '*') - res.setHeader('Access-Control-Allow-Methods', '*') - res.setHeader('Access-Control-Allow-Headers', '*') - if (req.method === 'OPTIONS') return res.end() + try { + res.setHeader('Access-Control-Allow-Origin', '*') + res.setHeader('Access-Control-Allow-Methods', '*') + res.setHeader('Access-Control-Allow-Headers', '*') + if (req.method === 'OPTIONS') return res.end() - if (req.method === 'POST') { - const service = getContentServeMockService() - const server = createUcantoServer(gateway, service) + if (req.method === 'POST') { + const service = getContentServeMockService() + const server = createUcantoServer(gateway, service) - const bodyBuffer = Buffer.concat(await collect(req)) + const bodyBuffer = Buffer.concat(await collect(req)) - const reqHeaders = /** @type {Record} */ ( - Object.fromEntries(Object.entries(req.headers)) - ) + const reqHeaders = /** @type {Record} */ ( + Object.fromEntries(Object.entries(req.headers)) + ) - const { headers, body, status } = await server.request({ - body: new Uint8Array( - bodyBuffer.buffer, - bodyBuffer.byteOffset, - bodyBuffer.byteLength - ), - headers: reqHeaders, - }) + const { headers, body, status } = await server.request({ + body: new Uint8Array( + bodyBuffer.buffer, + bodyBuffer.byteOffset, + bodyBuffer.byteLength + ), + headers: reqHeaders, + }) - for (const [key, value] of Object.entries(headers)) { - res.setHeader(key, value) + for (const [key, value] of Object.entries(headers)) { + res.setHeader(key, value) + } + res.writeHead(status ?? 200) + res.end(body) + } else { + res.end() } - res.writeHead(status ?? 200) - res.end(body) + } catch (error) { + process.stderr.write(`Error handling request: ${error}\n`) + if (!res.headersSent) { + res.writeHead(500) + } + res.end() } - res.end() }) /** @param {import('node:stream').Readable} stream */ @@ -53,9 +62,15 @@ const collect = (stream) => { ) } -// eslint-disable-next-line no-console -server.listen(port, () => - console.log(`[Mock] Gateway Server Listening on :${port}`) -) +server + .listen(port, () => { + process.stdout.write(`[Mock] Gateway Server Listening on :${port}\n`) + }) + .on('error', (err) => { + process.stderr.write( + `Failed to start server on port ${port}: ${err.message}\n` + ) + process.exit(1) + }) process.on('SIGTERM', () => process.exit(0)) diff --git a/packages/w3up-client/test/helpers/receipts-server.js b/packages/w3up-client/test/helpers/receipts-server.js index c502c0564..5f33dd9f0 100644 --- a/packages/w3up-client/test/helpers/receipts-server.js +++ b/packages/w3up-client/test/helpers/receipts-server.js @@ -19,65 +19,83 @@ const fixtureContent = fs.readFileSync( ) const server = createServer(async (req, res) => { - res.setHeader('Access-Control-Allow-Origin', '*') - res.setHeader('Access-Control-Allow-Methods', '*') - res.setHeader('Access-Control-Allow-Headers', '*') + try { + res.setHeader('Access-Control-Allow-Origin', '*') + res.setHeader('Access-Control-Allow-Methods', '*') + res.setHeader('Access-Control-Allow-Headers', '*') - const parts = new URL(req.url ?? '', 'http://localhost').pathname.split('/') - let task, content + const parts = new URL(req.url ?? '', 'http://localhost').pathname.split('/') + let task, content - // If request URL is structure like: `/content/:digest/task/:cid` - // ...then we can issue a location claim for the passed digest. - if (parts[1] === 'content') { - task = parseLink(parts[4]) - content = { digest: Digest.decode(base58btc.decode(parts[2])).bytes } - } else { - task = parseLink(parts[1]) - content = (await randomCAR(128)).cid - } + // If request URL is structure like: `/content/:digest/task/:cid` + // ...then we can issue a location claim for the passed digest. + if (parts[1] === 'content') { + task = parseLink(parts[4]) + content = { digest: Digest.decode(base58btc.decode(parts[2])).bytes } + } else { + task = parseLink(parts[1]) + content = (await randomCAR(128)).cid + } - if ( - task.toString() === - 'bafyreibo6nqtvp67daj7dkmeb5c2n6bg5bunxdmxq3lghtp3pmjtzpzfma' - ) { - res.writeHead(200, { - 'Content-disposition': 'attachment; filename=' + fixtureName, - }) - return res.end(fixtureContent) - } + if ( + task.toString() === + 'bafyreibo6nqtvp67daj7dkmeb5c2n6bg5bunxdmxq3lghtp3pmjtzpzfma' + ) { + res.writeHead(200, { + 'Content-disposition': 'attachment; filename=' + fixtureName, + }) + return res.end(fixtureContent) + } - const issuer = await Signer.generate() - const locationClaim = await Assert.location.delegate({ - issuer, - audience: issuer, - with: issuer.toDIDKey(), - nb: { - content, - location: ['http://localhost'], - }, - expiration: Infinity, - }) + const issuer = await Signer.generate() + const locationClaim = await Assert.location.delegate({ + issuer, + audience: issuer, + with: issuer.toDIDKey(), + nb: { + content, + location: ['http://localhost'], + }, + expiration: Infinity, + }) - const receipt = await Receipt.issue({ - issuer, - fx: { - fork: [locationClaim], - }, - ran: task, - result: { - ok: { - site: locationClaim.link(), + const receipt = await Receipt.issue({ + issuer, + fx: { + fork: [locationClaim], }, - }, - }) + ran: task, + result: { + ok: { + site: locationClaim.link(), + }, + }, + }) - const message = await Message.build({ - receipts: [receipt], - }) - const request = CAR.request.encode(message) - res.writeHead(200) - res.end(request.body) + const message = await Message.build({ + receipts: [receipt], + }) + const request = CAR.request.encode(message) + res.writeHead(200) + res.end(request.body) + } catch (error) { + process.stderr.write(`Error handling request: ${error}\n`) + if (!res.headersSent) { + res.writeHead(500) + } + res.end() + } }) -server.listen(port, () => console.log(`Listening on :${port}`)) +server + .listen(port, () => { + process.stdout.write(`Listening on :${port}\n`) + }) + .on('error', (err) => { + process.stderr.write( + `Failed to start server on port ${port}: ${err.message}\n` + ) + process.exit(1) + }) + process.on('SIGTERM', () => process.exit(0))