diff options
Diffstat (limited to 'index.js')
| -rw-r--r-- | index.js | 77 |
1 files changed, 76 insertions, 1 deletions
@@ -1,3 +1,78 @@ 'use strict' -// todo +const {createServer: createTlsServer} = require('tls') +const {EventEmitter} = require('events') +const {createParser} = require('./lib/parser') +const createResponse = require('./lib/response') + +const ALPN_ID = 'gemini' // todo: clarify this + +const createGeminiServer = (opt = {}, onRequest) => { + if (typeof opt === 'function') { + onRequest = opt + opt = {} + } + const { + tlsOpt, + } = { + tlsOpt: {}, + ...opt, + } + + const onConnection = (socket) => { + const req = createParser() + socket.pipe(req) + socket.once('error', (err) => { + socket.unpipe(req) + req.destroy(err) + }) + + const close = () => { + socket.destroy() + req.destroy() + } + let timeout = setTimeout(close, 20 * 1000) + + req.once('header', (header) => { + clearTimeout(timeout) + + // prepare req + req.socket = socket + req.url = header.url + const url = new URL(header.url, 'http://foo/') + req.path = url.pathname + // todo: req.abort(), req.destroy() + + // prepare res + const res = createResponse() + res.pipe(socket) + res.once('error', (err) => { + console.error('error', err) + res.unpipe(socket) + socket.destroy(err) + }) + Object.defineProperty(res, 'socket', {value: socket}) + + onRequest(req, res) + server.emit('request', req, res) + }) + } + + const server = createTlsServer({ + // ALPNProtocols: [ALPN_ID], + // https://gemini.circumlunar.space/docs/spec-spec.txt#1.4.1 + // > Servers MUST use TLS version 1.2 or higher and SHOULD use TLS version + // > 1.3 or higher. + minVersion: 'TLSv1.2', + ...tlsOpt, + }, onConnection) + + return server +} + +// https://gemini.circumlunar.space/docs/spec-spec.txt, 1. +// > When Gemini is served over TCP/IP, servers should listen on port 1965 +// > (the first manned Gemini mission, Gemini 3, flew in March '65). +createGeminiServer.DEFAULT_PORT = 1965 + +module.exports = createGeminiServer |
