diff options
| -rw-r--r-- | client.js | 77 | ||||
| -rw-r--r-- | connect.js | 6 | ||||
| -rw-r--r-- | examples/client.js | 8 | ||||
| -rw-r--r-- | examples/server.js | 6 |
4 files changed, 67 insertions, 30 deletions
@@ -1,32 +1,16 @@ 'use strict' +const {parse: parseUrl} = require('url') const connect = require('./connect') const createParser = require('./lib/response-parser') const { DEFAULT_PORT, ALPN_ID, } = require('./lib/util') +const {CODES} = require('./lib/statuses') -const sendGeminiRequest = (pathOrUrl, opt, cb) => { - if (typeof pathOrUrl !== 'string' || !pathOrUrl) { - throw new Error('pathOrUrl must be a string & not empty') - } - if (typeof opt === 'function') { - cb = opt - opt = {} - } - const { - port, - tlsOpt, - } = { - port: DEFAULT_PORT, - tlsOpt: {}, - ...opt, - } - - connect({ - port, tlsOpt, - }, (err, socket) => { +const _request = (pathOrUrl, opt, cb) => { + connect(opt, (err, socket) => { if (err) return cb(err) if (socket.alpnProtocol !== ALPN_ID) { @@ -66,4 +50,57 @@ const sendGeminiRequest = (pathOrUrl, opt, cb) => { }) } +const sendGeminiRequest = (pathOrUrl, opt, cb) => { + if (typeof pathOrUrl !== 'string' || !pathOrUrl) { + throw new Error('pathOrUrl must be a string & not empty') + } + if (typeof opt === 'function') { + cb = opt + opt = {} + } + const { + followRedirects, + cert, key, passphrase, + tlsOpt, + } = { + followRedirects: false, + cert: null, key: null, passphrase: null, + tlsOpt: {}, + ...opt, + } + + const target = parseUrl(pathOrUrl) + const hostname = target.hostname || 'localhost' + const port = target.port || DEFAULT_PORT + const reqOpt = { + hostname, port, + cert, key, passphrase, + tlsOpt, + } + + let onRes = cb + if (followRedirects) { + // todo: prevent endless redirects + onRes = (err, res) => { + if (err) return cb(err) + + if ( + res.statusCode === CODES.REDIRECT_TEMPORARY || + res.statusCode === CODES.REDIRECT_PERMANENT + ) { + const newTarget = parseUrl(res.meta) + _request(res.meta, { + ...reqOpt, + host: newTarget.hostname || hostname, + port: newTarget.port || port, + }, onRes) + } else { + cb(null, res) + } + } + } + + _request(pathOrUrl, reqOpt, onRes) +} + module.exports = sendGeminiRequest @@ -13,11 +13,11 @@ const connectToGeminiServer = (opt, cb) => { opt = {} } const { - host, + hostname, port, tlsOpt, } = { - host: '127.0.0.1', + hostname: '127.0.0.1', port: DEFAULT_PORT, tlsOpt: {}, // todo: TOFU via isTrustedCertificate() @@ -27,7 +27,7 @@ const connectToGeminiServer = (opt, cb) => { const socket = connectTls({ ALPNProtocols: [ALPN_ID], minVersion: MIN_TLS_VERSION, - host, port, + hostname, port, // todo: cert, key, passphrase ...tlsOpt, }) diff --git a/examples/client.js b/examples/client.js index 1695335..49e38d0 100644 --- a/examples/client.js +++ b/examples/client.js @@ -1,16 +1,14 @@ 'use strict' -const { - request, - DEFAULT_PORT, -} = require('..') +const {request} = require('..') const onError = (err) => { console.error(err) process.exit(1) } -request('/foo', { +request('/bar', { + followRedirects: true, tlsOpt: { rejectUnauthorized: false, }, diff --git a/examples/server.js b/examples/server.js index bff88e3..2012c42 100644 --- a/examples/server.js +++ b/examples/server.js @@ -8,8 +8,10 @@ const { const onRequest = (req, res) => { if (req.path === '/foo') { - res.write('foo,') - res.end('bar') + res.write('foo') + res.end('!') + } else if (req.path === '/bar') { + res.redirect('/foo') } else { res.gone() } |
