mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 (#6381)
* Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 * disable strict null check
This commit is contained in:
96
src/vs/platform/request/browser/requestService.ts
Normal file
96
src/vs/platform/request/browser/requestService.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IRequestOptions, IRequestContext } from 'vs/platform/request/common/request';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { canceled } from 'vs/base/common/errors';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { assign } from 'vs/base/common/objects';
|
||||
import { VSBuffer, bufferToStream } from 'vs/base/common/buffer';
|
||||
|
||||
/**
|
||||
* This service exposes the `request` API, while using the global
|
||||
* or configured proxy settings.
|
||||
*/
|
||||
export class RequestService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
constructor(
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@ILogService private readonly logService: ILogService
|
||||
) {
|
||||
}
|
||||
|
||||
request(options: IRequestOptions, token: CancellationToken): Promise<IRequestContext> {
|
||||
this.logService.trace('RequestService#request', options.url);
|
||||
|
||||
const authorization = this.configurationService.getValue<string>('http.proxyAuthorization');
|
||||
if (authorization) {
|
||||
options.headers = assign(options.headers || {}, { 'Proxy-Authorization': authorization });
|
||||
}
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
return new Promise<IRequestContext>((resolve, reject) => {
|
||||
|
||||
xhr.open(options.type || 'GET', options.url || '', true, options.user, options.password);
|
||||
this.setRequestHeaders(xhr, options);
|
||||
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.onerror = e => reject(new Error(xhr.statusText && ('XHR failed: ' + xhr.statusText)));
|
||||
xhr.onload = (e) => {
|
||||
resolve({
|
||||
res: {
|
||||
statusCode: xhr.status,
|
||||
headers: this.getResponseHeaders(xhr)
|
||||
},
|
||||
stream: bufferToStream(VSBuffer.wrap(new Uint8Array(xhr.response)))
|
||||
});
|
||||
};
|
||||
xhr.ontimeout = e => reject(new Error(`XHR timeout: ${options.timeout}ms`));
|
||||
|
||||
if (options.timeout) {
|
||||
xhr.timeout = options.timeout;
|
||||
}
|
||||
|
||||
xhr.send(options.data);
|
||||
|
||||
// cancel
|
||||
token.onCancellationRequested(() => {
|
||||
xhr.abort();
|
||||
reject(canceled());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private setRequestHeaders(xhr: XMLHttpRequest, options: IRequestOptions): void {
|
||||
if (options.headers) {
|
||||
outer: for (let k in options.headers) {
|
||||
switch (k) {
|
||||
case 'User-Agent':
|
||||
case 'Accept-Encoding':
|
||||
case 'Content-Length':
|
||||
// unsafe headers
|
||||
continue outer;
|
||||
}
|
||||
xhr.setRequestHeader(k, options.headers[k]);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private getResponseHeaders(xhr: XMLHttpRequest): { [name: string]: string } {
|
||||
const headers: { [name: string]: string } = Object.create(null);
|
||||
for (const line of xhr.getAllResponseHeaders().split(/\r\n|\n|\r/g)) {
|
||||
if (line) {
|
||||
const idx = line.indexOf(':');
|
||||
headers[line.substr(0, idx).trim().toLowerCase()] = line.substr(idx + 1).trim();
|
||||
}
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,20 +4,74 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IRequestOptions, IRequestContext } from 'vs/base/node/request';
|
||||
import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { VSBufferReadableStream, streamToBuffer } from 'vs/base/common/buffer';
|
||||
|
||||
export const IRequestService = createDecorator<IRequestService>('requestService');
|
||||
|
||||
export interface IHeaders {
|
||||
[header: string]: string;
|
||||
}
|
||||
|
||||
export interface IRequestOptions {
|
||||
type?: string;
|
||||
url?: string;
|
||||
user?: string;
|
||||
password?: string;
|
||||
headers?: IHeaders;
|
||||
timeout?: number;
|
||||
data?: string;
|
||||
followRedirects?: number;
|
||||
}
|
||||
|
||||
export interface IRequestContext {
|
||||
res: {
|
||||
headers: IHeaders;
|
||||
statusCode?: number;
|
||||
};
|
||||
stream: VSBufferReadableStream;
|
||||
}
|
||||
|
||||
export interface IRequestService {
|
||||
_serviceBrand: any;
|
||||
|
||||
request(options: IRequestOptions, token: CancellationToken): Promise<IRequestContext>;
|
||||
}
|
||||
|
||||
function isSuccess(context: IRequestContext): boolean {
|
||||
return (context.res.statusCode && context.res.statusCode >= 200 && context.res.statusCode < 300) || context.res.statusCode === 1223;
|
||||
}
|
||||
|
||||
function hasNoContent(context: IRequestContext): boolean {
|
||||
return context.res.statusCode === 204;
|
||||
}
|
||||
|
||||
export async function asText(context: IRequestContext): Promise<string | null> {
|
||||
if (!isSuccess(context)) {
|
||||
throw new Error('Server returned ' + context.res.statusCode);
|
||||
}
|
||||
if (hasNoContent(context)) {
|
||||
return null;
|
||||
}
|
||||
const buffer = await streamToBuffer(context.stream);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
export async function asJson<T = {}>(context: IRequestContext): Promise<T | null> {
|
||||
if (!isSuccess(context)) {
|
||||
throw new Error('Server returned ' + context.res.statusCode);
|
||||
}
|
||||
if (hasNoContent(context)) {
|
||||
return null;
|
||||
}
|
||||
const buffer = await streamToBuffer(context.stream);
|
||||
return JSON.parse(buffer.toString());
|
||||
}
|
||||
|
||||
|
||||
export interface IHTTPConfiguration {
|
||||
http?: {
|
||||
proxy?: string;
|
||||
51
src/vs/platform/request/common/requestIpc.ts
Normal file
51
src/vs/platform/request/common/requestIpc.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IRequestService, IRequestOptions, IRequestContext, IHeaders } from 'vs/platform/request/common/request';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { VSBuffer, bufferToStream, streamToBuffer } from 'vs/base/common/buffer';
|
||||
|
||||
type RequestResponse = [
|
||||
{
|
||||
headers: IHeaders;
|
||||
statusCode?: number;
|
||||
},
|
||||
VSBuffer
|
||||
];
|
||||
|
||||
export class RequestChannel implements IServerChannel {
|
||||
|
||||
constructor(private readonly service: IRequestService) { }
|
||||
|
||||
listen(context: any, event: string): Event<any> {
|
||||
throw new Error('Invalid listen');
|
||||
}
|
||||
|
||||
call(context: any, command: string, args?: any): Promise<any> {
|
||||
switch (command) {
|
||||
case 'request': return this.service.request(args[0], CancellationToken.None)
|
||||
.then(async ({ res, stream }) => {
|
||||
const buffer = await streamToBuffer(stream);
|
||||
return <RequestResponse>[{ statusCode: res.statusCode, headers: res.headers }, buffer];
|
||||
});
|
||||
}
|
||||
throw new Error('Invalid call');
|
||||
}
|
||||
}
|
||||
|
||||
export class RequestChannelClient {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
constructor(private readonly channel: IChannel) { }
|
||||
|
||||
async request(options: IRequestOptions, token: CancellationToken): Promise<IRequestContext> {
|
||||
const [res, buffer] = await this.channel.call<RequestResponse>('request', [options]);
|
||||
return { res, stream: bufferToStream(buffer) };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IRequestOptions, IRequestContext, IRequestFunction } from 'vs/base/node/request';
|
||||
import { Readable } from 'stream';
|
||||
import { RequestService as NodeRequestService } from 'vs/platform/request/node/requestService';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { canceled } from 'vs/base/common/errors';
|
||||
|
||||
/**
|
||||
* This service exposes the `request` API, while using the global
|
||||
* or configured proxy settings.
|
||||
*/
|
||||
export class RequestService extends NodeRequestService {
|
||||
request(options: IRequestOptions, token: CancellationToken): Promise<IRequestContext> {
|
||||
return super.request(options, token, xhrRequest);
|
||||
}
|
||||
}
|
||||
|
||||
export const xhrRequest: IRequestFunction = (options: IRequestOptions, token: CancellationToken): Promise<IRequestContext> => {
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
return new Promise<IRequestContext>((resolve, reject) => {
|
||||
|
||||
xhr.open(options.type || 'GET', options.url || '', true, options.user, options.password);
|
||||
setRequestHeaders(xhr, options);
|
||||
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.onerror = e => reject(new Error(xhr.statusText && ('XHR failed: ' + xhr.statusText)));
|
||||
xhr.onload = (e) => {
|
||||
resolve({
|
||||
res: {
|
||||
statusCode: xhr.status,
|
||||
headers: getResponseHeaders(xhr)
|
||||
},
|
||||
stream: new class ArrayBufferStream extends Readable {
|
||||
|
||||
private _buffer: Buffer;
|
||||
private _offset: number;
|
||||
private _length: number;
|
||||
|
||||
constructor(arraybuffer: ArrayBuffer) {
|
||||
super();
|
||||
this._buffer = Buffer.from(new Uint8Array(arraybuffer));
|
||||
this._offset = 0;
|
||||
this._length = this._buffer.length;
|
||||
}
|
||||
|
||||
_read(size: number) {
|
||||
if (this._offset < this._length) {
|
||||
this.push(this._buffer.slice(this._offset, (this._offset + size)));
|
||||
this._offset += size;
|
||||
} else {
|
||||
this.push(null);
|
||||
}
|
||||
}
|
||||
|
||||
}(xhr.response)
|
||||
});
|
||||
};
|
||||
xhr.ontimeout = e => reject(new Error(`XHR timeout: ${options.timeout}ms`));
|
||||
|
||||
if (options.timeout) {
|
||||
xhr.timeout = options.timeout;
|
||||
}
|
||||
|
||||
// TODO: remove any
|
||||
xhr.send(options.data as any);
|
||||
|
||||
// cancel
|
||||
token.onCancellationRequested(() => {
|
||||
xhr.abort();
|
||||
reject(canceled());
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function setRequestHeaders(xhr: XMLHttpRequest, options: IRequestOptions): void {
|
||||
if (options.headers) {
|
||||
outer: for (let k in options.headers) {
|
||||
switch (k) {
|
||||
case 'User-Agent':
|
||||
case 'Accept-Encoding':
|
||||
case 'Content-Length':
|
||||
// unsafe headers
|
||||
continue outer;
|
||||
}
|
||||
xhr.setRequestHeader(k, options.headers[k]);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getResponseHeaders(xhr: XMLHttpRequest): { [name: string]: string } {
|
||||
const headers: { [name: string]: string } = Object.create(null);
|
||||
for (const line of xhr.getAllResponseHeaders().split(/\r\n|\n|\r/g)) {
|
||||
if (line) {
|
||||
const idx = line.indexOf(':');
|
||||
headers[line.substr(0, idx).trim().toLowerCase()] = line.substr(idx + 1).trim();
|
||||
}
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
@@ -3,8 +3,8 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IRequestOptions, IRequestContext, request, IRawRequestFunction } from 'vs/base/node/request';
|
||||
import { RequestService as NodeRequestService } from 'vs/platform/request/node/requestService';
|
||||
import { IRequestOptions, IRequestContext } from 'vs/platform/request/common/request';
|
||||
import { RequestService as NodeRequestService, IRawRequestFunction } from 'vs/platform/request/node/requestService';
|
||||
import { assign } from 'vs/base/common/objects';
|
||||
import { net } from 'electron';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
@@ -16,6 +16,6 @@ function getRawRequest(options: IRequestOptions): IRawRequestFunction {
|
||||
export class RequestService extends NodeRequestService {
|
||||
|
||||
request(options: IRequestOptions, token: CancellationToken): Promise<IRequestContext> {
|
||||
return super.request(options, token, options => request(assign({}, options || {}, { getRawRequest }), token));
|
||||
return super.request(assign({}, options || {}, { getRawRequest }), token);
|
||||
}
|
||||
}
|
||||
|
||||
52
src/vs/platform/request/node/proxy.ts
Normal file
52
src/vs/platform/request/node/proxy.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Url, parse as parseUrl } from 'url';
|
||||
import { isBoolean } from 'vs/base/common/types';
|
||||
|
||||
export type Agent = any;
|
||||
|
||||
function getSystemProxyURI(requestURL: Url): string | null {
|
||||
if (requestURL.protocol === 'http:') {
|
||||
return process.env.HTTP_PROXY || process.env.http_proxy || null;
|
||||
} else if (requestURL.protocol === 'https:') {
|
||||
return process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy || null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export interface IOptions {
|
||||
proxyUrl?: string;
|
||||
strictSSL?: boolean;
|
||||
}
|
||||
|
||||
export async function getProxyAgent(rawRequestURL: string, options: IOptions = {}): Promise<Agent> {
|
||||
const requestURL = parseUrl(rawRequestURL);
|
||||
const proxyURL = options.proxyUrl || getSystemProxyURI(requestURL);
|
||||
|
||||
if (!proxyURL) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const proxyEndpoint = parseUrl(proxyURL);
|
||||
|
||||
if (!/^https?:$/.test(proxyEndpoint.protocol || '')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const opts = {
|
||||
host: proxyEndpoint.hostname || '',
|
||||
port: Number(proxyEndpoint.port),
|
||||
auth: proxyEndpoint.auth,
|
||||
rejectUnauthorized: isBoolean(options.strictSSL) ? options.strictSSL : true
|
||||
};
|
||||
|
||||
const Ctor = requestURL.protocol === 'http:'
|
||||
? await import('http-proxy-agent')
|
||||
: await import('https-proxy-agent');
|
||||
|
||||
return new Ctor(opts);
|
||||
}
|
||||
@@ -3,34 +3,51 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import * as https from 'https';
|
||||
import * as http from 'http';
|
||||
import { Stream } from 'stream';
|
||||
import { createGunzip } from 'zlib';
|
||||
import { parse as parseUrl } from 'url';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { assign } from 'vs/base/common/objects';
|
||||
import { IRequestOptions, IRequestContext, IRequestFunction, request } from 'vs/base/node/request';
|
||||
import { getProxyAgent } from 'vs/base/node/proxy';
|
||||
import { IRequestService, IHTTPConfiguration } from 'vs/platform/request/node/request';
|
||||
import { isBoolean, isNumber } from 'vs/base/common/types';
|
||||
import { canceled } from 'vs/base/common/errors';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IRequestOptions, IRequestContext, IRequestService, IHTTPConfiguration } from 'vs/platform/request/common/request';
|
||||
import { getProxyAgent, Agent } from 'vs/platform/request/node/proxy';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { toVSBufferReadableStream } from 'vs/base/common/buffer';
|
||||
|
||||
export interface IRawRequestFunction {
|
||||
(options: http.RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest;
|
||||
}
|
||||
|
||||
export interface NodeRequestOptions extends IRequestOptions {
|
||||
agent?: Agent;
|
||||
strictSSL?: boolean;
|
||||
getRawRequest?(options: IRequestOptions): IRawRequestFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* This service exposes the `request` API, while using the global
|
||||
* or configured proxy settings.
|
||||
*/
|
||||
export class RequestService implements IRequestService {
|
||||
export class RequestService extends Disposable implements IRequestService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
private proxyUrl?: string;
|
||||
private strictSSL: boolean;
|
||||
private authorization?: string;
|
||||
private disposables: IDisposable[] = [];
|
||||
|
||||
constructor(
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@ILogService private readonly logService: ILogService
|
||||
) {
|
||||
super();
|
||||
this.configure(configurationService.getValue<IHTTPConfiguration>());
|
||||
configurationService.onDidChangeConfiguration(() => this.configure(configurationService.getValue()), this, this.disposables);
|
||||
this._register(configurationService.onDidChangeConfiguration(() => this.configure(configurationService.getValue()), this));
|
||||
}
|
||||
|
||||
private configure(config: IHTTPConfiguration) {
|
||||
@@ -39,21 +56,91 @@ export class RequestService implements IRequestService {
|
||||
this.authorization = config.http && config.http.proxyAuthorization;
|
||||
}
|
||||
|
||||
request(options: IRequestOptions, token: CancellationToken, requestFn: IRequestFunction = request): Promise<IRequestContext> {
|
||||
async request(options: NodeRequestOptions, token: CancellationToken): Promise<IRequestContext> {
|
||||
this.logService.trace('RequestService#request', options.url);
|
||||
|
||||
const { proxyUrl, strictSSL } = this;
|
||||
const agentPromise = options.agent ? Promise.resolve(options.agent) : Promise.resolve(getProxyAgent(options.url || '', { proxyUrl, strictSSL }));
|
||||
const agent = options.agent ? options.agent : await getProxyAgent(options.url || '', { proxyUrl, strictSSL });
|
||||
|
||||
return agentPromise.then(agent => {
|
||||
options.agent = agent;
|
||||
options.strictSSL = strictSSL;
|
||||
options.agent = agent;
|
||||
options.strictSSL = strictSSL;
|
||||
|
||||
if (this.authorization) {
|
||||
options.headers = assign(options.headers || {}, { 'Proxy-Authorization': this.authorization });
|
||||
if (this.authorization) {
|
||||
options.headers = assign(options.headers || {}, { 'Proxy-Authorization': this.authorization });
|
||||
}
|
||||
|
||||
return this._request(options, token);
|
||||
}
|
||||
|
||||
private async getNodeRequest(options: IRequestOptions): Promise<IRawRequestFunction> {
|
||||
const endpoint = parseUrl(options.url!);
|
||||
const module = endpoint.protocol === 'https:' ? await import('https') : await import('http');
|
||||
return module.request;
|
||||
}
|
||||
|
||||
private _request(options: NodeRequestOptions, token: CancellationToken): Promise<IRequestContext> {
|
||||
|
||||
return new Promise<IRequestContext>(async (c, e) => {
|
||||
let req: http.ClientRequest;
|
||||
|
||||
const endpoint = parseUrl(options.url!);
|
||||
const rawRequest = options.getRawRequest
|
||||
? options.getRawRequest(options)
|
||||
: await this.getNodeRequest(options);
|
||||
|
||||
const opts: https.RequestOptions = {
|
||||
hostname: endpoint.hostname,
|
||||
port: endpoint.port ? parseInt(endpoint.port) : (endpoint.protocol === 'https:' ? 443 : 80),
|
||||
protocol: endpoint.protocol,
|
||||
path: endpoint.path,
|
||||
method: options.type || 'GET',
|
||||
headers: options.headers,
|
||||
agent: options.agent,
|
||||
rejectUnauthorized: isBoolean(options.strictSSL) ? options.strictSSL : true
|
||||
};
|
||||
|
||||
if (options.user && options.password) {
|
||||
opts.auth = options.user + ':' + options.password;
|
||||
}
|
||||
|
||||
return requestFn(options, token);
|
||||
req = rawRequest(opts, (res: http.IncomingMessage) => {
|
||||
const followRedirects: number = isNumber(options.followRedirects) ? options.followRedirects : 3;
|
||||
if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && followRedirects > 0 && res.headers['location']) {
|
||||
this._request(assign({}, options, {
|
||||
url: res.headers['location'],
|
||||
followRedirects: followRedirects - 1
|
||||
}), token).then(c, e);
|
||||
} else {
|
||||
let stream: Stream = res;
|
||||
|
||||
if (res.headers['content-encoding'] === 'gzip') {
|
||||
stream = stream.pipe(createGunzip());
|
||||
}
|
||||
|
||||
c({ res, stream: toVSBufferReadableStream(stream) } as IRequestContext);
|
||||
}
|
||||
});
|
||||
|
||||
req.on('error', e);
|
||||
|
||||
if (options.timeout) {
|
||||
req.setTimeout(options.timeout);
|
||||
}
|
||||
|
||||
if (options.data) {
|
||||
if (typeof options.data === 'string') {
|
||||
req.write(options.data);
|
||||
}
|
||||
}
|
||||
|
||||
req.end();
|
||||
|
||||
token.onCancellationRequested(() => {
|
||||
req.abort();
|
||||
e(canceled());
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user