diff --git a/src/json-schema-content-provider.ts b/src/json-schema-content-provider.ts index a52115c0..22149bd2 100644 --- a/src/json-schema-content-provider.ts +++ b/src/json-schema-content-provider.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { TextDocumentContentProvider, Uri, workspace, window } from 'vscode'; +import { TextDocumentContentProvider, Uri, workspace, window, WorkspaceConfiguration } from 'vscode'; import { xhr, configure as configureHttpRequests, getErrorStatusDescription, XHRResponse } from 'request-light'; import { SchemaExtensionAPI } from './schema-extension-api'; @@ -47,7 +47,9 @@ export async function getJsonSchemaContent(uri: string, schemaCache: IJSONSchema const cachedETag = schemaCache.getETag(uri); const httpSettings = workspace.getConfiguration('http'); - configureHttpRequests(httpSettings.proxy, httpSettings.proxyStrictSSL); + if (requestShouldBeProxied(uri, httpSettings)) { + configureHttpRequests(httpSettings.proxy, httpSettings.proxyStrictSSL); + } const headers: { [key: string]: string } = { 'Accept-Encoding': 'gzip, deflate' }; if (cachedETag) { @@ -97,3 +99,22 @@ export async function getJsonSchemaContent(uri: string, schemaCache: IJSONSchema function createReject(error: XHRResponse): Promise { return Promise.reject(error.responseText || getErrorStatusDescription(error.status) || error.toString()); } + +export function requestShouldBeProxied(uri: string, httpSettings: WorkspaceConfiguration): boolean { + const proxy = httpSettings.get('proxy'); + const noProxy = httpSettings.get('noProxy'); + // proxy not configured + if (!proxy) return false; + // proxy configured, no items in noProxy + if (!noProxy.length) return true; + + const noProxyEntries = noProxy.map((item) => item.trim()); + const uriAuthority = Uri.parse(uri).authority; + return !noProxyEntries.some((entry) => { + if (entry.startsWith('*.')) { + return uriAuthority.endsWith(entry.substring(1)); + } else { + return uriAuthority === entry; + } + }); +} diff --git a/test/proxy.test.ts b/test/proxy.test.ts new file mode 100644 index 00000000..2aa492e5 --- /dev/null +++ b/test/proxy.test.ts @@ -0,0 +1,67 @@ +import * as vscode from 'vscode'; +import { requestShouldBeProxied } from '../src/json-schema-content-provider'; +import assert = require('assert'); + +class Getable { + constructor(obj: { [key: string]: unknown }) { + Object.assign(this, obj); + } + + get(key: string): T { + return this[key]; + } +} + +function workspaceConfiguration(obj: { [key: string]: unknown }): vscode.WorkspaceConfiguration { + return (new Getable(obj) as unknown) as vscode.WorkspaceConfiguration; +} + +describe('#requestShouldBeProxied', () => { + describe('when http.proxy is empty', () => { + it('should return false', () => { + assert.equal( + requestShouldBeProxied( + 'https://google.com', + workspaceConfiguration({ + proxy: '', + }) + ), + false + ); + }); + }); + + describe(`when http.proxy is set`, () => { + describe('when http.noProxy is empty', () => { + const httpSettings = workspaceConfiguration({ + proxy: 'https://localhost:8080', + noProxy: [], + }); + + it('should return true', () => { + assert.equal(requestShouldBeProxied('https://google.com', httpSettings), true); + assert.equal(requestShouldBeProxied('http://something.example.com', httpSettings), true); + assert.equal(requestShouldBeProxied('http://localhost/path', httpSettings), true); + assert.equal(requestShouldBeProxied('http://127.0.0.1/path', httpSettings), true); + }); + }); + + describe('when http.noProxy has items', () => { + const httpSettings = workspaceConfiguration({ + proxy: 'https://localhost:8080', + noProxy: ['*.example.com', 'localhost', '127.0.0.1'], + }); + + it('should return true when uri does not match noProxy', () => { + assert.equal(requestShouldBeProxied('http://google.com', httpSettings), true); + assert.equal(requestShouldBeProxied('http://example.com', httpSettings), true); + }); + + it('should return false when uri matches noProxy', () => { + assert.equal(requestShouldBeProxied('http://something.example.com/path', httpSettings), false); + assert.equal(requestShouldBeProxied('http://localhost/path', httpSettings), false); + assert.equal(requestShouldBeProxied('http://127.0.0.1/path', httpSettings), false); + }); + }); + }); +});