summaryrefslogtreecommitdiffstats
path: root/server.js
diff options
context:
space:
mode:
authorJannis R <mail@jannisr.de>2020-05-02 15:32:36 +0200
committerJannis R <mail@jannisr.de>2020-05-02 16:35:50 +0200
commit1b5af6f4bdfca939e780ae70bd6e1819425824f7 (patch)
tree4e3fb0c4957680348c473ff45e3478780d1ba55c /server.js
parent635b65aa8af3b35a4ea2c8a5fea805853942cbf4 (diff)
move code, server example :memo:
Diffstat (limited to 'server.js')
-rw-r--r--server.js80
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