day-5.mjs

December 29, 2021 ยท View on GitHub

/////////////////////////////////////////////////////////////////////////////// // Day 5 - Are we done yet? // // #region problem // /////////////////////////////////////////////////////////////////////////////// // Make a middleware that saves a timestamp from req.expires so that when // // calling an async function keepGoing it resolves as long as Date.now() is // // less than the expires time. Otherwise it throws an Error. // ///////////////////////////////////////////////////////////////////////////////

/**

  • Save req.auth so that using read() from inside next() returns req.auth
  • be wary of multiple concurrent calls to save()
  • @param {import('http').IncomingMessage} req
  • @param {import('http').ServerResponse} res
  • @param {(err?: Error) => void} next
  • @returns {void} */ function save(req, res, next) { // ... }

/**

  • DO NOT ADD PARAMETERS
  • @returns {void} */ function keepGoing() { // ... }

/////////////////////////////////////////////////////////////////////////////// // #endregion problem // ///////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////// // Test - Leave code after this alone // // #region test // ///////////////////////////////////////////////////////////////////////////////

import {once} from 'node:events'; import timers from 'node:timers/promises';

import http from 'node:http';

const pending = []; const server = http.createServer((req, res) => { console.log('HTTP REQ', req.method, req.url) const expires = Date.now() + 100; req.expires = expires; save(req, res, async () => { let cont = new Promise((f, r) => { pending.push(() => f()); if (pending.length === 2) { process.exitCode = 0; for (const end of pending) { end(); } } }); await cont; try { // will fail for first request since second is started after // first expires await keepGoing(); if (req.url === '/1') { res.writeHead(500); res.end('/1 should be expired and throw an error'); } } catch (e) { if (req.url !== '/1') { res.writeHead(500); res.end('only /1 should be expired and throw an error'); throw e; } } res.end(); }); }).listen(0, '127.0.0.1'); process.exitCode = 1; server.unref();

await once(server, 'listening'); const url = http://127.0.0.1:${server.address().port}/; const req1 = http.get(url + '1').end(); await timers.setTimeout(150); const req2 = http.get(url + '2').end();

/////////////////////////////////////////////////////////////////////////////// // #endregion test // ///////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////// // Hints - Encoded in ROT13 encoded // // #region hints // /////////////////////////////////////////////////////////////////////////////// // // // Fvzcyr: lbh arrq fbzr qngn fgber gb genpx gur nflap pbagrkg. // // // /////////////////////////////////////////////////////////////////////////////// // #endregion hints // ///////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////// // Use Cases // // #region uses // /////////////////////////////////////////////////////////////////////////////// // // // Sometimes APIs cannot have parameters/data added to them due to being 3rd // // party libraries, or requiring a breaking change. Having implicit access // // to contextual data allows working around this. // // // /////////////////////////////////////////////////////////////////////////////// // #endregion uses // ///////////////////////////////////////////////////////////////////////////////