diff --git a/index.mjs b/index.mjs index 92625f1..ebe9ef3 100644 --- a/index.mjs +++ b/index.mjs @@ -1,30 +1,44 @@ import * as fs from 'node:fs'; -import express from 'express'; +import http from 'node:http'; -const sites = fs.readFileSync('./webring.txt', 'utf-8') - // split lines - .split(/\r?\n/) - // trim whitespace from each line - .map(site => site.trim()) - // exclude empty lines and lines that start with # because why not - .filter(site => site && !site.startsWith('#')); - -// modulo that does the right thing with negatives -// https://stackoverflow.com/a/4467559 const mod = (n, m) => ((n % m) + m) % m; +const stripURL = s => s.replace(/(^https?:\/\/|\/$)/g, '') -function handle (offset, request, response) { - const from = request.query.from; - const index = sites.findIndex(site => site === from); - if (!from || index === -1) { - response.status(400).send('the provided site is not in the webring'); - return; +const sitesArray = fs.readFileSync('./webring.txt', 'utf-8') + .match(/(? ({ + ...acc, [current]: { + '/next': sitesArray[mod(index + 1, sitesArray.length)], + '/prev': sitesArray[mod(index - 1, sitesArray.length)], } - response.redirect(301, sites[mod(index + offset, sites.length)]); +}), {}) + +const redirect = (response, url) => { + response.setHeader('Location', url) + response.statusCode = 301 + response.end() } -express() - .get('/prev', (request, response) => handle(-1, request, response)) - .get('/next', (request, response) => handle(+1, request, response)) - .get('/list', (_, response) => response.type('txt').send(sites.join('\n'))) - .listen(process.env.PORT || 8080); +const handle = (direction, from, response) => { + const destination = sitesLookup[stripURL(from)]?.[direction] + + if (destination) + return redirect(response, destination) + + response.statusCode = 400 + response.end('the provided site is not in the webring') +} + +http.createServer((request, response) => { + const url = new URL(request.url, `http://${request.headers.host}`); + + if (url.pathname === '/prev' || url.pathname === '/next') { + return handle(url.pathname, url.searchParams.get('from'), response) + } else if (url.pathname === '/list') { + return response.setHeader('Content-Type', 'text/plain').end(sitesArray.join('\n')) + } + + response.statusCode = 404 + response.end('not found') +}).listen(process.env.PORT || 8080)