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 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /**
  2. * Module dependencies.
  3. */
  4. var proxyAgent = require('proxy-agent');
  5. var debug = require('debug')('superagent-proxy');
  6. /**
  7. * Module exports.
  8. */
  9. module.exports = setup;
  10. /**
  11. * Adds a `.proxy(uri)` function to the "superagent" module's Request class.
  12. *
  13. * ``` js
  14. * var request = require('superagent');
  15. * require('superagent-proxy')(request);
  16. *
  17. * request
  18. * .get(uri)
  19. * .proxy(uri)
  20. * .end(fn);
  21. * ```
  22. *
  23. * Or, you can pass in a `superagent.Request` instance, and it's like calling the
  24. * `.proxy(uri)` function on it, but without extending the prototype:
  25. *
  26. * ``` js
  27. * var request = require('superagent');
  28. * var proxy = require('superagent-proxy');
  29. *
  30. * proxy(request.get(uri), uri).end(fn);
  31. * ```
  32. *
  33. * @param {Object} superagent The `superagent` exports object
  34. * @api public
  35. */
  36. function setup (superagent, uri) {
  37. var Request = superagent.Request;
  38. if (Request) {
  39. // the superagent exports object - extent Request with "proxy"
  40. Request.prototype.proxy = proxy;
  41. return superagent;
  42. } else {
  43. // assume it's a `superagent.Request` instance
  44. return proxy.call(superagent, uri);
  45. }
  46. }
  47. /**
  48. * Sets the proxy server to use for this HTTP(s) request.
  49. *
  50. * @param {String} uri proxy url
  51. * @api public
  52. */
  53. function proxy (uri) {
  54. debug('Request#proxy(%o)', uri);
  55. // we need to observe the `url` field from now on... Superagent sometimes
  56. // re-uses the `req` instance but changes its `url` field (i.e. in the case of
  57. // a redirect), so when that happens we need to potentially re-set the proxy
  58. // agent
  59. setupUrl(this);
  60. // attempt to get a proxying `http.Agent` instance
  61. var agent = proxyAgent(uri);
  62. // if we have an `http.Agent` instance then call the .agent() function
  63. if (agent) this.agent(agent);
  64. // store the proxy URI in case of changes to the `url` prop in the future
  65. this._proxyUri = uri;
  66. return this;
  67. }
  68. /**
  69. * Sets up a get/set descriptor for the `url` property of the provided `req`
  70. * Request instance. This is so that we can re-run the "proxy agent" logic when
  71. * the `url` field is changed, i.e. during a 302 Redirect scenario.
  72. *
  73. * @api private
  74. */
  75. function setupUrl (req) {
  76. var desc = Object.getOwnPropertyDescriptor(req, 'url');
  77. if (desc.get == getUrl && desc.set == setUrl) return; // already patched
  78. // save current value
  79. req._url = req.url;
  80. desc.get = getUrl;
  81. desc.set = setUrl;
  82. delete desc.value;
  83. delete desc.writable;
  84. Object.defineProperty(req, 'url', desc);
  85. debug('patched superagent Request "url" property for changes');
  86. }
  87. /**
  88. * `url` property getter.
  89. *
  90. * @api protected
  91. */
  92. function getUrl () {
  93. return this._url;
  94. }
  95. /**
  96. * `url` property setter.
  97. *
  98. * @api protected
  99. */
  100. function setUrl (v) {
  101. debug('set `.url`: %o', v);
  102. this._url = v;
  103. proxy.call(this, this._proxyUri);
  104. }