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.

Agent.js.flow 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. // @flow
  2. import {
  3. serializeError,
  4. } from 'serialize-error';
  5. import {
  6. boolean,
  7. } from 'boolean';
  8. import Logger from '../Logger';
  9. import type {
  10. AgentType,
  11. GetUrlProxyMethodType,
  12. IsProxyConfiguredMethodType,
  13. MustUrlUseProxyMethodType,
  14. ProtocolType,
  15. } from '../types';
  16. const log = Logger.child({
  17. namespace: 'Agent',
  18. });
  19. let requestId = 0;
  20. class Agent {
  21. defaultPort: number;
  22. protocol: ProtocolType;
  23. fallbackAgent: AgentType;
  24. isProxyConfigured: IsProxyConfiguredMethodType;
  25. mustUrlUseProxy: MustUrlUseProxyMethodType;
  26. getUrlProxy: GetUrlProxyMethodType;
  27. socketConnectionTimeout: number;
  28. constructor (
  29. isProxyConfigured: IsProxyConfiguredMethodType,
  30. mustUrlUseProxy: MustUrlUseProxyMethodType,
  31. getUrlProxy: GetUrlProxyMethodType,
  32. fallbackAgent: AgentType,
  33. socketConnectionTimeout: number,
  34. ) {
  35. this.fallbackAgent = fallbackAgent;
  36. this.isProxyConfigured = isProxyConfigured;
  37. this.mustUrlUseProxy = mustUrlUseProxy;
  38. this.getUrlProxy = getUrlProxy;
  39. this.socketConnectionTimeout = socketConnectionTimeout;
  40. }
  41. addRequest (request: *, configuration: *) {
  42. let requestUrl;
  43. // It is possible that addRequest was constructed for a proxied request already, e.g.
  44. // "request" package does this when it detects that a proxy should be used
  45. // https://github.com/request/request/blob/212570b6971a732b8dd9f3c73354bcdda158a737/request.js#L402
  46. // https://gist.github.com/gajus/e2074cd3b747864ffeaabbd530d30218
  47. if (request.path.startsWith('http://') || request.path.startsWith('https://')) {
  48. requestUrl = request.path;
  49. } else {
  50. requestUrl = this.protocol + '//' + (configuration.hostname || configuration.host) + (configuration.port === 80 || configuration.port === 443 ? '' : ':' + configuration.port) + request.path;
  51. }
  52. if (!this.isProxyConfigured()) {
  53. log.trace({
  54. destination: requestUrl,
  55. }, 'not proxying request; GLOBAL_AGENT.HTTP_PROXY is not configured');
  56. // $FlowFixMe It appears that Flow is missing the method description.
  57. this.fallbackAgent.addRequest(request, configuration);
  58. return;
  59. }
  60. if (!this.mustUrlUseProxy(requestUrl)) {
  61. log.trace({
  62. destination: requestUrl,
  63. }, 'not proxying request; url matches GLOBAL_AGENT.NO_PROXY');
  64. // $FlowFixMe It appears that Flow is missing the method description.
  65. this.fallbackAgent.addRequest(request, configuration);
  66. return;
  67. }
  68. const currentRequestId = requestId++;
  69. const proxy = this.getUrlProxy(requestUrl);
  70. if (this.protocol === 'http:') {
  71. request.path = requestUrl;
  72. if (proxy.authorization) {
  73. request.setHeader('proxy-authorization', 'Basic ' + Buffer.from(proxy.authorization).toString('base64'));
  74. }
  75. }
  76. log.trace({
  77. destination: requestUrl,
  78. proxy: 'http://' + proxy.hostname + ':' + proxy.port,
  79. requestId: currentRequestId,
  80. }, 'proxying request');
  81. request.on('error', (error) => {
  82. log.error({
  83. error: serializeError(error),
  84. }, 'request error');
  85. });
  86. request.once('response', (response) => {
  87. log.trace({
  88. headers: response.headers,
  89. requestId: currentRequestId,
  90. statusCode: response.statusCode,
  91. }, 'proxying response');
  92. });
  93. request.shouldKeepAlive = false;
  94. const connectionConfiguration = {
  95. host: configuration.hostname || configuration.host,
  96. port: configuration.port || 80,
  97. proxy,
  98. tls: {},
  99. };
  100. // add optional tls options for https requests.
  101. // @see https://nodejs.org/docs/latest-v12.x/api/https.html#https_https_request_url_options_callback :
  102. // > The following additional options from tls.connect()
  103. // > - https://nodejs.org/docs/latest-v12.x/api/tls.html#tls_tls_connect_options_callback -
  104. // > are also accepted:
  105. // > ca, cert, ciphers, clientCertEngine, crl, dhparam, ecdhCurve, honorCipherOrder,
  106. // > key, passphrase, pfx, rejectUnauthorized, secureOptions, secureProtocol, servername, sessionIdContext.
  107. if (this.protocol === 'https:') {
  108. connectionConfiguration.tls = {
  109. ca: configuration.ca,
  110. cert: configuration.cert,
  111. ciphers: configuration.ciphers,
  112. clientCertEngine: configuration.clientCertEngine,
  113. crl: configuration.crl,
  114. dhparam: configuration.dhparam,
  115. ecdhCurve: configuration.ecdhCurve,
  116. honorCipherOrder: configuration.honorCipherOrder,
  117. key: configuration.key,
  118. passphrase: configuration.passphrase,
  119. pfx: configuration.pfx,
  120. rejectUnauthorized: configuration.rejectUnauthorized,
  121. secureOptions: configuration.secureOptions,
  122. secureProtocol: configuration.secureProtocol,
  123. servername: configuration.servername || connectionConfiguration.host,
  124. sessionIdContext: configuration.sessionIdContext,
  125. };
  126. // This is not ideal because there is no way to override this setting using `tls` configuration if `NODE_TLS_REJECT_UNAUTHORIZED=0`.
  127. // However, popular HTTP clients (such as https://github.com/sindresorhus/got) come with pre-configured value for `rejectUnauthorized`,
  128. // which makes it impossible to override that value globally and respect `rejectUnauthorized` for specific requests only.
  129. //
  130. // eslint-disable-next-line no-process-env
  131. if (typeof process.env.NODE_TLS_REJECT_UNAUTHORIZED === 'string' && boolean(process.env.NODE_TLS_REJECT_UNAUTHORIZED) === false) {
  132. connectionConfiguration.tls.rejectUnauthorized = false;
  133. }
  134. }
  135. // $FlowFixMe It appears that Flow is missing the method description.
  136. this.createConnection(connectionConfiguration, (error, socket) => {
  137. log.trace({
  138. target: connectionConfiguration,
  139. }, 'connecting');
  140. // @see https://github.com/nodejs/node/issues/5757#issuecomment-305969057
  141. if (socket) {
  142. socket.setTimeout(this.socketConnectionTimeout, () => {
  143. socket.destroy();
  144. });
  145. socket.once('connect', () => {
  146. log.trace({
  147. target: connectionConfiguration,
  148. }, 'connected');
  149. socket.setTimeout(0);
  150. });
  151. socket.once('secureConnect', () => {
  152. log.trace({
  153. target: connectionConfiguration,
  154. }, 'connected (secure)');
  155. socket.setTimeout(0);
  156. });
  157. }
  158. if (error) {
  159. request.emit('error', error);
  160. } else {
  161. log.debug('created socket');
  162. socket.on('error', (socketError) => {
  163. log.error({
  164. error: serializeError(socketError),
  165. }, 'socket error');
  166. });
  167. request.onSocket(socket);
  168. }
  169. });
  170. }
  171. }
  172. export default Agent;