http-client.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /**
  2. * HTTP Client using the JSGI standard objects
  3. */
  4. var defer = require("../../promise").defer,
  5. when = require("../../promise").when,
  6. LazyArray = require("../../lazy-array").LazyArray,
  7. http = require("http"),
  8. https = require("https"),
  9. parse = require("url").parse;
  10. // configurable proxy server setting, defaults to http_proxy env var
  11. exports.proxyServer = require("../../process").env.http_proxy;
  12. exports.request = function(originalRequest){
  13. // make a shallow copy of original request object
  14. var request = {};
  15. for(var key in originalRequest){
  16. if(originalRequest.hasOwnProperty(key)){
  17. request[key] = originalRequest[key];
  18. }
  19. }
  20. if(request.timeout === undefined)request.timeout= 20000; // default timeout.
  21. if(request.url){
  22. var parsed = parse(request.url);
  23. if (parsed.pathname) {
  24. parsed.pathInfo = parsed.pathname;
  25. } else {
  26. parsed.pathInfo = "/";
  27. }
  28. request.queryString = parsed.query || "";
  29. for(var i in parsed){
  30. request[i] = parsed[i];
  31. }
  32. }
  33. var deferred = defer();
  34. if(exports.proxyServer){
  35. request.pathname = request.url;
  36. var proxySettings = parse(exports.proxyServer);
  37. request.port = proxySettings.port;
  38. request.protocol = proxySettings.protocol;
  39. request.hostname = proxySettings.hostname;
  40. }
  41. if(!request.protocol){
  42. throw new Error("No valid protocol/URL provided");
  43. }
  44. var timedOut, bodyDeferred;
  45. // Limits the time of sending the request + receiving the response header to 20 seconds.
  46. // No timeout is used on the client stream, but we do destroy the stream if a timeout is reached.
  47. var timeout = setTimeout(function(){
  48. timedOut = true;
  49. req.destroy();
  50. deferred.reject(new Error("Timeout"));
  51. }, request.timeout);
  52. var secure = request.protocol.indexOf("s") > -1;
  53. request.port = request.port || (secure ? 443 : 80);
  54. request.headers = request.headers || {host: request.host || request.hostname + (request.port ? ":" + request.port : "")};
  55. request.host = request.hostname;
  56. request.method = request.method || "GET";
  57. request.path = request.pathname || request.pathInfo || "";
  58. if (request.queryString) {
  59. request.path += "?"+request.queryString;
  60. }
  61. var timedOut;
  62. var req = (secure ? https : http).request(request);
  63. req.on("response", function (response){
  64. if(timedOut){
  65. return;
  66. }
  67. response.status = response.statusCode;
  68. var sendData = function(block){
  69. buffer.push(block);
  70. };
  71. var buffer = [];
  72. bodyDeferred = defer();
  73. var body = response.body = LazyArray({
  74. some: function(callback){
  75. buffer.forEach(callback);
  76. sendData = callback;
  77. return bodyDeferred.promise;
  78. }
  79. });
  80. response.setEncoding(request.encoding || "utf8");
  81. response.on("data", function (chunk) {
  82. sendData(chunk);
  83. });
  84. response.on("end", function(){
  85. bodyDeferred.resolve();
  86. });
  87. deferred.resolve(response);
  88. clearTimeout(timeout);
  89. });
  90. req.on('error', function(e) {
  91. if (!timedOut) {
  92. deferred.reject(e);
  93. clearTimeout(timeout);
  94. }
  95. });
  96. if(request.body){
  97. return when(request.body.forEach(function(block){
  98. req.write(block);
  99. }), function(){
  100. req.end();
  101. return deferred.promise;
  102. });
  103. }else{
  104. req.end();
  105. return deferred.promise;
  106. }
  107. };