1const http = require('http')
2const https = require('https')
3
4function doRequest (options, data) {
5  const { ssl, encoding, requestOptions } = options
6  if (data && requestOptions.headers) {
7    requestOptions.headers['Content-Length'] = Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data)
8  }
9  return new Promise((resolve, reject) => {
10    let responseText = ''
11    const responseBinary = []
12    const httpRequest = ssl ? https.request : http.request
13    const req = httpRequest(requestOptions, function (response) {
14      if (encoding !== 'binary') {
15        response.setEncoding(encoding)
16      }
17      response.on('data', function (chunk) {
18        if (encoding === 'binary') {
19          responseBinary.push(chunk)
20        } else {
21          responseText += chunk
22        }
23      })
24      response.on('end', function () {
25        const result = {
26          error: null,
27          data: { statusCode: response.statusCode, headers: response.headers }
28        }
29        if (encoding === 'binary') {
30          result.data.binary = Buffer.concat(responseBinary)
31        } else {
32          result.data.text = responseText
33        }
34        resolve(result)
35      })
36      response.on('error', function (error) {
37        reject(error)
38      })
39    }).on('error', function (error) {
40      reject(error)
41    })
42    if (data) {
43      req.write(data)
44    }
45    req.end()
46  })
47}
48
49(async () => {
50  try {
51    const encoding = 'utf-8'
52    let data
53    const args = process.argv.slice(2)
54    const options = {}
55    for (let j = 0; j < args.length; j++) {
56      const arg = args[j]
57      if (arg.startsWith('--ssl=')) {
58        options.ssl = arg.slice('--ssl='.length) === 'true'
59      } else if (arg.startsWith('--encoding=')) {
60        options.encoding = arg.slice('--encoding='.length)
61      } else if (arg.startsWith('--request-options=')) {
62        options.requestOptions = JSON.parse(arg.slice('--request-options='.length))
63      }
64    }
65    if (process.stdin.isTTY) {
66      // Even though executed by name, the first argument is still "node",
67      // the second the script name. The third is the string we want.
68      data = Buffer.from(process.argv[2] || '', encoding)
69      // There will be a trailing \n from the user hitting enter. Get rid of it.
70      data = data.replace(/\n$/, '')
71      const result = await doRequest(options, data)
72      console.log(JSON.stringify(result))
73    } else {
74      // Accepting piped content. E.g.:
75      // echo "pass in this string as input" | ./example-script
76      data = ''
77      process.stdin.setEncoding(encoding)
78      process.stdin.on('readable', function () {
79        let chunk = process.stdin.read()
80        while (chunk) {
81          data += chunk
82          chunk = process.stdin.read()
83        }
84      })
85      process.stdin.on('end', async function () {
86        try {
87          const result = await doRequest(options, data)
88          console.log(JSON.stringify(result))
89        } catch (e) {
90          console.log(JSON.stringify({ error: e }))
91        }
92      })
93    }
94  } catch (e) {
95    console.log(JSON.stringify({ error: e }))
96  }
97})()
98