httpserver.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // Licensed to the Software Freedom Conservancy (SFC) under one
  2. // or more contributor license agreements. See the NOTICE file
  3. // distributed with this work for additional information
  4. // regarding copyright ownership. The SFC licenses this file
  5. // to you under the Apache License, Version 2.0 (the
  6. // "License"); you may not use this file except in compliance
  7. // with the License. You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing,
  12. // software distributed under the License is distributed on an
  13. // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  14. // KIND, either express or implied. See the License for the
  15. // specific language governing permissions and limitations
  16. // under the License.
  17. 'use strict';
  18. var assert = require('assert'),
  19. http = require('http'),
  20. url = require('url');
  21. var net = require('../../net'),
  22. portprober = require('../../net/portprober'),
  23. promise = require('../..').promise;
  24. /**
  25. * Encapsulates a simple HTTP server for testing. The {@code onrequest}
  26. * function should be overridden to define request handling behavior.
  27. * @param {function(!http.ServerRequest, !http.ServerResponse)} requestHandler
  28. * The request handler for the server.
  29. * @constructor
  30. */
  31. var Server = function(requestHandler) {
  32. var server = http.createServer(function(req, res) {
  33. requestHandler(req, res);
  34. });
  35. server.on('connection', function(stream) {
  36. stream.setTimeout(4000);
  37. });
  38. /** @typedef {{port: number, address: string, family: string}} */
  39. var Host;
  40. /**
  41. * Starts the server on the given port. If no port, or 0, is provided,
  42. * the server will be started on a random port.
  43. * @param {number=} opt_port The port to start on.
  44. * @return {!Promise<Host>} A promise that will resolve
  45. * with the server host when it has fully started.
  46. */
  47. this.start = function(opt_port) {
  48. assert(typeof opt_port !== 'function',
  49. "start invoked with function, not port (mocha callback)?");
  50. var port = opt_port || portprober.findFreePort('localhost');
  51. return Promise.resolve(port).then(port => {
  52. return promise.checkedNodeCall(
  53. server.listen.bind(server, port, 'localhost'));
  54. }).then(function() {
  55. return server.address();
  56. });
  57. };
  58. /**
  59. * Stops the server.
  60. * @return {!Promise} A promise that will resolve when the
  61. * server has closed all connections.
  62. */
  63. this.stop = function() {
  64. return new Promise(resolve => server.close(resolve));
  65. };
  66. /**
  67. * @return {Host} This server's host info.
  68. * @throws {Error} If the server is not running.
  69. */
  70. this.address = function() {
  71. var addr = server.address();
  72. if (!addr) {
  73. throw Error('There server is not running!');
  74. }
  75. return addr;
  76. };
  77. /**
  78. * return {string} The host:port of this server.
  79. * @throws {Error} If the server is not running.
  80. */
  81. this.host = function() {
  82. return net.getLoopbackAddress() + ':' +
  83. this.address().port;
  84. };
  85. /**
  86. * Formats a URL for this server.
  87. * @param {string=} opt_pathname The desired pathname on the server.
  88. * @return {string} The formatted URL.
  89. * @throws {Error} If the server is not running.
  90. */
  91. this.url = function(opt_pathname) {
  92. var addr = this.address();
  93. var pathname = opt_pathname || '';
  94. return url.format({
  95. protocol: 'http',
  96. hostname: net.getLoopbackAddress(),
  97. port: addr.port,
  98. pathname: pathname
  99. });
  100. };
  101. };
  102. // PUBLIC API
  103. exports.Server = Server;