| 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 |  | 
| 18 | /** | 
| 19 |  * @fileoverview Various HTTP utilities. | 
| 20 |  */ | 
| 21 |  | 
| 22 | var base = require('../_base'), | 
| 23 |     HttpClient = require('./index').HttpClient, | 
| 24 |     checkResponse = base.require('bot.response').checkResponse, | 
| 25 |     Executor = base.require('webdriver.http.Executor'), | 
| 26 |     HttpRequest = base.require('webdriver.http.Request'), | 
| 27 |     Command = base.require('webdriver.Command'), | 
| 28 |     CommandName = base.require('webdriver.CommandName'), | 
| 29 |     promise = base.require('webdriver.promise'); | 
| 30 |  | 
| 31 |  | 
| 32 |  | 
| 33 | /** | 
| 34 |  * Queries a WebDriver server for its current status. | 
| 35 |  * @param {string} url Base URL of the server to query. | 
| 36 |  * @param {function(Error, *=)} callback The function to call with the | 
| 37 |  *     response. | 
| 38 |  */ | 
| 39 | function getStatus(url, callback) { | 
| 40 |   var client = new HttpClient(url); | 
| 41 |   var executor = new Executor(client); | 
| 42 |   var command = new Command(CommandName.GET_SERVER_STATUS); | 
| 43 |   executor.execute(command, function(err, responseObj) { | 
| 44 |     if (err) return callback(err); | 
| 45 |     try { | 
| 46 |       checkResponse(responseObj); | 
| 47 |     } catch (ex) { | 
| 48 |       return callback(ex); | 
| 49 |     } | 
| 50 |     callback(null, responseObj['value']); | 
| 51 |   }); | 
| 52 | } | 
| 53 |  | 
| 54 |  | 
| 55 | // PUBLIC API | 
| 56 |  | 
| 57 |  | 
| 58 | /** | 
| 59 |  * Queries a WebDriver server for its current status. | 
| 60 |  * @param {string} url Base URL of the server to query. | 
| 61 |  * @return {!webdriver.promise.Promise.<!Object>} A promise that resolves with | 
| 62 |  *     a hash of the server status. | 
| 63 |  */ | 
| 64 | exports.getStatus = function(url) { | 
| 65 |   return promise.checkedNodeCall(getStatus.bind(null, url)); | 
| 66 | }; | 
| 67 |  | 
| 68 |  | 
| 69 | /** | 
| 70 |  * Waits for a WebDriver server to be healthy and accepting requests. | 
| 71 |  * @param {string} url Base URL of the server to query. | 
| 72 |  * @param {number} timeout How long to wait for the server. | 
| 73 |  * @return {!webdriver.promise.Promise} A promise that will resolve when the | 
| 74 |  *     server is ready. | 
| 75 |  */ | 
| 76 | exports.waitForServer = function(url, timeout) { | 
| 77 |   var ready = promise.defer(), | 
| 78 |       start = Date.now(), | 
| 79 |       checkServerStatus = getStatus.bind(null, url, onResponse); | 
| 80 |   checkServerStatus(); | 
| 81 |   return ready.promise; | 
| 82 |  | 
| 83 |   function onResponse(err) { | 
| 84 |     if (!ready.isPending()) return; | 
| 85 |     if (!err) return ready.fulfill(); | 
| 86 |  | 
| 87 |     if (Date.now() - start > timeout) { | 
| 88 |       ready.reject( | 
| 89 |           Error('Timed out waiting for the WebDriver server at ' + url)); | 
| 90 |     } else { | 
| 91 |       setTimeout(function() { | 
| 92 |         if (ready.isPending()) { | 
| 93 |           checkServerStatus(); | 
| 94 |         } | 
| 95 |       }, 50); | 
| 96 |     } | 
| 97 |   } | 
| 98 | }; | 
| 99 |  | 
| 100 |  | 
| 101 | /** | 
| 102 |  * Polls a URL with GET requests until it returns a 2xx response or the | 
| 103 |  * timeout expires. | 
| 104 |  * @param {string} url The URL to poll. | 
| 105 |  * @param {number} timeout How long to wait, in milliseconds. | 
| 106 |  * @return {!webdriver.promise.Promise} A promise that will resolve when the | 
| 107 |  *     URL responds with 2xx. | 
| 108 |  */ | 
| 109 | exports.waitForUrl = function(url, timeout) { | 
| 110 |   var client = new HttpClient(url), | 
| 111 |       request = new HttpRequest('GET', ''), | 
| 112 |       testUrl = client.send.bind(client, request, onResponse), | 
| 113 |       ready = promise.defer(), | 
| 114 |       start = Date.now(); | 
| 115 |   testUrl(); | 
| 116 |   return ready.promise; | 
| 117 |  | 
| 118 |   function onResponse(err, response) { | 
| 119 |     if (!ready.isPending()) return; | 
| 120 |     if (!err && response.status > 199 && response.status < 300) { | 
| 121 |       return ready.fulfill(); | 
| 122 |     } | 
| 123 |  | 
| 124 |     if (Date.now() - start > timeout) { | 
| 125 |       ready.reject(Error( | 
| 126 |           'Timed out waiting for the URL to return 2xx: ' + url)); | 
| 127 |     } else { | 
| 128 |       setTimeout(function() { | 
| 129 |         if (ready.isPending()) { | 
| 130 |           testUrl(); | 
| 131 |         } | 
| 132 |       }, 50); | 
| 133 |     } | 
| 134 |   } | 
| 135 | }; |