summaryrefslogtreecommitdiffstats
path: root/client.js
diff options
context:
space:
mode:
authorJannis R <mail@jannisr.de>2020-05-02 15:41:32 +0200
committerJannis R <mail@jannisr.de>2020-05-02 16:36:09 +0200
commit58d2e4c5e17b3306e35e7a8e28cce5cc4eb74f26 (patch)
tree44fd76efa940862b38442fa8926d6a0092268487 /client.js
parent1b5af6f4bdfca939e780ae70bd6e1819425824f7 (diff)
basic client
Diffstat (limited to 'client.js')
-rw-r--r--client.js69
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