summaryrefslogtreecommitdiffstats
path: root/readme.md
diff options
context:
space:
mode:
Diffstat (limited to 'readme.md')
-rw-r--r--readme.md139
1 files changed, 138 insertions, 1 deletions
diff --git a/readme.md b/readme.md
index 2e3118f..4a515e5 100644
--- a/readme.md
+++ b/readme.md
@@ -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: {},
+}
```