diff options
| author | Jannis R <mail@jannisr.de> | 2020-05-02 15:32:36 +0200 |
|---|---|---|
| committer | Jannis R <mail@jannisr.de> | 2020-05-02 16:35:50 +0200 |
| commit | 1b5af6f4bdfca939e780ae70bd6e1819425824f7 (patch) | |
| tree | 4e3fb0c4957680348c473ff45e3478780d1ba55c /server.js | |
| parent | 635b65aa8af3b35a4ea2c8a5fea805853942cbf4 (diff) | |
move code, server example :memo:
Diffstat (limited to 'server.js')
| -rw-r--r-- | server.js | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/server.js b/server.js new file mode 100644 index 0000000..344728c --- /dev/null +++ b/server.js @@ -0,0 +1,80 @@ +'use strict' + +const {createServer: createTlsServer} = require('tls') +const {EventEmitter} = require('events') +const createParser = require('./lib/request-parser') +const createResponse = require('./lib/response') +const {ALPN_ID} = require('./lib/util') + +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', + requestCert: !!alwaysRequireClientCert, + // > Gemini requests typically will be made without a client + // > certificate being sent to the server. If a requested resource + // > is part of a server-side application which requires persistent + // > state, a Gemini server can [...] request that the client repeat + // the request with a "transient certificate" to initiate a client + // > certificate section. + rejectUnauthorized: false, + ...tlsOpt, + }, onConnection) + + return server +} + +module.exports = createGeminiServer |
