| // 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. |
| |
| /** |
| * @fileoverview Various HTTP utilities. |
| */ |
| |
| 'use strict' |
| |
| const Executor = require('./index').Executor |
| const HttpClient = require('./index').HttpClient |
| const HttpRequest = require('./index').Request |
| const Command = require('../lib/command').Command |
| const CommandName = require('../lib/command').Name |
| const error = require('../lib/error') |
| |
| /** |
| * Queries a WebDriver server for its current status. |
| * @param {string} url Base URL of the server to query. |
| * @return {!Promise<!Object>} A promise that resolves with |
| * a hash of the server status. |
| */ |
| function getStatus(url) { |
| const client = new HttpClient(url) |
| const executor = new Executor(client) |
| const command = new Command(CommandName.GET_SERVER_STATUS) |
| return executor.execute(command) |
| } |
| |
| class CancellationError {} |
| |
| /** |
| * Waits for a WebDriver server to be healthy and accepting requests. |
| * @param {string} url Base URL of the server to query. |
| * @param {number} timeout How long to wait for the server. |
| * @param {Promise=} opt_cancelToken A promise used as a cancellation signal: |
| * if resolved before the server is ready, the wait will be terminated |
| * early with a {@link CancellationError}. |
| * @return {!Promise} A promise that will resolve when the server is ready, or |
| * if the wait is cancelled. |
| */ |
| function waitForServer(url, timeout, opt_cancelToken) { |
| return new Promise((onResolve, onReject) => { |
| let start = Date.now() |
| |
| let done = false |
| let resolve = (status) => { |
| done = true |
| onResolve(status) |
| } |
| let reject = (err) => { |
| done = true |
| onReject(err) |
| } |
| |
| if (opt_cancelToken) { |
| opt_cancelToken.then((_) => reject(new CancellationError())) |
| } |
| |
| checkServerStatus() |
| |
| function checkServerStatus() { |
| return getStatus(url).then((status) => resolve(status), onError) |
| } |
| |
| function onError(e) { |
| // Some servers don't support the status command. If they are able to |
| // response with an error, then can consider the server ready. |
| if (e instanceof error.UnsupportedOperationError) { |
| resolve({}) |
| return |
| } |
| |
| if (Date.now() - start > timeout) { |
| reject(Error('Timed out waiting for the WebDriver server at ' + url)) |
| } else { |
| setTimeout(function () { |
| if (!done) { |
| checkServerStatus() |
| } |
| }, 50) |
| } |
| } |
| }) |
| } |
| |
| /** |
| * Polls a URL with GET requests until it returns a 2xx response or the |
| * timeout expires. |
| * @param {string} url The URL to poll. |
| * @param {number} timeout How long to wait, in milliseconds. |
| * @param {Promise=} opt_cancelToken A promise used as a cancellation signal: |
| * if resolved before the a 2xx response is received, the wait will be |
| * terminated early with a {@link CancellationError}. |
| * @return {!Promise} A promise that will resolve when a 2xx is received from |
| * the given URL, or if the wait is cancelled. |
| */ |
| function waitForUrl(url, timeout, opt_cancelToken) { |
| return new Promise((onResolve, onReject) => { |
| let client = new HttpClient(url) |
| let request = new HttpRequest('GET', '') |
| let start = Date.now() |
| |
| let done = false |
| let resolve = () => { |
| done = true |
| onResolve() |
| } |
| let reject = (err) => { |
| done = true |
| onReject(err) |
| } |
| |
| if (opt_cancelToken) { |
| opt_cancelToken.then((_) => reject(new CancellationError())) |
| } |
| |
| testUrl() |
| |
| function testUrl() { |
| client.send(request).then(onResponse, onError) |
| } |
| |
| function onError() { |
| if (Date.now() - start > timeout) { |
| reject(Error('Timed out waiting for the URL to return 2xx: ' + url)) |
| } else { |
| setTimeout(function () { |
| if (!done) { |
| testUrl() |
| } |
| }, 50) |
| } |
| } |
| |
| function onResponse(response) { |
| if (done) { |
| return |
| } |
| if (response.status > 199 && response.status < 300) { |
| resolve() |
| return |
| } |
| onError() |
| } |
| }) |
| } |
| |
| // PUBLIC API |
| module.exports.getStatus = getStatus |
| module.exports.CancellationError = CancellationError |
| module.exports.waitForServer = waitForServer |
| module.exports.waitForUrl = waitForUrl |