headers_spec.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. var http = require('http'),
  2. helpers = require('./helpers'),
  3. should = require('should');
  4. var port = 54321;
  5. describe('request headers', function() {
  6. var needle,
  7. server,
  8. existing_sockets,
  9. original_defaultMaxSockets;
  10. before(function(done) {
  11. setTimeout(function() {
  12. existing_sockets = get_active_sockets().length;
  13. server = helpers.server({ port: port }, done);
  14. }, 100);
  15. })
  16. after(function(done) {
  17. server.close(done);
  18. })
  19. function send_request(opts, cb) {
  20. needle.get('http://localhost:' + port, opts, cb);
  21. }
  22. function get_active_sockets() {
  23. var handles = process._getActiveHandles();
  24. return handles.filter(function(el) {
  25. if (el.constructor.name.toString() == 'Socket') {
  26. return el.destroyed !== true;
  27. }
  28. })
  29. }
  30. describe('old node versions (<0.11.4) with persistent keep-alive connections', function() {
  31. // emulate old node behaviour
  32. before(function() {
  33. delete require.cache[require.resolve('..')] // in case it was already loaded
  34. original_defaultMaxSockets = http.Agent.defaultMaxSockets;
  35. http.Agent.defaultMaxSockets = 5;
  36. needle = require('..');
  37. })
  38. after(function() {
  39. http.Agent.defaultMaxSockets = original_defaultMaxSockets;
  40. delete require.cache[require.resolve('..')]
  41. })
  42. describe('default options', function() {
  43. it('sends a Connection: close header', function(done) {
  44. send_request({}, function(err, resp) {
  45. resp.body.headers['connection'].should.eql('close');
  46. done();
  47. })
  48. })
  49. it('no open sockets remain after request', function(done) {
  50. send_request({}, function(err, resp) {
  51. setTimeout(function() {
  52. get_active_sockets().length.should.eql(existing_sockets);
  53. done();
  54. }, 10)
  55. });
  56. })
  57. })
  58. describe('passing connection: close', function() {
  59. it('sends a Connection: close header', function(done) {
  60. send_request({ connection: 'close' }, function(err, resp) {
  61. resp.body.headers['connection'].should.eql('close');
  62. done();
  63. })
  64. })
  65. it('no open sockets remain after request', function(done) {
  66. send_request({ connection: 'close' }, function(err, resp) {
  67. setTimeout(function() {
  68. get_active_sockets().length.should.eql(existing_sockets);
  69. done();
  70. }, 10)
  71. });
  72. })
  73. })
  74. describe('passing connection: keep-alive', function() {
  75. it('sends a Connection: keep-alive header (using options.headers.connection)', function(done) {
  76. send_request({ headers: { connection: 'keep-alive' }}, function(err, resp) {
  77. resp.body.headers['connection'].should.eql('keep-alive');
  78. done();
  79. })
  80. })
  81. it('sends a Connection: keep-alive header (using options.connection)', function(done) {
  82. send_request({ connection: 'keep-alive' }, function(err, resp) {
  83. resp.body.headers['connection'].should.eql('keep-alive');
  84. done();
  85. })
  86. })
  87. it('one open socket remain after request', function(done) {
  88. send_request({ connection: 'keep-alive' }, function(err, resp) {
  89. get_active_sockets().length.should.eql(existing_sockets + 1);
  90. done();
  91. });
  92. })
  93. })
  94. })
  95. describe('new node versions with smarter connection disposing', function() {
  96. before(function() {
  97. delete require.cache[require.resolve('..')]
  98. original_defaultMaxSockets = http.Agent.defaultMaxSockets;
  99. http.Agent.defaultMaxSockets = Infinity;
  100. needle = require('..');
  101. })
  102. after(function() {
  103. http.Agent.defaultMaxSockets = original_defaultMaxSockets;
  104. delete require.cache[require.resolve('..')]
  105. })
  106. describe('default options', function() {
  107. var node_major_ver = process.version.split('.')[0].replace('v', '');
  108. if (parseInt(node_major_ver) >= 4) {
  109. it('sets Connection header to close (> v4)', function(done) {
  110. send_request({}, function(err, resp) {
  111. resp.body.headers['connection'].should.eql('close');
  112. done()
  113. })
  114. })
  115. } else {
  116. it('sets Connection header to keep-alive (< v4)', function(done) {
  117. send_request({}, function(err, resp) {
  118. resp.body.headers['connection'].should.eql('keep-alive');
  119. done();
  120. })
  121. })
  122. }
  123. if (parseInt(node_major_ver) >= 14) {
  124. // TODO: figure out why this happens
  125. it('two open sockets remains after request (>= v14)', function(done) {
  126. send_request({}, function(err, resp) {
  127. get_active_sockets().length.should.eql(existing_sockets + 2);
  128. done();
  129. });
  130. })
  131. } else if (parseInt(node_major_ver) >= 8 || parseInt(node_major_ver) == 0) {
  132. it('one open socket remains after request (> v8 && v0.10)', function(done) {
  133. send_request({}, function(err, resp) {
  134. get_active_sockets().length.should.eql(existing_sockets + 1);
  135. done();
  136. });
  137. })
  138. } else {
  139. it('no open sockets remain after request (> v0.10 && < v8)', function(done) {
  140. send_request({}, function(err, resp) {
  141. get_active_sockets().length.should.eql(existing_sockets);
  142. done();
  143. });
  144. })
  145. }
  146. })
  147. describe('passing connection: close', function() {
  148. it('sends a Connection: close header', function(done) {
  149. send_request({ connection: 'close' }, function(err, resp) {
  150. resp.body.headers['connection'].should.eql('close');
  151. done();
  152. })
  153. })
  154. it('no open sockets remain after request', function(done) {
  155. send_request({ connection: 'close' }, function(err, resp) {
  156. setTimeout(function() {
  157. get_active_sockets().length.should.eql(existing_sockets);
  158. done();
  159. }, 10);
  160. });
  161. })
  162. })
  163. describe('passing connection: keep-alive', function() {
  164. it('sends a Connection: keep-alive header (using options.headers.connection)', function(done) {
  165. send_request({ headers: { connection: 'keep-alive' }}, function(err, resp) {
  166. resp.body.headers['connection'].should.eql('keep-alive');
  167. done();
  168. })
  169. })
  170. it('sends a Connection: keep-alive header (using options.connection)', function(done) {
  171. send_request({ connection: 'keep-alive' }, function(err, resp) {
  172. resp.body.headers['connection'].should.eql('keep-alive');
  173. done();
  174. })
  175. })
  176. it('one open socket remain after request', function(done) {
  177. send_request({ connection: 'keep-alive' }, function(err, resp) {
  178. get_active_sockets().length.should.eql(existing_sockets + 1);
  179. done();
  180. });
  181. })
  182. })
  183. })
  184. describe('using shared keep-alive agent', function() {
  185. before(function() {
  186. needle.defaults({ agent: http.Agent({ keepAlive: true }) })
  187. })
  188. after(function() {
  189. needle.defaults().agent.destroy(); // close existing connections
  190. needle.defaults({ agent: null }); // and reset default value
  191. })
  192. describe('default options', function() {
  193. it('sends a Connection: keep-alive header', function(done) {
  194. send_request({}, function(err, resp) {
  195. resp.body.headers['connection'].should.eql('keep-alive');
  196. done();
  197. })
  198. })
  199. it('one open socket remain after request', function(done) {
  200. send_request({ connection: 'keep-alive' }, function(err, resp) {
  201. setTimeout(function() {
  202. get_active_sockets().length.should.eql(existing_sockets + 1);
  203. done();
  204. }, 10);
  205. });
  206. })
  207. })
  208. describe('passing connection: close', function() {
  209. it('sends a Connection: close header', function(done) {
  210. send_request({ connection: 'close' }, function(err, resp) {
  211. resp.body.headers['connection'].should.eql('close');
  212. done();
  213. })
  214. })
  215. it('no open sockets remain after request', function(done) {
  216. send_request({ connection: 'close' }, function(err, resp) {
  217. setTimeout(function() {
  218. get_active_sockets().length.should.eql(existing_sockets);
  219. done();
  220. }, 10)
  221. });
  222. })
  223. })
  224. describe('passing connection: keep-alive', function() {
  225. it('sends a Connection: keep-alive header (using options.headers.connection)', function(done) {
  226. send_request({ headers: { connection: 'keep-alive' }}, function(err, resp) {
  227. resp.body.headers['connection'].should.eql('keep-alive');
  228. done();
  229. })
  230. })
  231. it('sends a Connection: keep-alive header (using options.connection)', function(done) {
  232. send_request({ connection: 'keep-alive' }, function(err, resp) {
  233. resp.body.headers['connection'].should.eql('keep-alive');
  234. done();
  235. })
  236. })
  237. it('one open socket remain after request', function(done) {
  238. send_request({ connection: 'keep-alive' }, function(err, resp) {
  239. setTimeout(function() {
  240. get_active_sockets().length.should.eql(existing_sockets + 1);
  241. done();
  242. }, 10);
  243. })
  244. })
  245. })
  246. })
  247. })