Path: blob/trunk/javascript/selenium-webdriver/lib/test/httpserver.js
2884 views
// Licensed to the Software Freedom Conservancy (SFC) under one1// or more contributor license agreements. See the NOTICE file2// distributed with this work for additional information3// regarding copyright ownership. The SFC licenses this file4// to you under the Apache License, Version 2.0 (the5// "License"); you may not use this file except in compliance6// with the License. You may obtain a copy of the License at7//8// http://www.apache.org/licenses/LICENSE-2.09//10// Unless required by applicable law or agreed to in writing,11// software distributed under the License is distributed on an12// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13// KIND, either express or implied. See the License for the14// specific language governing permissions and limitations15// under the License.1617'use strict'1819const assert = require('node:assert')20const http = require('node:http')21const url = require('node:url')2223const net = require('selenium-webdriver/net')24const portprober = require('selenium-webdriver/net/portprober')25const promise = require('selenium-webdriver').promise2627/**28* Encapsulates a simple HTTP server for testing. The {@code onrequest}29* function should be overridden to define request handling behavior.30* @param {function(!http.ServerRequest, !http.ServerResponse)} requestHandler31* The request handler for the server.32* @constructor33*/34let Server = function (requestHandler) {35let server = http.createServer(function (req, res) {36requestHandler(req, res)37})3839server.on('connection', function (stream) {40stream.setTimeout(4000)41})4243/** @typedef {{port: number, address: string, family: string}} */44let Host // eslint-disable-line4546/**47* Starts the server on the given port. If no port, or 0, is provided,48* the server will be started on a random port.49* @param {number=} opt_port The port to start on.50* @return {!Promise<Host>} A promise that will resolve51* with the server host when it has fully started.52*/53this.start = function (opt_port) {54assert(typeof opt_port !== 'function', 'start invoked with function, not port (mocha callback)?')55const port = opt_port || portprober.findFreePort('127.0.0.1')56return Promise.resolve(port)57.then((port) => {58return promise.checkedNodeCall(server.listen.bind(server, port, '127.0.0.1'))59})60.then(function () {61return server.address()62})63}6465/**66* Stops the server.67* @return {!Promise} A promise that will resolve when the68* server has closed all connections.69*/70this.stop = function () {71return new Promise((resolve) => server.close(resolve))72}7374/**75* @return {Host} This server's host info.76* @throws {Error} If the server is not running.77*/78this.address = function () {79const addr = server.address()80if (!addr) {81throw Error('There server is not running!')82}83return addr84}8586/**87* return {string} The host:port of this server.88* @throws {Error} If the server is not running.89*/90this.host = function () {91return net.getLoopbackAddress() + ':' + this.address().port92}9394/**95* Formats a URL for this server.96* @param {string=} opt_pathname The desired pathname on the server.97* @return {string} The formatted URL.98* @throws {Error} If the server is not running.99*/100this.url = function (opt_pathname) {101const addr = this.address()102const pathname = opt_pathname || ''103return url.format({104protocol: 'http',105hostname: net.getLoopbackAddress(),106port: addr.port,107pathname: pathname,108})109}110}111112// PUBLIC API113114exports.Server = Server115116117