From c6a417420e4e82611fdf940d9b7403b8479f8dfc Mon Sep 17 00:00:00 2001 From: Jannis R Date: Sun, 3 May 2020 00:21:22 +0200 Subject: client: followRedirects option --- client.js | 77 ++++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 20 deletions(-) (limited to 'client.js') diff --git a/client.js b/client.js index 77dd88b..2edede7 100644 --- a/client.js +++ b/client.js @@ -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 -- cgit v1.3