|
|
|
// Packages
|
|
|
|
import {parse} from 'url'
|
|
|
|
import http2 from 'spdy'
|
|
|
|
import fetch from 'node-fetch'
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a `fetch` version with a similar
|
|
|
|
* API to the browser's configured with a
|
|
|
|
* HTTP2 agent.
|
|
|
|
*
|
|
|
|
* It encodes `body` automatically as JSON.
|
|
|
|
*
|
|
|
|
* @param {String} host
|
|
|
|
* @return {Function} fetch
|
|
|
|
*/
|
|
|
|
|
|
|
|
export default class Agent {
|
|
|
|
constructor(url, {tls = true, debug} = {}) {
|
|
|
|
this._url = url
|
|
|
|
const parsed = parse(url)
|
|
|
|
this._host = parsed.hostname
|
|
|
|
this._port = parsed.port
|
|
|
|
this._protocol = parsed.protocol
|
|
|
|
this._debug = debug
|
|
|
|
if (tls) {
|
|
|
|
this._initAgent()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_initAgent() {
|
|
|
|
if (this._protocol !== 'https:') {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
this._agent = http2.createAgent({
|
|
|
|
host: this._host,
|
|
|
|
port: this._port || 443
|
|
|
|
}).once('error', err => this._onError(err))
|
|
|
|
}
|
|
|
|
|
|
|
|
_onError(err) {
|
|
|
|
if (this._debug) {
|
|
|
|
console.log('> [debug] agent connection error', err.stack)
|
|
|
|
}
|
|
|
|
this._error = err
|
|
|
|
}
|
|
|
|
|
|
|
|
fetch(path, opts = {}) {
|
|
|
|
if (this._error) {
|
|
|
|
if (this._debug) {
|
|
|
|
console.log('> [debug] re-initializing agent after error')
|
|
|
|
}
|
|
|
|
|
|
|
|
this._error = null
|
|
|
|
this._initAgent()
|
|
|
|
}
|
|
|
|
|
|
|
|
const {body} = opts
|
|
|
|
if (this._agent) {
|
|
|
|
opts.agent = this._agent
|
|
|
|
}
|
|
|
|
|
|
|
|
if (body && typeof body === 'object' && typeof body.pipe !== 'function') {
|
|
|
|
opts.headers['Content-Type'] = 'application/json'
|
|
|
|
opts.body = JSON.stringify(body)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opts.body && typeof body.pipe !== 'function') {
|
|
|
|
opts.headers['Content-Length'] = Buffer.byteLength(opts.body)
|
|
|
|
}
|
|
|
|
|
|
|
|
return fetch(this._url + path, opts)
|
|
|
|
}
|
|
|
|
|
|
|
|
close() {
|
|
|
|
if (this._debug) {
|
|
|
|
console.log('> [debug] closing agent')
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this._agent) {
|
|
|
|
this._agent.close()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|