index.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /**
  2. * Module dependencies.
  3. */
  4. var co = require('co');
  5. var vm = require('vm');
  6. var thunkify = require('thunkify');
  7. var degenerator = require('degenerator');
  8. /**
  9. * Built-in PAC functions.
  10. */
  11. var dateRange = require('./dateRange');
  12. var dnsDomainIs = require('./dnsDomainIs');
  13. var dnsDomainLevels = require('./dnsDomainLevels');
  14. var dnsResolve = require('./dnsResolve');
  15. var isInNet = require('./isInNet');
  16. var isPlainHostName = require('./isPlainHostName');
  17. var isResolvable = require('./isResolvable');
  18. var localHostOrDomainIs = require('./localHostOrDomainIs');
  19. var myIpAddress = require('./myIpAddress');
  20. var shExpMatch = require('./shExpMatch');
  21. var timeRange = require('./timeRange');
  22. var weekdayRange = require('./weekdayRange');
  23. /**
  24. * Module exports.
  25. */
  26. module.exports = generate;
  27. /**
  28. * Returns an asyncronous `FindProxyForURL` function from the
  29. * given JS string (from a PAC file).
  30. *
  31. * @param {String} str JS string
  32. * @param {Object} opts optional "options" object
  33. * @return {Function} async resolver function
  34. */
  35. function generate (str, opts) {
  36. var i;
  37. // the sandbox to use for the vm
  38. var sandbox = {
  39. dateRange: dateRange,
  40. dnsDomainIs: dnsDomainIs,
  41. dnsDomainLevels: dnsDomainLevels,
  42. dnsResolve: dnsResolve,
  43. isInNet: isInNet,
  44. isPlainHostName: isPlainHostName,
  45. isResolvable: isResolvable,
  46. localHostOrDomainIs: localHostOrDomainIs,
  47. myIpAddress: myIpAddress,
  48. shExpMatch: shExpMatch,
  49. timeRange: timeRange,
  50. weekdayRange: weekdayRange
  51. };
  52. // copy the properties from the user-provided `sandbox` onto ours
  53. if (opts && opts.sandbox) {
  54. for (i in opts.sandbox) {
  55. sandbox[i] = opts.sandbox[i];
  56. }
  57. }
  58. // construct the array of async function names to add `yield` calls to.
  59. // user-provided async functions added to the `sandbox` must have an
  60. // `async = true` property set on the function instance
  61. var names = [];
  62. for (i in sandbox) {
  63. if (sandbox[i].async) {
  64. names.push(i);
  65. sandbox[i] = thunkify(sandbox[i]);
  66. }
  67. }
  68. //console.log(names);
  69. // convert the JS FindProxyForURL function into a generator function
  70. var js = degenerator(str, names);
  71. // filename of the pac file for the vm
  72. var filename = opts && opts.filename ? opts.filename : 'proxy.pac';
  73. // evaluate the JS string and extract the FindProxyForURL generator function
  74. var fn = vm.runInNewContext(js + ';FindProxyForURL', sandbox, filename);
  75. if ('function' != typeof fn) {
  76. throw new TypeError('PAC file JavaScript contents must define a `FindProxyForURL` function');
  77. }
  78. // return the async resolver function
  79. var resolver = co(fn);
  80. return function FindProxyForURL (url, host, fn) {
  81. resolver(url, host, fn);
  82. };
  83. }