diff --git a/package-lock.json b/package-lock.json index 3dfbbd66..350c23ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,21 +34,11 @@ "dev": true }, "agent-base": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", - "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", - "dev": true, + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.0.tgz", + "integrity": "sha512-c+R/U5X+2zz2+UCrCFv6odQzJdoqI+YecuhnAJLa1zYaMc13zPfwMwZrr91Pd1DYNo/yPRbiM4WVf9whgwFsIg==", "requires": { - "extend": "3.0.1", - "semver": "5.0.3" - }, - "dependencies": { - "semver": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", - "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", - "dev": true - } + "es6-promisify": "5.0.0" } }, "ajv": { @@ -595,6 +585,21 @@ "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=", "dev": true }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "requires": { + "es6-promise": "4.2.4" + }, + "dependencies": { + "es6-promise": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", + "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==" + } + } + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -1193,14 +1198,22 @@ } }, "https-proxy-agent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", - "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", - "dev": true, + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.0.tgz", + "integrity": "sha512-uUWcfXHvy/dwfM9bqa6AozvAjS32dZSTUYd/4SEpYKRg6LEcPLshksnQYRudM9AyNvUARMfAg5TLjUDyX/K4vA==", "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1" + "agent-base": "4.2.0", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } } }, "iconv-lite": { @@ -2225,8 +2238,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "mute-stream": { "version": "0.0.7", @@ -2745,6 +2757,35 @@ "https-proxy-agent": "1.0.0", "lodash": "4.17.4", "rimraf": "2.6.2" + }, + "dependencies": { + "agent-base": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", + "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", + "dev": true, + "requires": { + "extend": "3.0.1", + "semver": "5.0.3" + } + }, + "https-proxy-agent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", + "dev": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1" + } + }, + "semver": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", + "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", + "dev": true + } } }, "sax": { diff --git a/package.json b/package.json index 44b4be05..e4916ab5 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,8 @@ "http_ece": "1.0.5", "jws": "^3.1.3", "minimist": "^1.2.0", - "urlsafe-base64": "^1.0.0" + "urlsafe-base64": "^1.0.0", + "https-proxy-agent": "^2.1.1" }, "devDependencies": { "chalk": "^2.3.0", diff --git a/src/web-push-lib.js b/src/web-push-lib.js index 61dbada0..f83d1d8f 100644 --- a/src/web-push-lib.js +++ b/src/web-push-lib.js @@ -3,6 +3,7 @@ const urlBase64 = require('urlsafe-base64'); const url = require('url'); const https = require('https'); +const HttpsProxyAgent = require('https-proxy-agent'); const WebPushError = require('./web-push-error.js'); const vapidHelper = require('./vapid-helper.js'); @@ -109,6 +110,7 @@ WebPushLib.prototype.generateRequestDetails = let timeToLive = DEFAULT_TTL; let extraHeaders = {}; let contentEncoding = webPushConstants.supportedContentEncodings.AES_GCM; + let proxy; if (options) { const validOptionKeys = [ @@ -116,7 +118,8 @@ WebPushLib.prototype.generateRequestDetails = 'gcmAPIKey', 'vapidDetails', 'TTL', - 'contentEncoding' + 'contentEncoding', + 'proxy' ]; const optionKeys = Object.keys(options); for (let i = 0; i < optionKeys.length; i += 1) { @@ -162,6 +165,14 @@ WebPushLib.prototype.generateRequestDetails = throw new Error('Unsupported content encoding specified.'); } } + + if (options.proxy) { + if (typeof options.proxy === 'string') { + proxy = options.proxy; + } else { + console.warn('Attempt to use proxy option, but invalid type it should be a string '); + } + } } if (typeof timeToLive === 'undefined') { @@ -250,6 +261,10 @@ WebPushLib.prototype.generateRequestDetails = requestDetails.body = requestPayload; requestDetails.endpoint = subscription.endpoint; + if (proxy) { + requestDetails.proxy = proxy; + } + return requestDetails; }; @@ -286,6 +301,10 @@ WebPushLib.prototype.sendNotification = httpsOptions.headers = requestDetails.headers; httpsOptions.method = requestDetails.method; + if (requestDetails.proxy) { + httpsOptions.agent = new HttpsProxyAgent(requestDetails.proxy); + } + const pushRequest = https.request(httpsOptions, function(pushResponse) { let responseText = ''; diff --git a/test/test-generate-request-details.js b/test/test-generate-request-details.js index 0420fad0..17fabdf8 100644 --- a/test/test-generate-request-details.js +++ b/test/test-generate-request-details.js @@ -271,4 +271,18 @@ suite('Test Generate Request Details', function() { assert.ok(audience, 'Audience exists'); assert.equal(audience, 'http://example.com:4242', 'Audience contains expected value with port'); }); + + test('Proxy option', function() { + let subscription = { endpoint: 'https://127.0.0.1:8080' }; + let message; + let extraOptions = { + 'proxy': 'proxy' + }; + let details = webPush.generateRequestDetails( + subscription, + message, + extraOptions + ); + assert.equal(details.proxy, extraOptions.proxy); + }); });