2015-04-04 09:53:59 -07:00
|
|
|
// 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
|
2014-11-12 19:33:37 +00:00
|
|
|
//
|
2015-04-04 09:53:59 -07:00
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
2014-11-12 19:33:37 +00:00
|
|
|
//
|
2015-04-04 09:53:59 -07:00
|
|
|
// 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.
|
2013-06-26 22:16:09 -07:00
|
|
|
|
2020-08-03 17:56:31 +03:00
|
|
|
'use strict'
|
2013-06-26 22:16:09 -07:00
|
|
|
|
2024-04-16 01:50:58 +05:30
|
|
|
const assert = require('node:assert')
|
|
|
|
|
const http = require('node:http')
|
|
|
|
|
const url = require('node:url')
|
2013-06-26 22:16:09 -07:00
|
|
|
|
2024-06-27 18:33:36 +01:00
|
|
|
const net = require('selenium-webdriver/net')
|
|
|
|
|
const portprober = require('selenium-webdriver/net/portprober')
|
|
|
|
|
const promise = require('selenium-webdriver').promise
|
2013-06-26 22:16:09 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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
|
|
|
|
|
*/
|
2021-02-16 11:53:41 +05:30
|
|
|
let Server = function (requestHandler) {
|
|
|
|
|
let server = http.createServer(function (req, res) {
|
2020-08-03 17:56:31 +03:00
|
|
|
requestHandler(req, res)
|
|
|
|
|
})
|
2013-06-26 22:16:09 -07:00
|
|
|
|
2020-08-03 17:56:31 +03:00
|
|
|
server.on('connection', function (stream) {
|
|
|
|
|
stream.setTimeout(4000)
|
|
|
|
|
})
|
2013-06-26 22:16:09 -07:00
|
|
|
|
|
|
|
|
/** @typedef {{port: number, address: string, family: string}} */
|
2021-02-16 11:53:41 +05:30
|
|
|
let Host // eslint-disable-line
|
2013-06-26 22:16:09 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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.
|
2016-10-30 11:30:58 -07:00
|
|
|
* @return {!Promise<Host>} A promise that will resolve
|
2013-06-26 22:16:09 -07:00
|
|
|
* with the server host when it has fully started.
|
|
|
|
|
*/
|
2020-08-03 17:56:31 +03:00
|
|
|
this.start = function (opt_port) {
|
2024-02-07 16:07:24 +00:00
|
|
|
assert(typeof opt_port !== 'function', 'start invoked with function, not port (mocha callback)?')
|
2022-08-26 17:48:15 +05:30
|
|
|
const port = opt_port || portprober.findFreePort('127.0.0.1')
|
2020-08-03 17:56:31 +03:00
|
|
|
return Promise.resolve(port)
|
|
|
|
|
.then((port) => {
|
2024-02-07 16:07:24 +00:00
|
|
|
return promise.checkedNodeCall(server.listen.bind(server, port, '127.0.0.1'))
|
2020-08-03 17:56:31 +03:00
|
|
|
})
|
|
|
|
|
.then(function () {
|
|
|
|
|
return server.address()
|
|
|
|
|
})
|
|
|
|
|
}
|
2013-06-26 22:16:09 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Stops the server.
|
2016-10-30 11:30:58 -07:00
|
|
|
* @return {!Promise} A promise that will resolve when the
|
2013-06-26 22:16:09 -07:00
|
|
|
* server has closed all connections.
|
|
|
|
|
*/
|
2020-08-03 17:56:31 +03:00
|
|
|
this.stop = function () {
|
|
|
|
|
return new Promise((resolve) => server.close(resolve))
|
|
|
|
|
}
|
2013-06-26 22:16:09 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @return {Host} This server's host info.
|
|
|
|
|
* @throws {Error} If the server is not running.
|
|
|
|
|
*/
|
2020-08-03 17:56:31 +03:00
|
|
|
this.address = function () {
|
2021-02-16 11:53:41 +05:30
|
|
|
const addr = server.address()
|
2013-06-26 22:16:09 -07:00
|
|
|
if (!addr) {
|
2020-08-03 17:56:31 +03:00
|
|
|
throw Error('There server is not running!')
|
2013-06-26 22:16:09 -07:00
|
|
|
}
|
2020-08-03 17:56:31 +03:00
|
|
|
return addr
|
|
|
|
|
}
|
2013-06-26 22:16:09 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* return {string} The host:port of this server.
|
|
|
|
|
* @throws {Error} If the server is not running.
|
|
|
|
|
*/
|
2020-08-03 17:56:31 +03:00
|
|
|
this.host = function () {
|
|
|
|
|
return net.getLoopbackAddress() + ':' + this.address().port
|
|
|
|
|
}
|
2013-06-26 22:16:09 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
2020-08-03 17:56:31 +03:00
|
|
|
this.url = function (opt_pathname) {
|
2021-02-16 11:53:41 +05:30
|
|
|
const addr = this.address()
|
|
|
|
|
const pathname = opt_pathname || ''
|
2013-06-26 22:16:09 -07:00
|
|
|
return url.format({
|
|
|
|
|
protocol: 'http',
|
2015-02-16 14:55:06 -08:00
|
|
|
hostname: net.getLoopbackAddress(),
|
2013-06-26 22:16:09 -07:00
|
|
|
port: addr.port,
|
2020-08-03 17:56:31 +03:00
|
|
|
pathname: pathname,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-06-26 22:16:09 -07:00
|
|
|
|
|
|
|
|
// PUBLIC API
|
|
|
|
|
|
2020-08-03 17:56:31 +03:00
|
|
|
exports.Server = Server
|