chore: use http-request-plus@1

This commit is contained in:
Julien Fontanet 2023-02-15 19:07:23 +01:00
parent bc0afb589e
commit ab96c549ae
21 changed files with 131 additions and 141 deletions

View File

@ -67,38 +67,44 @@ ${pkg.name} v${pkg.version}`
// sequence path of the current call
const callPath = []
let url
let { token } = opts
if (opts.url !== '') {
url = new URL(opts.url)
const { username } = url
if (username !== '') {
token = username
url.username = ''
}
} else {
url = new URL('https://localhost/')
if (opts.host !== '') {
url.host = opts.host
} else {
const { hostname = 'localhost', port } = config?.http?.listen?.https ?? {}
url.hostname = hostname
url.port = port
}
}
url = new URL('/api/v1', url)
const baseRequest = {
headers: {
'content-type': 'application/json',
cookie: `authenticationToken=${token}`,
},
pathname: '/api/v1',
method: 'POST',
rejectUnauthorized: false,
}
let { token } = opts
if (opts.url !== '') {
const { protocol, host, username } = new URL(opts.url)
Object.assign(baseRequest, { protocol, host })
if (username !== '') {
token = username
}
} else {
baseRequest.protocol = 'https:'
if (opts.host !== '') {
baseRequest.host = opts.host
} else {
const { hostname = 'localhost', port } = config?.http?.listen?.https ?? {}
baseRequest.hostname = hostname
baseRequest.port = port
}
}
baseRequest.headers.cookie = `authenticationToken=${token}`
const call = async ({ method, params }) => {
if (callPath.length !== 0) {
process.stderr.write(`\n${colors.bold(`--- call #${callPath.join('.')}`)} ---\n\n`)
}
const response = await hrp.post(baseRequest, {
const response = await hrp(url, {
...baseRequest,
body: format.request(0, method, params),
})

View File

@ -32,7 +32,7 @@
"content-type": "^1.0.4",
"cson-parser": "^4.0.7",
"getopts": "^2.2.3",
"http-request-plus": "^0.14.0",
"http-request-plus": "github:JsCommunity/http-request-plus#v1",
"json-rpc-protocol": "^0.13.1",
"promise-toolbox": "^0.21.0",
"pumpify": "^2.0.1",

View File

@ -35,7 +35,7 @@
"form-data": "^4.0.0",
"fs-extra": "^11.1.0",
"get-stream": "^6.0.0",
"http-request-plus": "^0.14.0",
"http-request-plus": "github:JsCommunity/http-request-plus#v1",
"human-format": "^1.0.0",
"lodash": "^4.17.4",
"pretty-ms": "^7.0.0",

View File

@ -230,10 +230,15 @@ export async function upload(args) {
)
formData.append('file', input, { filename: 'file', knownLength: length })
try {
return await hrp.post(url.toString(), { body: formData, headers: formData.getHeaders() }).readAll('utf-8')
const response = await hrp(url.toString(), { body: formData, headers: formData.getHeaders(), method: 'POST' })
return await response.text()
} catch (e) {
console.log('ERROR', e)
console.log('ERROR content', await e.response.readAll('utf-8'))
const { response } = e
if (response !== undefined) {
console.log('ERROR content', await response.text())
}
throw e
}
}

View File

@ -26,7 +26,7 @@
"@xen-orchestra/log": "^0.6.0",
"d3-time-format": "^3.0.0",
"golike-defer": "^0.5.1",
"http-request-plus": "^0.14.0",
"http-request-plus": "github:JsCommunity/http-request-plus#v1",
"json-rpc-protocol": "^0.13.2",
"lodash": "^4.17.15",
"promise-toolbox": "^0.21.0",

View File

@ -35,7 +35,7 @@
"bind-property-descriptor": "^2.0.0",
"blocked": "^1.2.1",
"debug": "^4.0.1",
"http-request-plus": "^0.14.0",
"http-request-plus": "github:JsCommunity/http-request-plus#v1",
"jest-diff": "^29.0.3",
"json-rpc-protocol": "^0.13.1",
"kindof": "^2.0.0",

View File

@ -5,7 +5,6 @@ import ms from 'ms'
import httpRequest from 'http-request-plus'
import map from 'lodash/map'
import noop from 'lodash/noop'
import omit from 'lodash/omit'
import ProxyAgent from 'proxy-agent'
import { coalesceCalls } from '@vates/coalesce-calls'
import { Collection } from 'xo-collection'
@ -392,7 +391,7 @@ export class Xapi extends EventEmitter {
const response = await this._addSyncStackTrace(
pRetry(
async () =>
httpRequest($cancelToken, url.href, {
httpRequest(url, {
rejectUnauthorized: !this._allowUnauthorized,
// this is an inactivity timeout (unclear in Node doc)
@ -403,6 +402,8 @@ export class Xapi extends EventEmitter {
// Support XS <= 6.5 with Node => 12
minVersion: 'TLSv1',
agent: this.httpAgent,
signal: $cancelToken,
}),
{
when: { code: 302 },
@ -411,7 +412,7 @@ export class Xapi extends EventEmitter {
if (response === undefined) {
throw error
}
response.cancel()
response.destroy()
url = await this._replaceHostAddressInUrl(new URL(response.headers.location, url))
},
}
@ -467,40 +468,45 @@ export class Xapi extends EventEmitter {
url.search = new URLSearchParams(query)
await this._setHostAddressInUrl(url, host)
const doRequest = httpRequest.put.bind(undefined, $cancelToken, {
agent: this.httpAgent,
const doRequest = (url, opts) =>
httpRequest(url, {
agent: this.httpAgent,
body,
headers,
rejectUnauthorized: !this._allowUnauthorized,
body,
headers,
method: 'PUT',
rejectUnauthorized: !this._allowUnauthorized,
signal: $cancelToken,
// this is an inactivity timeout (unclear in Node doc)
timeout: this._httpInactivityTimeout,
// this is an inactivity timeout (unclear in Node doc)
timeout: this._httpInactivityTimeout,
// Support XS <= 6.5 with Node => 12
minVersion: 'TLSv1',
})
// Support XS <= 6.5 with Node => 12
minVersion: 'TLSv1',
...opts,
})
const dummyUrl = new URL(url)
dummyUrl.searchParams.delete('task_id')
// if body is a stream, sends a dummy request to probe for a redirection
// before consuming body
const response = await this._addSyncStackTrace(
isStream
? doRequest(url.href, {
? doRequest(dummyUrl, {
body: '',
// omit task_id because this request will fail on purpose
query: 'task_id' in query ? omit(query, 'task_id') : query,
maxRedirects: 0,
}).then(
response => {
response.cancel()
return doRequest(url.href)
response.destroy()
return doRequest(url)
},
async error => {
let response
if (error != null && (response = error.response) != null) {
response.cancel()
response.destroy()
const {
headers: { location },
@ -510,14 +516,14 @@ export class Xapi extends EventEmitter {
// ensure the original query is sent
const newUrl = new URL(location, url)
newUrl.searchParams.set('task_id', query.task_id)
return doRequest((await this._replaceHostAddressInUrl(newUrl)).href)
return doRequest(await this._replaceHostAddressInUrl(newUrl))
}
}
throw error
}
)
: doRequest(url.href)
: doRequest(url)
)
if (pTaskResult !== undefined) {
@ -540,13 +546,13 @@ export class Xapi extends EventEmitter {
const { req } = response
if (!req.finished) {
await new Promise((resolve, reject) => {
req.on('finish', resolve).on('error', reject)
req.on('finish', resolve)
response.on('error', reject)
})
}
if (useHack) {
response.cancel()
response.destroy()
} else {
// consume the response
response.resume()

View File

@ -1,6 +1,5 @@
import httpRequestPlus from 'http-request-plus'
import { format, parse } from 'json-rpc-protocol'
import { join } from 'path'
import XapiError from '../_XapiError'
@ -8,41 +7,37 @@ import UnsupportedTransport from './_UnsupportedTransport'
// https://github.com/xenserver/xenadmin/blob/0df39a9d83cd82713f32d24704852a0fd57b8a64/XenModel/XenAPI/Session.cs#L403-L433
export default ({ secureOptions, url, agent }) => {
return (method, args) =>
httpRequestPlus
.post(url, {
...secureOptions,
body: format.request(0, method, args),
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
pathname: join(url.pathname, 'jsonrpc'),
agent,
})
.readAll('utf8')
.then(
text => {
let response
try {
response = parse(text)
} catch (error) {
throw new UnsupportedTransport()
}
url = new URL('./jsonrpc', Object.assign(new URL('http://localhost'), url))
if (response.type === 'response') {
return response.result
}
return async function (method, args) {
const res = await httpRequestPlus(url, {
...secureOptions,
body: format.request(0, method, args),
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
method: 'POST',
agent,
}).catch(error => {
console.warn('xen-api/transports/json-rpc', error)
throw XapiError.wrap(response.error)
},
error => {
if (error.response !== undefined) {
// HTTP error
throw new UnsupportedTransport()
}
throw new UnsupportedTransport()
})
throw error
}
)
const text = await res.text()
let response
try {
response = parse(text)
} catch (error) {
throw new UnsupportedTransport()
}
if (response.type === 'response') {
return response.result
}
throw XapiError.wrap(response.error)
}
}

View File

@ -473,14 +473,15 @@ async function call(args) {
noop
)
return hrp
.post(url, httpOptions, {
body: input,
headers: {
'content-length': length,
},
})
.readAll('utf-8')
const response = await hrp(url, {
...httpOptions,
body: input,
headers: {
'content-length': length,
},
method: 'POST',
})
return response.text()
}
}

View File

@ -32,7 +32,7 @@
"chalk": "^5.0.1",
"fs-extra": "^11.1.0",
"getopts": "^2.3.0",
"http-request-plus": "^0.14.0",
"http-request-plus": "github:JsCommunity/http-request-plus#v1",
"human-format": "^1.0.0",
"lodash": "^4.17.4",
"micromatch": "^4.0.2",

View File

@ -35,11 +35,6 @@ const indexName = (name, index) => {
return name.slice(0, NAME_MAX_LENGTH - suffix.length) + suffix
}
const onRequest = req => {
req.setTimeout(REQUEST_TIMEOUT)
req.on('timeout', req.abort)
}
class Netbox {
#allowUnauthorized
#endpoint
@ -108,15 +103,15 @@ class Netbox {
const options = {
headers: { 'Content-Type': 'application/json', Authorization: `Token ${this.#token}` },
method,
onRequest,
rejectUnauthorized: !this.#allowUnauthorized,
timeout: REQUEST_TIMEOUT,
}
const httpRequest = async () => {
try {
const response = await this.#xo.httpRequest(url, options)
this.#netboxApiVersion = response.headers['api-version']
const body = await response.readAll()
const body = await response.text()
if (body.length > 0) {
return JSON.parse(body)
}
@ -127,7 +122,7 @@ class Netbox {
body: dataDebug,
}
try {
const body = await error.response.readAll()
const body = await error.response.text()
if (body.length > 0) {
error.data.error = JSON.parse(body)
}

View File

@ -689,7 +689,7 @@ ${entriesWithMissingStats.map(({ listItem }) => listItem).join('\n')}`
payload.vm_uuid = xapiObject.uuid
}
// JSON is not well formed, can't use the default node parser
return JSON5.parse(await (await xapi.getResource('/rrd_updates', payload)).readAll())
return JSON5.parse(await (await xapi.getResource('/rrd_updates', payload)).text())
}
}

View File

@ -121,7 +121,7 @@ class XoServerIcinga2 {
exit_status: icinga2Status,
}),
})
.readAll()
.then(response => response.text())
}
}

View File

@ -38,10 +38,7 @@ class XoServerHooks {
body: JSON.stringify({ ...data, type }),
headers: { 'Content-Type': 'application/json' },
method: 'POST',
onRequest: req => {
req.setTimeout(1e4)
req.on('timeout', req.abort)
},
timeout: 1e4,
})
}

View File

@ -82,7 +82,7 @@
"helmet": "^3.9.0",
"highland": "^2.11.1",
"http-proxy": "^1.16.2",
"http-request-plus": "^0.14.0",
"http-request-plus": "github:JsCommunity/http-request-plus#v1",
"http-server-plus": "^1.0.0",
"human-format": "^1.0.0",
"iterable-backoff": "^0.1.0",

View File

@ -1133,7 +1133,7 @@ async function handleExport(req, res, { xapi, vmRef, compress, format = 'xva' })
const stream =
format === 'ova' ? await xapi.exportVmOva(vmRef) : await xapi.VM_export(FAIL_ON_QUEUE, vmRef, { compress })
res.on('close', () => stream.cancel())
res.on('close', () => stream.destroy())
// Remove the filename as it is already part of the URL.
stream.headers['content-disposition'] = 'attachment'

View File

@ -263,7 +263,7 @@ export default class XapiStats {
start: timestamp,
},
})
.then(response => response.readAll().then(JSON5.parse))
.then(response => response.text().then(JSON5.parse))
}
// To avoid multiple requests, we keep a cash for the stats and

View File

@ -65,11 +65,7 @@ export default {
async _getXenUpdates() {
const response = await this.xo.httpRequest('http://updates.xensource.com/XenServer/updates.xml')
if (response.statusCode !== 200) {
throw new Error('cannot fetch patches list from Citrix')
}
const data = parseXml(await response.readAll()).patchdata
const data = parseXml(await response.buffer()).patchdata
const patches = { __proto__: null }
forEach(data.patches.patch, patch => {

View File

@ -26,13 +26,11 @@ export default class Http {
})
}
httpRequest(...args) {
return hrp(
{
agent: this._agent,
},
...args
)
httpRequest(url, opts) {
return hrp(url, {
...opts,
agent: this._agent,
})
}
// Inject the proxy into the environnement, it will be automatically used by `_agent` and by most libs (e.g `axios`)

View File

@ -419,6 +419,8 @@ export default class Proxy {
async callProxyMethod(id, method, params, { assertType = 'scalar' } = {}) {
const proxy = await this._getProxy(id)
const url = new URL('https://localhost/api/v1')
const request = {
body: format.request(0, method, params),
headers: {
@ -426,14 +428,12 @@ export default class Proxy {
Cookie: cookie.serialize('authenticationToken', proxy.authenticationToken),
},
method: 'POST',
pathname: '/api/v1',
protocol: 'https:',
rejectUnauthorized: false,
timeout: this._app.config.getDuration('xo-proxy.callTimeout'),
}
if (proxy.address !== undefined) {
request.host = proxy.address
url.host = proxy.address
} else {
const vm = this._app.getXapi(proxy.vmUuid).getObjectByUuid(proxy.vmUuid)
@ -444,11 +444,10 @@ export default class Proxy {
throw error
}
// use hostname field to avoid issues with IPv6 addresses
request.hostname = address
url.hostname = address.includes(':') ? `[${address}]` : address
}
const response = await hrp(request)
const response = await hrp(url, request)
const authenticationToken = parseSetCookie(response, {
map: true,

View File

@ -10786,14 +10786,11 @@ http-proxy@^1.16.2, http-proxy@^1.17.0, http-proxy@^1.18.1:
follow-redirects "^1.0.0"
requires-port "^1.0.0"
http-request-plus@^0.14.0:
"http-request-plus@github:JsCommunity/http-request-plus#v1":
version "0.14.0"
resolved "https://registry.yarnpkg.com/http-request-plus/-/http-request-plus-0.14.0.tgz#a190ece4b5b67d66ab442d2983a1a1bcd363b866"
integrity sha512-EX/OoPA2vWO7k9Whq+vOSN/nH/P1Ae9smCSzhBIIEU8WLDJyXoH9S8pY4Ieh4yQartrMB1vc2o6T4KV4oIQsDQ==
resolved "https://codeload.github.com/JsCommunity/http-request-plus/tar.gz/af641418c9a91e0285f9662e2794822045062b0c"
dependencies:
is-redirect "^1.0.0"
promise-toolbox "^0.19.2"
pump "^3.0.0"
"@xen-orchestra/log" "^0.6.0"
http-server-plus@^0.12.0:
version "0.12.0"
@ -11621,11 +11618,6 @@ is-promise@^2.0.0, is-promise@^2.2.2:
resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1"
integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==
is-redirect@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24"
integrity sha512-cr/SlUEe5zOGmzvj9bUyC4LVvkNVAXu4GytXLNMr1pny+a65MpQ9IJzFHD5vi7FyJgb4qt27+eS3TuQnqB+RQw==
is-regex@^1.0.3, is-regex@^1.0.4, is-regex@^1.0.5, is-regex@^1.1.0, is-regex@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
@ -15879,7 +15871,7 @@ promise-polyfill@^6.0.1:
resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-6.1.0.tgz#dfa96943ea9c121fca4de9b5868cb39d3472e057"
integrity sha512-g0LWaH0gFsxovsU7R5LrrhHhWAWiHRnh1GPrhXnPgYsDkIqjRYUYSZEsej/wtleDrz5xVSIDbeKfidztp2XHFQ==
promise-toolbox@^0.19.0, promise-toolbox@^0.19.2:
promise-toolbox@^0.19.0:
version "0.19.2"
resolved "https://registry.yarnpkg.com/promise-toolbox/-/promise-toolbox-0.19.2.tgz#7453d117313a9afba6add0c67c46210f7b5833f8"
integrity sha512-3956j2kaS4nJG1ANd4SZBQj8GrxLSlvfpVzMT4I7k7K8BkhhpAChXOI3B1VMlU7TQstShBh4D4uKt9zFjahKNg==