diff options
Diffstat (limited to 'client.js')
| -rw-r--r-- | client.js | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/client.js b/client.js new file mode 100644 index 0000000..77dd88b --- /dev/null +++ b/client.js @@ -0,0 +1,69 @@ +'use strict' + +const connect = require('./connect') +const createParser = require('./lib/response-parser') +const { + DEFAULT_PORT, + ALPN_ID, +} = require('./lib/util') + +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) => { + if (err) return cb(err) + + if (socket.alpnProtocol !== ALPN_ID) { + socket.destroy() + return cb(new Error('invalid or missing ALPN protocol')) + } + + const res = createParser() + socket.pipe(res) + socket.once('error', (err) => { + socket.unpipe(res) + res.destroy(err) + }) + + const close = () => { + socket.destroy() + res.destroy() + } + let timeout = setTimeout(close, 20 * 1000) + + res.once('header', (header) => { + clearTimeout(timeout) + + // prepare res + res.socket = socket + res.statusCode = header.statusCode + res.statusMessage = header.statusMsg + res.meta = header.meta // todo: change name + // todo: res.abort(), res.destroy() + + cb(null, res) + socket.emit('response', res) + }) + + // send request + socket.end(encodeURI(pathOrUrl) + ' \r\n') + }) +} + +module.exports = sendGeminiRequest |
