Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.js 9.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /* jshint node:true */
  2. 'use strict';
  3. /**
  4. * @fileOverview
  5. * Global proxy settings.
  6. */
  7. var globalTunnel = exports;
  8. exports.constructor = function() {};
  9. var http = require('http');
  10. var https = require('https');
  11. var urlParse = require('url').parse;
  12. var urlStringify = require('url').format;
  13. var pick = require('lodash/pick');
  14. var assign = require('lodash/assign');
  15. var clone = require('lodash/clone');
  16. var tunnel = require('tunnel');
  17. var npmConfig = require('npm-conf');
  18. var encodeUrl = require('encodeurl');
  19. var agents = require('./lib/agents');
  20. exports.agents = agents;
  21. var ENV_VAR_PROXY_SEARCH_ORDER = [
  22. 'https_proxy',
  23. 'HTTPS_PROXY',
  24. 'http_proxy',
  25. 'HTTP_PROXY'
  26. ];
  27. var NPM_CONFIG_PROXY_SEARCH_ORDER = ['https-proxy', 'http-proxy', 'proxy'];
  28. // Save the original settings for restoration later.
  29. var ORIGINALS = {
  30. http: pick(http, 'globalAgent', ['request', 'get']),
  31. https: pick(https, 'globalAgent', ['request', 'get']),
  32. env: pick(process.env, ENV_VAR_PROXY_SEARCH_ORDER)
  33. };
  34. var loggingEnabled =
  35. process &&
  36. process.env &&
  37. process.env.DEBUG &&
  38. process.env.DEBUG.toLowerCase().indexOf('global-tunnel') !== -1 &&
  39. console &&
  40. typeof console.log === 'function';
  41. function log(message) {
  42. if (loggingEnabled) {
  43. console.log('DEBUG global-tunnel: ' + message);
  44. }
  45. }
  46. function resetGlobals() {
  47. assign(http, ORIGINALS.http);
  48. assign(https, ORIGINALS.https);
  49. var val;
  50. for (var key in ORIGINALS.env) {
  51. if (Object.prototype.hasOwnProperty.call(ORIGINALS.env, key)) {
  52. val = ORIGINALS.env[key];
  53. if (val !== null && val !== undefined) {
  54. process.env[key] = val;
  55. }
  56. }
  57. }
  58. }
  59. /**
  60. * Parses the de facto `http_proxy` environment.
  61. */
  62. function tryParse(url) {
  63. if (!url) {
  64. return null;
  65. }
  66. var parsed = urlParse(url);
  67. return {
  68. protocol: parsed.protocol,
  69. host: parsed.hostname,
  70. port: parseInt(parsed.port, 10),
  71. proxyAuth: parsed.auth
  72. };
  73. }
  74. // Stringifies the normalized parsed config
  75. function stringifyProxy(conf) {
  76. return encodeUrl(
  77. urlStringify({
  78. protocol: conf.protocol,
  79. hostname: conf.host,
  80. port: conf.port,
  81. auth: conf.proxyAuth
  82. })
  83. );
  84. }
  85. globalTunnel.isProxying = false;
  86. globalTunnel.proxyUrl = null;
  87. globalTunnel.proxyConfig = null;
  88. function findEnvVarProxy() {
  89. var i;
  90. var key;
  91. var val;
  92. var result;
  93. for (i = 0; i < ENV_VAR_PROXY_SEARCH_ORDER.length; i++) {
  94. key = ENV_VAR_PROXY_SEARCH_ORDER[i];
  95. val = process.env[key];
  96. if (val !== null && val !== undefined) {
  97. // Get the first non-empty
  98. result = result || val;
  99. // Delete all
  100. // NB: we do it here to prevent double proxy handling (and for example path change)
  101. // by us and the `request` module or other sub-dependencies
  102. delete process.env[key];
  103. log('Found proxy in environment variable ' + ENV_VAR_PROXY_SEARCH_ORDER[i]);
  104. }
  105. }
  106. if (!result) {
  107. // __GLOBAL_TUNNEL_DEPENDENCY_NPMCONF__ is a hook to override the npm-conf module
  108. var config =
  109. (global.__GLOBAL_TUNNEL_DEPENDENCY_NPMCONF__ &&
  110. global.__GLOBAL_TUNNEL_DEPENDENCY_NPMCONF__()) ||
  111. npmConfig();
  112. for (i = 0; i < NPM_CONFIG_PROXY_SEARCH_ORDER.length && !val; i++) {
  113. val = config.get(NPM_CONFIG_PROXY_SEARCH_ORDER[i]);
  114. }
  115. if (val) {
  116. log('Found proxy in npm config ' + NPM_CONFIG_PROXY_SEARCH_ORDER[i]);
  117. result = val;
  118. }
  119. }
  120. return result;
  121. }
  122. /**
  123. * Overrides the node http/https `globalAgent`s to use the configured proxy.
  124. *
  125. * If the config is empty, the `http_proxy` environment variable is checked.
  126. * If that's not present, the NPM `http-proxy` configuration is checked.
  127. * If neither are present no proxying will be enabled.
  128. *
  129. * @param {object} conf - Options
  130. * @param {string} conf.host - Hostname or IP of the HTTP proxy to use
  131. * @param {int} conf.port - TCP port of the proxy
  132. * @param {string} [conf.protocol='http'] - The protocol of the proxy, 'http' or 'https'
  133. * @param {string} [conf.proxyAuth] - Credentials for the proxy in the form userId:password
  134. * @param {string} [conf.connect='https'] - Which protocols will use the CONNECT method 'neither', 'https' or 'both'
  135. * @param {int} [conf.sockets=5] Maximum number of TCP sockets to use in each pool. There are two different pools for HTTP and HTTPS
  136. * @param {object} [conf.httpsOptions] - HTTPS options
  137. */
  138. globalTunnel.initialize = function(conf) {
  139. // Don't do anything if already proxying.
  140. // To change the settings `.end()` should be called first.
  141. if (globalTunnel.isProxying) {
  142. log('Already proxying');
  143. return;
  144. }
  145. try {
  146. // This has an effect of also removing the proxy config
  147. // from the global env to prevent other modules (like request) doing
  148. // double handling
  149. var envVarProxy = findEnvVarProxy();
  150. if (conf && typeof conf === 'string') {
  151. // Passed string - parse it as a URL
  152. conf = tryParse(conf);
  153. } else if (conf) {
  154. // Passed object - take it but clone for future mutations
  155. conf = clone(conf);
  156. } else if (envVarProxy) {
  157. // Nothing passed - parse from the env
  158. conf = tryParse(envVarProxy);
  159. } else {
  160. log('No configuration found, not proxying');
  161. // No config - do nothing
  162. return;
  163. }
  164. log('Proxy configuration to be used is ' + JSON.stringify(conf, null, 2));
  165. if (!conf.host) {
  166. throw new Error('upstream proxy host is required');
  167. }
  168. if (!conf.port) {
  169. throw new Error('upstream proxy port is required');
  170. }
  171. if (conf.protocol === undefined) {
  172. conf.protocol = 'http:'; // Default to proxy speaking http
  173. }
  174. if (!/:$/.test(conf.protocol)) {
  175. conf.protocol += ':';
  176. }
  177. if (!conf.connect) {
  178. conf.connect = 'https'; // Just HTTPS by default
  179. }
  180. if (['both', 'neither', 'https'].indexOf(conf.connect) < 0) {
  181. throw new Error('valid connect options are "neither", "https", or "both"');
  182. }
  183. var connectHttp = conf.connect === 'both';
  184. var connectHttps = conf.connect !== 'neither';
  185. if (conf.httpsOptions) {
  186. conf.innerHttpsOpts = conf.httpsOptions;
  187. conf.outerHttpsOpts = conf.innerHttpsOpts;
  188. }
  189. http.globalAgent = globalTunnel._makeAgent(conf, 'http', connectHttp);
  190. https.globalAgent = globalTunnel._makeAgent(conf, 'https', connectHttps);
  191. http.request = globalTunnel._makeHttp('request', http, 'http');
  192. https.request = globalTunnel._makeHttp('request', https, 'https');
  193. http.get = globalTunnel._makeHttp('get', http, 'http');
  194. https.get = globalTunnel._makeHttp('get', https, 'https');
  195. globalTunnel.isProxying = true;
  196. globalTunnel.proxyUrl = stringifyProxy(conf);
  197. globalTunnel.proxyConfig = clone(conf);
  198. } catch (e) {
  199. resetGlobals();
  200. throw e;
  201. }
  202. };
  203. var _makeAgent = function(conf, innerProtocol, useCONNECT) {
  204. log('Creating proxying agent');
  205. var outerProtocol = conf.protocol;
  206. innerProtocol += ':';
  207. var opts = {
  208. proxy: pick(conf, 'host', 'port', 'protocol', 'localAddress', 'proxyAuth'),
  209. maxSockets: conf.sockets
  210. };
  211. opts.proxy.innerProtocol = innerProtocol;
  212. if (useCONNECT) {
  213. if (conf.proxyHttpsOptions) {
  214. assign(opts.proxy, conf.proxyHttpsOptions);
  215. }
  216. if (conf.originHttpsOptions) {
  217. assign(opts, conf.originHttpsOptions);
  218. }
  219. if (outerProtocol === 'https:') {
  220. if (innerProtocol === 'https:') {
  221. return tunnel.httpsOverHttps(opts);
  222. }
  223. return tunnel.httpOverHttps(opts);
  224. }
  225. if (innerProtocol === 'https:') {
  226. return tunnel.httpsOverHttp(opts);
  227. }
  228. return tunnel.httpOverHttp(opts);
  229. }
  230. if (conf.originHttpsOptions) {
  231. throw new Error('originHttpsOptions must be combined with a tunnel:true option');
  232. }
  233. if (conf.proxyHttpsOptions) {
  234. // NB: not opts.
  235. assign(opts, conf.proxyHttpsOptions);
  236. }
  237. if (outerProtocol === 'https:') {
  238. return new agents.OuterHttpsAgent(opts);
  239. }
  240. return new agents.OuterHttpAgent(opts);
  241. };
  242. /**
  243. * Construct an agent based on:
  244. * - is the connection to the proxy secure?
  245. * - is the connection to the origin secure?
  246. * - the address of the proxy
  247. */
  248. globalTunnel._makeAgent = function(conf, innerProtocol, useCONNECT) {
  249. var agent = _makeAgent(conf, innerProtocol, useCONNECT);
  250. // Set the protocol to match that of the target request type
  251. agent.protocol = innerProtocol + ':';
  252. return agent;
  253. };
  254. /**
  255. * Override for http/https, makes sure to default the agent
  256. * to the global agent. Due to how node implements it in lib/http.js, the
  257. * globalAgent we define won't get used (node uses a module-scoped variable,
  258. * not the exports field).
  259. * @param {string} method 'request' or 'get', http/https methods
  260. * @param {string|object} options http/https request url or options
  261. * @param {function} [cb]
  262. * @private
  263. */
  264. globalTunnel._makeHttp = function(method, httpOrHttps, protocol) {
  265. return function(options, callback) {
  266. if (typeof options === 'string') {
  267. options = urlParse(options);
  268. } else {
  269. options = clone(options);
  270. }
  271. // Respect the default agent provided by node's lib/https.js
  272. if (
  273. (options.agent === null || options.agent === undefined) &&
  274. typeof options.createConnection !== 'function' &&
  275. (options.host || options.hostname)
  276. ) {
  277. options.agent = options._defaultAgent || httpOrHttps.globalAgent;
  278. }
  279. // Set the default port ourselves to prevent Node doing it based on the proxy agent protocol
  280. if (options.protocol === 'https:' || (!options.protocol && protocol === 'https')) {
  281. options.port = options.port || 443;
  282. }
  283. if (options.protocol === 'http:' || (!options.protocol && protocol === 'http')) {
  284. options.port = options.port || 80;
  285. }
  286. log(
  287. 'Requesting to ' +
  288. (options.protocol || protocol) +
  289. '//' +
  290. (options.host || options.hostname) +
  291. ':' +
  292. options.port
  293. );
  294. return ORIGINALS[protocol][method].call(httpOrHttps, options, callback);
  295. };
  296. };
  297. /**
  298. * Restores global http/https agents.
  299. */
  300. globalTunnel.end = function() {
  301. resetGlobals();
  302. globalTunnel.isProxying = false;
  303. globalTunnel.proxyUrl = null;
  304. globalTunnel.proxyConfig = null;
  305. };