// Licensed to the Software Freedom Conservancy (SFC) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The SFC licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. 'use strict' const assert = require('node:assert') const http = require('node:http') const url = require('node:url') const net = require('selenium-webdriver/net') const portprober = require('selenium-webdriver/net/portprober') const promise = require('selenium-webdriver').promise /** * Encapsulates a simple HTTP server for testing. The {@code onrequest} * function should be overridden to define request handling behavior. * @param {function(!http.ServerRequest, !http.ServerResponse)} requestHandler * The request handler for the server. * @constructor */ let Server = function (requestHandler) { let server = http.createServer(function (req, res) { requestHandler(req, res) }) server.on('connection', function (stream) { stream.setTimeout(4000) }) /** @typedef {{port: number, address: string, family: string}} */ let Host // eslint-disable-line /** * Starts the server on the given port. If no port, or 0, is provided, * the server will be started on a random port. * @param {number=} opt_port The port to start on. * @return {!Promise} A promise that will resolve * with the server host when it has fully started. */ this.start = function (opt_port) { assert(typeof opt_port !== 'function', 'start invoked with function, not port (mocha callback)?') const port = opt_port || portprober.findFreePort('127.0.0.1') return Promise.resolve(port) .then((port) => { return promise.checkedNodeCall(server.listen.bind(server, port, '127.0.0.1')) }) .then(function () { return server.address() }) } /** * Stops the server. * @return {!Promise} A promise that will resolve when the * server has closed all connections. */ this.stop = function () { return new Promise((resolve) => server.close(resolve)) } /** * @return {Host} This server's host info. * @throws {Error} If the server is not running. */ this.address = function () { const addr = server.address() if (!addr) { throw Error('There server is not running!') } return addr } /** * return {string} The host:port of this server. * @throws {Error} If the server is not running. */ this.host = function () { return net.getLoopbackAddress() + ':' + this.address().port } /** * Formats a URL for this server. * @param {string=} opt_pathname The desired pathname on the server. * @return {string} The formatted URL. * @throws {Error} If the server is not running. */ this.url = function (opt_pathname) { const addr = this.address() const pathname = opt_pathname || '' return url.format({ protocol: 'http', hostname: net.getLoopbackAddress(), port: addr.port, pathname: pathname, }) } } // PUBLIC API exports.Server = Server