diff options
Diffstat (limited to 'readme.md')
| -rw-r--r-- | readme.md | 139 |
1 files changed, 138 insertions, 1 deletions
@@ -19,8 +19,145 @@ npm install @derhuerst/gemini ## Usage +### Server + +The following code assumes that you have a valid SSL certificate & key. + +```js +const {createServer, DEFAULT_PORT} = require('@derhuerst/gemini') + +const onError = (err) => { + console.error(err) + process.exit(1) +} + +const server = createGeminiServer({ + cert: …, // certificate (+ chain) + key: …, // private key + passphrase: …, // passphrase, if the key is encrypted +}, (req, res) => { + if (req.path === '/foo') { + if (!req.clientFingerprint) { + return res.requestTransientClientCert('/foo is secret!') + } + res.write('foo') + res.end('!') + } else if (req.path === '/bar') { + res.redirect('/foo') + } else { + res.gone() + } +}) + +server.listen(DEFAULT_PORT) +server.on('error', console.error) +``` + +### Client + +```js +const request = require('@derhuerst/gemini/client') + +request('/bar', (err, res) => { + if (err) { + console.error(err) + process.exit(1) + } + + console.log(res.statusCode, res.statusMessage) + if (res.meta) console.log(res.meta) + res.pipe(process.stdout) +}) +``` + +#### [TOFU](https://en.wikipedia.org/wiki/Trust_on_first_use)-style client certificates + +> Interactive clients for human users MUST inform users that such a session has been requested and require the user to approve generation of such a certificate. Transient certificates MUST NOT be generated automatically. +– [Gemini spec](https://gemini.circumlunar.space/docs/spec-spec.txt), section 1.4.3 + +If is up to you how to implement that approval process. As an example, we're going to build a simple CLI prompt: + +```js +const {createInterface} = require('readline') + +const letUserConfirmClientCertUsage = ({host, reason}, cb) => { + const prompt = createInterface({ + input: process.stdin, + output: process.stdout, + history: 0, + }) + prompt.question(`Send client cert to ${host}? Server says: "${reason}". y/n > `, (confirmed) => { + prompt.close() + cb(confirmed === 'y' || confirmed === 'Y') + }) +} + +request('/foo', { + // opt into client certificates + useClientCerts: true, + letUserConfirmClientCertUsage, +}, cb) +``` + + +## API + +```js +const createServer = require('@derhuerst/gemini/server') +createServer(opt = {}, onRequest) +``` + +`opt` extends the following defaults: + +```js +{ + // SSL certificate & key + cert: null, key: null, passphrase: null, + // additional options to be passed into `tls.createServer` + tlsOpt: {}, +} +``` + +--- + +```js +const request = require('@derhuerst/gemini/client') +request(pathOrUrl, opt = {}, cb) +``` + +`opt` extends the following defaults: + +```js +{ + // follow redirects automatically + followRedirects: false, + // client certificates + useClientCerts: false, + letUserConfirmClientCertUsage: null, + clientCertStore: defaultClientCertStore, + // additional options to be passed into `tls.connect` + tlsOpt: {}, +} +``` + +--- + +```js +const connect = require('@derhuerst/gemini/connect') +connect(opt = {}, cb) +``` + +`opt` extends the following defaults: + ```js -todo +{ + hostname: '127.0.0.1', + port: 1965, + // client certificate + cert: null, key: null, passphrase: null, + // additional options to be passed into `tls.connect` + tlsOpt: {}, +} ``` |
