diff --git a/src/vs/base/node/request.ts b/src/vs/base/node/request.ts deleted file mode 100644 index 17731debc5b..00000000000 --- a/src/vs/base/node/request.ts +++ /dev/null @@ -1,183 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { isBoolean, isNumber } from 'vs/base/common/types'; -import * as https from 'https'; -import * as http from 'http'; -import { Stream } from 'stream'; -import { parse as parseUrl } from 'url'; -import { createWriteStream } from 'fs'; -import { assign } from 'vs/base/common/objects'; -import { createGunzip } from 'zlib'; -import { CancellationToken } from 'vs/base/common/cancellation'; -import { canceled } from 'vs/base/common/errors'; - -export type Agent = any; - -export interface IRawRequestFunction { - (options: http.RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest; -} - -export interface IRequestOptions { - type?: string; - url?: string; - user?: string; - password?: string; - headers?: any; - timeout?: number; - data?: string | Stream; - agent?: Agent; - followRedirects?: number; - strictSSL?: boolean; - getRawRequest?(options: IRequestOptions): IRawRequestFunction; -} - -export interface IRequestContext { - // req: http.ClientRequest; - // res: http.ClientResponse; - res: { - headers: { [n: string]: string }; - statusCode?: number; - }; - stream: Stream; -} - -export interface IRequestFunction { - (options: IRequestOptions, token: CancellationToken): Promise; -} - -async function getNodeRequest(options: IRequestOptions): Promise { - const endpoint = parseUrl(options.url!); - const module = endpoint.protocol === 'https:' ? await import('https') : await import('http'); - return module.request; -} - -export function request(options: IRequestOptions, token: CancellationToken): Promise { - let req: http.ClientRequest; - - const rawRequestPromise = options.getRawRequest - ? Promise.resolve(options.getRawRequest(options)) - : Promise.resolve(getNodeRequest(options)); - - return rawRequestPromise.then(rawRequest => { - - return new Promise((c, e) => { - const endpoint = parseUrl(options.url!); - - 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; - } - - 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']) { - 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 } 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); - } else { - options.data.pipe(req); - return; - } - } - - req.end(); - - token.onCancellationRequested(() => { - req.abort(); - e(canceled()); - }); - }); - }); -} - -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 function download(filePath: string, context: IRequestContext): Promise { - return new Promise((c, e) => { - const out = createWriteStream(filePath); - - out.once('finish', () => c(undefined)); - context.stream.once('error', e); - context.stream.pipe(out); - }); -} - -export function asText(context: IRequestContext): Promise { - return new Promise((c, e) => { - if (!isSuccess(context)) { - return e('Server returned ' + context.res.statusCode); - } - - if (hasNoContent(context)) { - return c(null); - } - - const buffer: string[] = []; - context.stream.on('data', (d: string) => buffer.push(d)); - context.stream.on('end', () => c(buffer.join(''))); - context.stream.on('error', e); - }); -} - -export function asJson(context: IRequestContext): Promise { - return new Promise((c, e) => { - if (!isSuccess(context)) { - return e('Server returned ' + context.res.statusCode); - } - - if (hasNoContent(context)) { - return c(null); - } - - const buffer: string[] = []; - context.stream.on('data', (d: string) => buffer.push(d)); - context.stream.on('end', () => { - try { - c(JSON.parse(buffer.join(''))); - } catch (err) { - e(err); - } - }); - context.stream.on('error', e); - }); -} diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts index 00acb515cb3..e713834efe6 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts @@ -19,8 +19,8 @@ import { ExtensionManagementService } from 'vs/platform/extensionManagement/node import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ConfigurationService } from 'vs/platform/configuration/node/configurationService'; -import { IRequestService } from 'vs/platform/request/node/request'; -import { RequestService } from 'vs/platform/request/electron-browser/requestService'; +import { IRequestService } from 'vs/platform/request/common/request'; +import { RequestService } from 'vs/platform/request/browser/requestService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { combinedAppender, NullTelemetryService, ITelemetryAppender, NullAppender, LogAppender } from 'vs/platform/telemetry/common/telemetryUtils'; import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties'; @@ -51,6 +51,10 @@ import { SpdLogService } from 'vs/platform/log/node/spdlogService'; import { DiagnosticsService } from 'vs/platform/diagnostics/node/diagnosticsService'; import { IDiagnosticsService } from 'vs/platform/diagnostics/common/diagnosticsService'; import { DiagnosticsChannel } from 'vs/platform/diagnostics/node/diagnosticsIpc'; +import { FileService } from 'vs/platform/files/common/fileService'; +import { IFileService } from 'vs/platform/files/common/files'; +import { DiskFileSystemProvider } from 'vs/platform/files/electron-browser/diskFileSystemProvider'; +import { Schemas } from 'vs/base/common/network'; export interface ISharedProcessConfiguration { readonly machineId: string; @@ -122,6 +126,15 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat const dialogChannel = server.getChannel('dialog', activeWindowRouter); services.set(IDialogService, new DialogChannelClient(dialogChannel)); + // Files + const fileService = new FileService(logService); + services.set(IFileService, fileService); + disposables.add(fileService); + + const diskFileSystemProvider = new DiskFileSystemProvider(logService); + disposables.add(diskFileSystemProvider); + fileService.registerProvider(Schemas.file, diskFileSystemProvider); + const instantiationService = new InstantiationService(services); let telemetryService: ITelemetryService; diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index d34f16ef958..f70eece8b30 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -83,6 +83,9 @@ import { statSync } from 'fs'; import { ISignService } from 'vs/platform/sign/common/sign'; import { IDiagnosticsService } from 'vs/platform/diagnostics/common/diagnosticsService'; import { DiagnosticsService } from 'vs/platform/diagnostics/node/diagnosticsIpc'; +import { FileService } from 'vs/platform/files/common/fileService'; +import { IFileService } from 'vs/platform/files/common/files'; +import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider'; export class CodeApplication extends Disposable { @@ -418,6 +421,13 @@ export class CodeApplication extends Disposable { private async createServices(machineId: string, sharedProcess: SharedProcess, sharedProcessClient: Promise>): Promise { const services = new ServiceCollection(); + // Files + const fileService = this._register(new FileService(this.logService)); + services.set(IFileService, fileService); + + const diskFileSystemProvider = this._register(new DiskFileSystemProvider(this.logService)); + fileService.registerProvider(Schemas.file, diskFileSystemProvider); + switch (process.platform) { case 'win32': services.set(IUpdateService, new SyncDescriptor(Win32UpdateService)); diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index e71b758a7f7..897fe6ef386 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -26,7 +26,7 @@ import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/ import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ConfigurationService } from 'vs/platform/configuration/node/configurationService'; -import { IRequestService } from 'vs/platform/request/node/request'; +import { IRequestService } from 'vs/platform/request/common/request'; import { RequestService } from 'vs/platform/request/electron-main/requestService'; import * as fs from 'fs'; import { CodeApplication } from 'vs/code/electron-main/app'; diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts index 9446ef00d59..cd80057618c 100644 --- a/src/vs/code/node/cliProcessMain.ts +++ b/src/vs/code/node/cliProcessMain.ts @@ -22,7 +22,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { combinedAppender, NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService'; import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties'; -import { IRequestService } from 'vs/platform/request/node/request'; +import { IRequestService } from 'vs/platform/request/common/request'; import { RequestService } from 'vs/platform/request/node/requestService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ConfigurationService } from 'vs/platform/configuration/node/configurationService'; diff --git a/src/vs/platform/download/node/downloadService.ts b/src/vs/platform/download/node/downloadService.ts index 7822ed2253d..e464b7ae73d 100644 --- a/src/vs/platform/download/node/downloadService.ts +++ b/src/vs/platform/download/node/downloadService.ts @@ -7,19 +7,20 @@ import { IDownloadService } from 'vs/platform/download/common/download'; import { URI } from 'vs/base/common/uri'; import { Schemas } from 'vs/base/common/network'; import { copy } from 'vs/base/node/pfs'; -import { IRequestService } from 'vs/platform/request/node/request'; -import { asText, download } from 'vs/base/node/request'; +import { IRequestService, asText } from 'vs/platform/request/common/request'; import { CancellationToken } from 'vs/base/common/cancellation'; import { join } from 'vs/base/common/path'; import { tmpdir } from 'os'; import { generateUuid } from 'vs/base/common/uuid'; +import { IFileService } from 'vs/platform/files/common/files'; export class DownloadService implements IDownloadService { _serviceBrand: any; constructor( - @IRequestService private readonly requestService: IRequestService + @IRequestService private readonly requestService: IRequestService, + @IFileService private readonly fileService: IFileService ) { } download(uri: URI, target: string = join(tmpdir(), generateUuid()), cancellationToken: CancellationToken = CancellationToken.None): Promise { @@ -30,7 +31,7 @@ export class DownloadService implements IDownloadService { return this.requestService.request(options, cancellationToken) .then(context => { if (context.res.statusCode === 200) { - return download(target, context).then(() => target); + return this.fileService.writeFile(URI.file(target), context.stream).then(() => target); } return asText(context) .then(message => Promise.reject(new Error(`Expected 200, got back ${context.res.statusCode} instead.\n\n${message}`))); diff --git a/src/vs/platform/extensionManagement/node/extensionGalleryService.ts b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts index 77ed9973c5d..71c67d5bda3 100644 --- a/src/vs/platform/extensionManagement/node/extensionGalleryService.ts +++ b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts @@ -9,10 +9,9 @@ import { getErrorMessage, isPromiseCanceledError, canceled } from 'vs/base/commo import { StatisticType, IGalleryExtension, IExtensionGalleryService, IGalleryExtensionAsset, IQueryOptions, SortBy, SortOrder, IExtensionIdentifier, IReportedExtension, InstallOperation, ITranslation, IGalleryExtensionVersion, IGalleryExtensionAssets, isIExtensionIdentifier } from 'vs/platform/extensionManagement/common/extensionManagement'; import { getGalleryExtensionId, getGalleryExtensionTelemetryData, adoptToGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { assign, getOrDefault } from 'vs/base/common/objects'; -import { IRequestService } from 'vs/platform/request/node/request'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IPager } from 'vs/base/common/paging'; -import { IRequestOptions, IRequestContext, download, asJson, asText } from 'vs/base/node/request'; +import { IRequestService, IRequestOptions, IRequestContext, asJson, asText } from 'vs/platform/request/common/request'; import pkg from 'vs/platform/product/node/package'; import product from 'vs/platform/product/node/product'; import { isEngineValid } from 'vs/platform/extensions/node/extensionValidator'; @@ -23,6 +22,8 @@ import { values } from 'vs/base/common/map'; import { CancellationToken } from 'vs/base/common/cancellation'; import { ILogService } from 'vs/platform/log/common/log'; import { IExtensionManifest } from 'vs/platform/extensions/common/extensions'; +import { IFileService } from 'vs/platform/files/common/files'; +import { URI } from 'vs/base/common/uri'; interface IRawGalleryExtensionFile { assetType: string; @@ -336,7 +337,8 @@ export class ExtensionGalleryService implements IExtensionGalleryService { @IRequestService private readonly requestService: IRequestService, @ILogService private readonly logService: ILogService, @IEnvironmentService private readonly environmentService: IEnvironmentService, - @ITelemetryService private readonly telemetryService: ITelemetryService + @ITelemetryService private readonly telemetryService: ITelemetryService, + @IFileService private readonly fileService: IFileService, ) { const config = product.extensionsGallery; this.extensionsGalleryUrl = config && config.serviceUrl; @@ -555,7 +557,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService { } : extension.assets.download; return this.getAsset(downloadAsset) - .then(context => download(zipPath, context)) + .then(context => this.fileService.writeFile(URI.file(zipPath), context.stream)) .then(() => log(new Date().getTime() - startTime)) .then(() => zipPath); } diff --git a/src/vs/platform/files/common/files.ts b/src/vs/platform/files/common/files.ts index 69b1fb785d4..4b576f6de98 100644 --- a/src/vs/platform/files/common/files.ts +++ b/src/vs/platform/files/common/files.ts @@ -105,7 +105,7 @@ export interface IFileService { /** * Updates the content replacing its previous value. */ - writeFile(resource: URI, bufferOrReadable: VSBuffer | VSBufferReadable, options?: IWriteFileOptions): Promise; + writeFile(resource: URI, bufferOrReadable: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: IWriteFileOptions): Promise; /** * Moves the file/folder to a new path identified by the resource. diff --git a/src/vs/platform/files/electron-browser/diskFileSystemProvider.ts b/src/vs/platform/files/electron-browser/diskFileSystemProvider.ts index 68cc8ed95db..2c23af873f1 100644 --- a/src/vs/platform/files/electron-browser/diskFileSystemProvider.ts +++ b/src/vs/platform/files/electron-browser/diskFileSystemProvider.ts @@ -9,14 +9,9 @@ import { FileDeleteOptions, FileSystemProviderCapabilities } from 'vs/platform/f import { isWindows } from 'vs/base/common/platform'; import { localize } from 'vs/nls'; import { basename } from 'vs/base/common/path'; -import { ILogService } from 'vs/platform/log/common/log'; export class DiskFileSystemProvider extends NodeDiskFileSystemProvider { - constructor(logService: ILogService) { - super(logService); - } - get capabilities(): FileSystemProviderCapabilities { if (!this._capabilities) { this._capabilities = super.capabilities | FileSystemProviderCapabilities.Trash; diff --git a/src/vs/platform/request/browser/requestService.ts b/src/vs/platform/request/browser/requestService.ts new file mode 100644 index 00000000000..bb16b39afea --- /dev/null +++ b/src/vs/platform/request/browser/requestService.ts @@ -0,0 +1,97 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. 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 { + this.logService.trace('RequestService#request', options.url); + + const authorization = this.configurationService.getValue('http.proxyAuthorization'); + if (authorization) { + options.headers = assign(options.headers || {}, { 'Proxy-Authorization': authorization }); + } + + const xhr = new XMLHttpRequest(); + return new Promise((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; + } + + // TODO: remove any + xhr.send(options.data as any); + + // 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; + } + +} \ No newline at end of file diff --git a/src/vs/platform/request/node/request.ts b/src/vs/platform/request/common/request.ts similarity index 66% rename from src/vs/platform/request/node/request.ts rename to src/vs/platform/request/common/request.ts index a19c75449f8..acb9e553824 100644 --- a/src/vs/platform/request/node/request.ts +++ b/src/vs/platform/request/common/request.ts @@ -4,20 +4,72 @@ *--------------------------------------------------------------------------------------------*/ 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('requestService'); +export interface IRequestOptions { + type?: string; + url?: string; + user?: string; + password?: string; + headers?: any; + timeout?: number; + data?: string; + followRedirects?: number; +} + +export interface IRequestContext { + // req: http.ClientRequest; + // res: http.ClientResponse; + res: { + headers: { [n: string]: string }; + statusCode?: number; + }; + stream: VSBufferReadableStream; +} + export interface IRequestService { _serviceBrand: any; request(options: IRequestOptions, token: CancellationToken): Promise; } +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 { + 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(context: IRequestContext): Promise { + 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; diff --git a/src/vs/platform/request/electron-browser/requestService.ts b/src/vs/platform/request/electron-browser/requestService.ts deleted file mode 100644 index 87636c4d4cf..00000000000 --- a/src/vs/platform/request/electron-browser/requestService.ts +++ /dev/null @@ -1,105 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. 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 { - return super.request(options, token, xhrRequest); - } -} - -export const xhrRequest: IRequestFunction = (options: IRequestOptions, token: CancellationToken): Promise => { - - const xhr = new XMLHttpRequest(); - return new Promise((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; -} diff --git a/src/vs/platform/request/electron-main/requestService.ts b/src/vs/platform/request/electron-main/requestService.ts index 72e2847be9e..cd27b9fbf5d 100644 --- a/src/vs/platform/request/electron-main/requestService.ts +++ b/src/vs/platform/request/electron-main/requestService.ts @@ -3,8 +3,8 @@ * Licensed under the MIT License. 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 { - return super.request(options, token, options => request(assign({}, options || {}, { getRawRequest }), token)); + return super.request(assign({}, options || {}, { getRawRequest }), token); } } diff --git a/src/vs/base/node/proxy.ts b/src/vs/platform/request/node/proxy.ts similarity index 97% rename from src/vs/base/node/proxy.ts rename to src/vs/platform/request/node/proxy.ts index 2ef6c6768b2..c5932a7d10b 100644 --- a/src/vs/base/node/proxy.ts +++ b/src/vs/platform/request/node/proxy.ts @@ -5,7 +5,8 @@ import { Url, parse as parseUrl } from 'url'; import { isBoolean } from 'vs/base/common/types'; -import { Agent } from './request'; + +export type Agent = any; function getSystemProxyURI(requestURL: Url): string | null { if (requestURL.protocol === 'http:') { diff --git a/src/vs/platform/request/node/requestService.ts b/src/vs/platform/request/node/requestService.ts index c2858fe6dd0..8297dffc911 100644 --- a/src/vs/platform/request/node/requestService.ts +++ b/src/vs/platform/request/node/requestService.ts @@ -3,14 +3,31 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +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 { VSBuffer, VSBufferWriteableStream, writeableBufferStream } 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 @@ -20,9 +37,9 @@ export class RequestService extends Disposable implements IRequestService { _serviceBrand: any; - private proxyUrl?: string; - private strictSSL: boolean; - private authorization?: string; + protected proxyUrl?: string; + protected strictSSL: boolean; + protected authorization?: string; constructor( @IConfigurationService configurationService: IConfigurationService, @@ -39,21 +56,96 @@ export class RequestService extends Disposable implements IRequestService { this.authorization = config.http && config.http.proxyAuthorization; } - request(options: IRequestOptions, token: CancellationToken, requestFn: IRequestFunction = request): Promise { + async request(options: NodeRequestOptions, token: CancellationToken): Promise { 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 { + 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 { + + return new Promise(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()); + } + + const stream: VSBufferWriteableStream = writeableBufferStream(); + _stream.on('data', (d: string) => stream.write(VSBuffer.fromString(d))); + _stream.on('error', e => stream.end(e)); + _stream.on('end', e => stream.end()); + + c({ res, 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()); + }); }); + } -} + +} \ No newline at end of file diff --git a/src/vs/platform/update/electron-main/abstractUpdateService.ts b/src/vs/platform/update/electron-main/abstractUpdateService.ts index fcca3cbfb9f..76544db2221 100644 --- a/src/vs/platform/update/electron-main/abstractUpdateService.ts +++ b/src/vs/platform/update/electron-main/abstractUpdateService.ts @@ -11,7 +11,7 @@ import product from 'vs/platform/product/node/product'; import { IUpdateService, State, StateType, AvailableForDownload, UpdateType } from 'vs/platform/update/common/update'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ILogService } from 'vs/platform/log/common/log'; -import { IRequestService } from 'vs/platform/request/node/request'; +import { IRequestService } from 'vs/platform/request/common/request'; import { CancellationToken } from 'vs/base/common/cancellation'; export function createUpdateURL(platform: string, quality: string): string { diff --git a/src/vs/platform/update/electron-main/updateService.darwin.ts b/src/vs/platform/update/electron-main/updateService.darwin.ts index 4427e2a75eb..352d4d91633 100644 --- a/src/vs/platform/update/electron-main/updateService.darwin.ts +++ b/src/vs/platform/update/electron-main/updateService.darwin.ts @@ -14,7 +14,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ILogService } from 'vs/platform/log/common/log'; import { AbstractUpdateService, createUpdateURL } from 'vs/platform/update/electron-main/abstractUpdateService'; -import { IRequestService } from 'vs/platform/request/node/request'; +import { IRequestService } from 'vs/platform/request/common/request'; export class DarwinUpdateService extends AbstractUpdateService { diff --git a/src/vs/platform/update/electron-main/updateService.linux.ts b/src/vs/platform/update/electron-main/updateService.linux.ts index 38b022755d9..52c4ac7dc2b 100644 --- a/src/vs/platform/update/electron-main/updateService.linux.ts +++ b/src/vs/platform/update/electron-main/updateService.linux.ts @@ -6,13 +6,12 @@ import product from 'vs/platform/product/node/product'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; -import { IRequestService } from 'vs/platform/request/node/request'; import { State, IUpdate, AvailableForDownload, UpdateType } from 'vs/platform/update/common/update'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ILogService } from 'vs/platform/log/common/log'; import { createUpdateURL, AbstractUpdateService } from 'vs/platform/update/electron-main/abstractUpdateService'; -import { asJson } from 'vs/base/node/request'; +import { IRequestService, asJson } from 'vs/platform/request/common/request'; import { shell } from 'electron'; import { CancellationToken } from 'vs/base/common/cancellation'; diff --git a/src/vs/platform/update/electron-main/updateService.win32.ts b/src/vs/platform/update/electron-main/updateService.win32.ts index 8467f908dc6..cbff0bf1c74 100644 --- a/src/vs/platform/update/electron-main/updateService.win32.ts +++ b/src/vs/platform/update/electron-main/updateService.win32.ts @@ -9,20 +9,21 @@ import * as pfs from 'vs/base/node/pfs'; import { memoize } from 'vs/base/common/decorators'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; -import { IRequestService } from 'vs/platform/request/node/request'; import product from 'vs/platform/product/node/product'; import { State, IUpdate, StateType, AvailableForDownload, UpdateType } from 'vs/platform/update/common/update'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ILogService } from 'vs/platform/log/common/log'; import { createUpdateURL, AbstractUpdateService } from 'vs/platform/update/electron-main/abstractUpdateService'; -import { download, asJson } from 'vs/base/node/request'; +import { IRequestService, asJson } from 'vs/platform/request/common/request'; import { checksum } from 'vs/base/node/crypto'; import { tmpdir } from 'os'; import { spawn } from 'child_process'; import { shell } from 'electron'; import { CancellationToken } from 'vs/base/common/cancellation'; import { timeout } from 'vs/base/common/async'; +import { IFileService } from 'vs/platform/files/common/files'; +import { URI } from 'vs/base/common/uri'; async function pollUntil(fn: () => boolean, millis = 1000): Promise { while (!fn()) { @@ -64,7 +65,8 @@ export class Win32UpdateService extends AbstractUpdateService { @ITelemetryService private readonly telemetryService: ITelemetryService, @IEnvironmentService environmentService: IEnvironmentService, @IRequestService requestService: IRequestService, - @ILogService logService: ILogService + @ILogService logService: ILogService, + @IFileService private readonly fileService: IFileService ) { super(lifecycleService, configurationService, environmentService, requestService, logService); @@ -142,7 +144,7 @@ export class Win32UpdateService extends AbstractUpdateService { const downloadPath = `${updatePackagePath}.tmp`; return this.requestService.request({ url }, CancellationToken.None) - .then(context => download(downloadPath, context)) + .then(context => this.fileService.writeFile(URI.file(downloadPath), context.stream)) .then(hash ? () => checksum(downloadPath, update.hash) : () => undefined) .then(() => pfs.rename(downloadPath, updatePackagePath)) .then(() => updatePackagePath); diff --git a/src/vs/workbench/browser/web.simpleservices.ts b/src/vs/workbench/browser/web.simpleservices.ts index 34905fba1a2..dc0f272fbcb 100644 --- a/src/vs/workbench/browser/web.simpleservices.ts +++ b/src/vs/workbench/browser/web.simpleservices.ts @@ -455,27 +455,6 @@ export class SimpleMultiExtensionsManagementService implements IExtensionManagem //#endregion -//#region Request - -export const IRequestService = createDecorator('requestService'); - -export interface IRequestService { - _serviceBrand: any; - - request(options: any, token: CancellationToken): Promise; -} - -export class SimpleRequestService implements IRequestService { - - _serviceBrand: any; - - request(options: any, token: CancellationToken): Promise { - return Promise.resolve(Object.create(null)); - } -} - -//#endregion - //#region Telemetry export class SimpleTelemetryService implements ITelemetryService { diff --git a/src/vs/workbench/contrib/experiments/electron-browser/experimentService.ts b/src/vs/workbench/contrib/experiments/electron-browser/experimentService.ts index 0deb24c7201..9a0aad7548b 100644 --- a/src/vs/workbench/contrib/experiments/electron-browser/experimentService.ts +++ b/src/vs/workbench/contrib/experiments/electron-browser/experimentService.ts @@ -12,11 +12,10 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { IRequestService } from 'vs/platform/request/node/request'; import { language } from 'vs/base/common/platform'; import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; import { match } from 'vs/base/common/glob'; -import { asJson } from 'vs/base/node/request'; +import { IRequestService, asJson } from 'vs/platform/request/common/request'; import { Emitter, Event } from 'vs/base/common/event'; import { ITextFileService, StateChange } from 'vs/workbench/services/textfile/common/textfiles'; import { WorkspaceStats } from 'vs/workbench/contrib/stats/electron-browser/workspaceStats'; diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionTipsService.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionTipsService.ts index f192f1c16d9..853db02ca8d 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionTipsService.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionTipsService.ts @@ -32,8 +32,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { guessMimeTypes, MIME_UNKNOWN } from 'vs/base/common/mime'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { getHashedRemotesFromUri } from 'vs/workbench/contrib/stats/electron-browser/workspaceStats'; -import { IRequestService } from 'vs/platform/request/node/request'; -import { asJson } from 'vs/base/node/request'; +import { IRequestService, asJson } from 'vs/platform/request/common/request'; import { isNumber } from 'vs/base/common/types'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { INotificationService } from 'vs/platform/notification/common/notification'; diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionsSlowActions.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionsSlowActions.ts index fece37e6a35..3b81b03291c 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionsSlowActions.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionsSlowActions.ts @@ -11,9 +11,8 @@ import { URI } from 'vs/base/common/uri'; import { IExtensionHostProfile } from 'vs/workbench/services/extensions/common/extensions'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { localize } from 'vs/nls'; -import { IRequestService } from 'vs/platform/request/node/request'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { asText } from 'vs/base/node/request'; +import { IRequestService, asText } from 'vs/platform/request/common/request'; import { join } from 'vs/base/common/path'; import { onUnexpectedError } from 'vs/base/common/errors'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; diff --git a/src/vs/workbench/contrib/preferences/electron-browser/preferencesSearch.ts b/src/vs/workbench/contrib/preferences/electron-browser/preferencesSearch.ts index a31aa422474..829d560a6ad 100644 --- a/src/vs/workbench/contrib/preferences/electron-browser/preferencesSearch.ts +++ b/src/vs/workbench/contrib/preferences/electron-browser/preferencesSearch.ts @@ -8,8 +8,7 @@ import { top } from 'vs/base/common/arrays'; import * as strings from 'vs/base/common/strings'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IRequestService } from 'vs/platform/request/node/request'; -import { asJson } from 'vs/base/node/request'; +import { IRequestService, asJson } from 'vs/platform/request/common/request'; import { IExtensionManagementService, ILocalExtension, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement'; import { ILogService } from 'vs/platform/log/common/log'; import { IPreferencesSearchService, ISearchProvider, IWorkbenchSettingsConfiguration } from 'vs/workbench/contrib/preferences/common/preferences'; diff --git a/src/vs/workbench/contrib/update/electron-browser/releaseNotesEditor.ts b/src/vs/workbench/contrib/update/electron-browser/releaseNotesEditor.ts index 95c3f16b960..273eaec4fce 100644 --- a/src/vs/workbench/contrib/update/electron-browser/releaseNotesEditor.ts +++ b/src/vs/workbench/contrib/update/electron-browser/releaseNotesEditor.ts @@ -7,7 +7,6 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import * as marked from 'vs/base/common/marked/marked'; import { OS } from 'vs/base/common/platform'; import { URI } from 'vs/base/common/uri'; -import { asText } from 'vs/base/node/request'; import { TokenizationRegistry, ITokenizationSupport } from 'vs/editor/common/modes'; import { generateTokensCSSForColorMap } from 'vs/editor/common/modes/supports/tokenization'; import { tokenizeToString } from 'vs/editor/common/modes/textToHtmlTokenizer'; @@ -17,7 +16,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { IRequestService } from 'vs/platform/request/node/request'; +import { IRequestService, asText } from 'vs/platform/request/common/request'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { addGAParameters } from 'vs/platform/telemetry/node/telemetryNodeUtils'; import { IWebviewEditorService } from 'vs/workbench/contrib/webview/browser/webviewEditorService'; diff --git a/src/vs/workbench/test/electron-browser/colorRegistry.releaseTest.ts b/src/vs/workbench/test/electron-browser/colorRegistry.releaseTest.ts index 40eb17f7d9a..c61f19b0d58 100644 --- a/src/vs/workbench/test/electron-browser/colorRegistry.releaseTest.ts +++ b/src/vs/workbench/test/electron-browser/colorRegistry.releaseTest.ts @@ -12,12 +12,15 @@ import { debugExceptionWidgetBackground } from 'vs/workbench/contrib/debug/brows import { debugToolBarBackground } from 'vs/workbench/contrib/debug/browser/debugToolBar'; import { buttonBackground } from 'vs/workbench/contrib/welcome/page/browser/welcomePage'; import { embeddedEditorBackground } from 'vs/workbench/contrib/welcome/walkThrough/browser/walkThroughPart'; -import { request, asText } from 'vs/base/node/request'; +import { asText } from 'vs/platform/request/common/request'; import * as pfs from 'vs/base/node/pfs'; import * as path from 'vs/base/common/path'; import * as assert from 'assert'; import { getPathFromAmdModule } from 'vs/base/common/amd'; import { CancellationToken } from 'vs/base/common/cancellation'; +import { RequestService } from 'vs/platform/request/node/requestService'; +import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; +import { NullLogService } from 'vs/platform/log/common/log'; interface ColorInfo { @@ -40,7 +43,7 @@ export const experimental: string[] = []; // 'settings.modifiedItemForeground', suite('Color Registry', function () { test('all colors documented', async function () { - const reqContext = await request({ url: 'https://raw.githubusercontent.com/Microsoft/vscode-docs/vnext/docs/getstarted/theme-color-reference.md' }, CancellationToken.None); + const reqContext = await new RequestService(new TestConfigurationService(), new NullLogService()).request({ url: 'https://raw.githubusercontent.com/Microsoft/vscode-docs/vnext/docs/getstarted/theme-color-reference.md' }, CancellationToken.None); const content = (await asText(reqContext))!; const expression = /\-\s*\`([\w\.]+)\`: (.*)/g; diff --git a/src/vs/workbench/workbench.main.ts b/src/vs/workbench/workbench.main.ts index dc3e95c613d..f039eb03b56 100644 --- a/src/vs/workbench/workbench.main.ts +++ b/src/vs/workbench/workbench.main.ts @@ -68,8 +68,8 @@ import { IExtensionGalleryService } from 'vs/platform/extensionManagement/common import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService'; import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService'; -import { IRequestService } from 'vs/platform/request/node/request'; -import { RequestService } from 'vs/platform/request/electron-browser/requestService'; +import { IRequestService } from 'vs/platform/request/common/request'; +import { RequestService } from 'vs/platform/request/browser/requestService'; import { LifecycleService } from 'vs/platform/lifecycle/electron-browser/lifecycleService'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { ILocalizationsService } from 'vs/platform/localizations/common/localizations'; diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts index bba70ef3eab..8ce24a1b1b4 100644 --- a/src/vs/workbench/workbench.web.main.ts +++ b/src/vs/workbench/workbench.web.main.ts @@ -66,8 +66,8 @@ import { BrowserAccessibilityService } from 'vs/platform/accessibility/common/ac // import { IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement'; import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService'; // import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService'; -// import { IRequestService } from 'vs/platform/request/node/request'; -// import { RequestService } from 'vs/platform/request/electron-browser/requestService'; +import { IRequestService } from 'vs/platform/request/common/request'; +import { RequestService } from 'vs/platform/request/browser/requestService'; import { BrowserLifecycleService } from 'vs/platform/lifecycle/browser/lifecycleService'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; @@ -156,7 +156,7 @@ registerSingleton(ITextResourceConfigurationService, TextResourceConfigurationSe registerSingleton(IAccessibilityService, BrowserAccessibilityService, true); registerSingleton(IContextViewService, ContextViewService, true); // registerSingleton(IExtensionGalleryService, ExtensionGalleryService, true); -// registerSingleton(IRequestService, RequestService, true); +registerSingleton(IRequestService, RequestService, true); registerSingleton(ILifecycleService, BrowserLifecycleService); // registerSingleton(ILocalizationsService, LocalizationsService); // registerSingleton(ISharedProcessService, SharedProcessService, true);