forked from mirrors/gecko-dev
Bug 1484462 - Update webdriver to hyper 0.12. r=ato
This commit is contained in:
parent
4a601e2fa3
commit
963e21bf7f
8 changed files with 596 additions and 376 deletions
550
Cargo.lock
generated
550
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -12,7 +12,7 @@ publish = false
|
|||
base64 = "0.6"
|
||||
chrono = "^0.2"
|
||||
clap = { version = "^2.19", default-features = false, features = ["suggestions", "wrap_help"] }
|
||||
hyper = "0.10"
|
||||
hyper = "0.12"
|
||||
lazy_static = "1.0"
|
||||
log = { version = "0.4", features = ["std"] }
|
||||
mozprofile = { path = "../mozbase/rust/mozprofile" }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use base64;
|
||||
use hyper::method::Method;
|
||||
use hyper::Method;
|
||||
use mozprofile::preferences::Pref;
|
||||
use mozprofile::profile::Profile;
|
||||
use mozrunner::runner::{FirefoxProcess, FirefoxRunner, Runner, RunnerProcess};
|
||||
|
|
@ -67,32 +67,32 @@ const LEGACY_ELEMENT_KEY: &'static str = "ELEMENT";
|
|||
pub fn extension_routes() -> Vec<(Method, &'static str, GeckoExtensionRoute)> {
|
||||
return vec![
|
||||
(
|
||||
Method::Get,
|
||||
Method::GET,
|
||||
"/session/{sessionId}/moz/context",
|
||||
GeckoExtensionRoute::GetContext,
|
||||
),
|
||||
(
|
||||
Method::Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/moz/context",
|
||||
GeckoExtensionRoute::SetContext,
|
||||
),
|
||||
(
|
||||
Method::Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/moz/xbl/{elementId}/anonymous_children",
|
||||
GeckoExtensionRoute::XblAnonymousChildren,
|
||||
),
|
||||
(
|
||||
Method::Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/moz/xbl/{elementId}/anonymous_by_attribute",
|
||||
GeckoExtensionRoute::XblAnonymousByAttribute,
|
||||
),
|
||||
(
|
||||
Method::Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/moz/addon/install",
|
||||
GeckoExtensionRoute::InstallAddon,
|
||||
),
|
||||
(
|
||||
Method::Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/moz/addon/uninstall",
|
||||
GeckoExtensionRoute::UninstallAddon,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -10,15 +10,18 @@ readme = "README.md"
|
|||
license = "MPL-2.0"
|
||||
|
||||
[dependencies]
|
||||
cookie = { version = "0.10", default-features = false }
|
||||
base64 = "0.6"
|
||||
hyper = "0.10"
|
||||
cookie = { version = "0.11", default-features = false }
|
||||
futures = "0.1"
|
||||
http = "0.1"
|
||||
hyper = "0.12"
|
||||
log = "0.4"
|
||||
regex = "1.0"
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
serde_derive = "1.0"
|
||||
time = "0.1"
|
||||
tokio = "0.1"
|
||||
unicode-segmentation = "1.2"
|
||||
url = "1"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use base64::DecodeError;
|
||||
use hyper::status::StatusCode;
|
||||
use hyper::StatusCode;
|
||||
use serde::ser::{Serialize, Serializer};
|
||||
use serde_json;
|
||||
use std::borrow::Cow;
|
||||
|
|
@ -188,37 +188,36 @@ impl ErrorStatus {
|
|||
/// Returns the correct HTTP status code associated with the error type.
|
||||
pub fn http_status(&self) -> StatusCode {
|
||||
use self::ErrorStatus::*;
|
||||
use self::StatusCode::*;
|
||||
match *self {
|
||||
ElementClickIntercepted => BadRequest,
|
||||
ElementNotInteractable => BadRequest,
|
||||
ElementNotSelectable => BadRequest,
|
||||
InsecureCertificate => BadRequest,
|
||||
InvalidArgument => BadRequest,
|
||||
InvalidCookieDomain => BadRequest,
|
||||
InvalidCoordinates => BadRequest,
|
||||
InvalidElementState => BadRequest,
|
||||
InvalidSelector => BadRequest,
|
||||
InvalidSessionId => NotFound,
|
||||
JavascriptError => InternalServerError,
|
||||
MoveTargetOutOfBounds => InternalServerError,
|
||||
NoSuchAlert => NotFound,
|
||||
NoSuchCookie => NotFound,
|
||||
NoSuchElement => NotFound,
|
||||
NoSuchFrame => NotFound,
|
||||
NoSuchWindow => NotFound,
|
||||
ScriptTimeout => InternalServerError,
|
||||
SessionNotCreated => InternalServerError,
|
||||
StaleElementReference => NotFound,
|
||||
Timeout => InternalServerError,
|
||||
UnableToCaptureScreen => BadRequest,
|
||||
UnableToSetCookie => InternalServerError,
|
||||
UnexpectedAlertOpen => InternalServerError,
|
||||
UnknownCommand => NotFound,
|
||||
UnknownError => InternalServerError,
|
||||
UnknownMethod => MethodNotAllowed,
|
||||
UnknownPath => NotFound,
|
||||
UnsupportedOperation => InternalServerError,
|
||||
ElementClickIntercepted => StatusCode::BAD_REQUEST,
|
||||
ElementNotInteractable => StatusCode::BAD_REQUEST,
|
||||
ElementNotSelectable => StatusCode::BAD_REQUEST,
|
||||
InsecureCertificate => StatusCode::BAD_REQUEST,
|
||||
InvalidArgument => StatusCode::BAD_REQUEST,
|
||||
InvalidCookieDomain => StatusCode::BAD_REQUEST,
|
||||
InvalidCoordinates => StatusCode::BAD_REQUEST,
|
||||
InvalidElementState => StatusCode::BAD_REQUEST,
|
||||
InvalidSelector => StatusCode::BAD_REQUEST,
|
||||
InvalidSessionId => StatusCode::NOT_FOUND,
|
||||
JavascriptError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
MoveTargetOutOfBounds => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
NoSuchAlert => StatusCode::NOT_FOUND,
|
||||
NoSuchCookie => StatusCode::NOT_FOUND,
|
||||
NoSuchElement => StatusCode::NOT_FOUND,
|
||||
NoSuchFrame => StatusCode::NOT_FOUND,
|
||||
NoSuchWindow => StatusCode::NOT_FOUND,
|
||||
ScriptTimeout => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
SessionNotCreated => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
StaleElementReference => StatusCode::NOT_FOUND,
|
||||
Timeout => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
UnableToCaptureScreen => StatusCode::BAD_REQUEST,
|
||||
UnableToSetCookie => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
UnexpectedAlertOpen => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
UnknownCommand => StatusCode::NOT_FOUND,
|
||||
UnknownError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
UnknownMethod => StatusCode::METHOD_NOT_ALLOWED,
|
||||
UnknownPath => StatusCode::NOT_FOUND,
|
||||
UnsupportedOperation => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use regex::{Captures, Regex};
|
||||
|
||||
use hyper::method::Method;
|
||||
use hyper::method::Method::{Delete, Get, Post};
|
||||
use hyper::Method;
|
||||
use serde_json::Value;
|
||||
|
||||
use command::{VoidWebDriverExtensionCommand, WebDriverCommand, WebDriverExtensionCommand,
|
||||
|
|
@ -10,214 +9,214 @@ use error::{ErrorStatus, WebDriverError, WebDriverResult};
|
|||
|
||||
fn standard_routes<U: WebDriverExtensionRoute>() -> Vec<(Method, &'static str, Route<U>)> {
|
||||
return vec![
|
||||
(Post, "/session", Route::NewSession),
|
||||
(Delete, "/session/{sessionId}", Route::DeleteSession),
|
||||
(Post, "/session/{sessionId}/url", Route::Get),
|
||||
(Get, "/session/{sessionId}/url", Route::GetCurrentUrl),
|
||||
(Post, "/session/{sessionId}/back", Route::GoBack),
|
||||
(Post, "/session/{sessionId}/forward", Route::GoForward),
|
||||
(Post, "/session/{sessionId}/refresh", Route::Refresh),
|
||||
(Get, "/session/{sessionId}/title", Route::GetTitle),
|
||||
(Get, "/session/{sessionId}/source", Route::GetPageSource),
|
||||
(Get, "/session/{sessionId}/window", Route::GetWindowHandle),
|
||||
(Method::POST, "/session", Route::NewSession),
|
||||
(Method::DELETE, "/session/{sessionId}", Route::DeleteSession),
|
||||
(Method::POST, "/session/{sessionId}/url", Route::Get),
|
||||
(Method::GET, "/session/{sessionId}/url", Route::GetCurrentUrl),
|
||||
(Method::POST, "/session/{sessionId}/back", Route::GoBack),
|
||||
(Method::POST, "/session/{sessionId}/forward", Route::GoForward),
|
||||
(Method::POST, "/session/{sessionId}/refresh", Route::Refresh),
|
||||
(Method::GET, "/session/{sessionId}/title", Route::GetTitle),
|
||||
(Method::GET, "/session/{sessionId}/source", Route::GetPageSource),
|
||||
(Method::GET, "/session/{sessionId}/window", Route::GetWindowHandle),
|
||||
(
|
||||
Get,
|
||||
Method::GET,
|
||||
"/session/{sessionId}/window/handles",
|
||||
Route::GetWindowHandles,
|
||||
),
|
||||
(Delete, "/session/{sessionId}/window", Route::CloseWindow),
|
||||
(Method::DELETE, "/session/{sessionId}/window", Route::CloseWindow),
|
||||
(
|
||||
Get,
|
||||
Method::GET,
|
||||
"/session/{sessionId}/window/size",
|
||||
Route::GetWindowSize,
|
||||
),
|
||||
(
|
||||
Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/window/size",
|
||||
Route::SetWindowSize,
|
||||
),
|
||||
(
|
||||
Get,
|
||||
Method::GET,
|
||||
"/session/{sessionId}/window/position",
|
||||
Route::GetWindowPosition,
|
||||
),
|
||||
(
|
||||
Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/window/position",
|
||||
Route::SetWindowPosition,
|
||||
),
|
||||
(
|
||||
Get,
|
||||
Method::GET,
|
||||
"/session/{sessionId}/window/rect",
|
||||
Route::GetWindowRect,
|
||||
),
|
||||
(
|
||||
Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/window/rect",
|
||||
Route::SetWindowRect,
|
||||
),
|
||||
(
|
||||
Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/window/minimize",
|
||||
Route::MinimizeWindow,
|
||||
),
|
||||
(
|
||||
Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/window/maximize",
|
||||
Route::MaximizeWindow,
|
||||
),
|
||||
(
|
||||
Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/window/fullscreen",
|
||||
Route::FullscreenWindow,
|
||||
),
|
||||
(Post, "/session/{sessionId}/window", Route::SwitchToWindow),
|
||||
(Post, "/session/{sessionId}/frame", Route::SwitchToFrame),
|
||||
(Method::POST, "/session/{sessionId}/window", Route::SwitchToWindow),
|
||||
(Method::POST, "/session/{sessionId}/frame", Route::SwitchToFrame),
|
||||
(
|
||||
Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/frame/parent",
|
||||
Route::SwitchToParentFrame,
|
||||
),
|
||||
(Post, "/session/{sessionId}/element", Route::FindElement),
|
||||
(Post, "/session/{sessionId}/elements", Route::FindElements),
|
||||
(Method::POST, "/session/{sessionId}/element", Route::FindElement),
|
||||
(Method::POST, "/session/{sessionId}/elements", Route::FindElements),
|
||||
(
|
||||
Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/element/{elementId}/element",
|
||||
Route::FindElementElement,
|
||||
),
|
||||
(
|
||||
Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/element/{elementId}/elements",
|
||||
Route::FindElementElements,
|
||||
),
|
||||
(
|
||||
Get,
|
||||
Method::GET,
|
||||
"/session/{sessionId}/element/active",
|
||||
Route::GetActiveElement,
|
||||
),
|
||||
(
|
||||
Get,
|
||||
Method::GET,
|
||||
"/session/{sessionId}/element/{elementId}/displayed",
|
||||
Route::IsDisplayed,
|
||||
),
|
||||
(
|
||||
Get,
|
||||
Method::GET,
|
||||
"/session/{sessionId}/element/{elementId}/selected",
|
||||
Route::IsSelected,
|
||||
),
|
||||
(
|
||||
Get,
|
||||
Method::GET,
|
||||
"/session/{sessionId}/element/{elementId}/attribute/{name}",
|
||||
Route::GetElementAttribute,
|
||||
),
|
||||
(
|
||||
Get,
|
||||
Method::GET,
|
||||
"/session/{sessionId}/element/{elementId}/property/{name}",
|
||||
Route::GetElementProperty,
|
||||
),
|
||||
(
|
||||
Get,
|
||||
Method::GET,
|
||||
"/session/{sessionId}/element/{elementId}/css/{propertyName}",
|
||||
Route::GetCSSValue,
|
||||
),
|
||||
(
|
||||
Get,
|
||||
Method::GET,
|
||||
"/session/{sessionId}/element/{elementId}/text",
|
||||
Route::GetElementText,
|
||||
),
|
||||
(
|
||||
Get,
|
||||
Method::GET,
|
||||
"/session/{sessionId}/element/{elementId}/name",
|
||||
Route::GetElementTagName,
|
||||
),
|
||||
(
|
||||
Get,
|
||||
Method::GET,
|
||||
"/session/{sessionId}/element/{elementId}/rect",
|
||||
Route::GetElementRect,
|
||||
),
|
||||
(
|
||||
Get,
|
||||
Method::GET,
|
||||
"/session/{sessionId}/element/{elementId}/enabled",
|
||||
Route::IsEnabled,
|
||||
),
|
||||
(
|
||||
Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/execute/sync",
|
||||
Route::ExecuteScript,
|
||||
),
|
||||
(
|
||||
Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/execute/async",
|
||||
Route::ExecuteAsyncScript,
|
||||
),
|
||||
(Get, "/session/{sessionId}/cookie", Route::GetCookies),
|
||||
(Method::GET, "/session/{sessionId}/cookie", Route::GetCookies),
|
||||
(
|
||||
Get,
|
||||
Method::GET,
|
||||
"/session/{sessionId}/cookie/{name}",
|
||||
Route::GetNamedCookie,
|
||||
),
|
||||
(Post, "/session/{sessionId}/cookie", Route::AddCookie),
|
||||
(Delete, "/session/{sessionId}/cookie", Route::DeleteCookies),
|
||||
(Method::POST, "/session/{sessionId}/cookie", Route::AddCookie),
|
||||
(Method::DELETE, "/session/{sessionId}/cookie", Route::DeleteCookies),
|
||||
(
|
||||
Delete,
|
||||
Method::DELETE,
|
||||
"/session/{sessionId}/cookie/{name}",
|
||||
Route::DeleteCookie,
|
||||
),
|
||||
(Get, "/session/{sessionId}/timeouts", Route::GetTimeouts),
|
||||
(Post, "/session/{sessionId}/timeouts", Route::SetTimeouts),
|
||||
(Method::GET, "/session/{sessionId}/timeouts", Route::GetTimeouts),
|
||||
(Method::POST, "/session/{sessionId}/timeouts", Route::SetTimeouts),
|
||||
(
|
||||
Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/element/{elementId}/click",
|
||||
Route::ElementClick,
|
||||
),
|
||||
(
|
||||
Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/element/{elementId}/tap",
|
||||
Route::ElementTap,
|
||||
),
|
||||
(
|
||||
Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/element/{elementId}/clear",
|
||||
Route::ElementClear,
|
||||
),
|
||||
(
|
||||
Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/element/{elementId}/value",
|
||||
Route::ElementSendKeys,
|
||||
),
|
||||
(
|
||||
Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/alert/dismiss",
|
||||
Route::DismissAlert,
|
||||
),
|
||||
(
|
||||
Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/alert/accept",
|
||||
Route::AcceptAlert,
|
||||
),
|
||||
(Get, "/session/{sessionId}/alert/text", Route::GetAlertText),
|
||||
(Method::GET, "/session/{sessionId}/alert/text", Route::GetAlertText),
|
||||
(
|
||||
Post,
|
||||
Method::POST,
|
||||
"/session/{sessionId}/alert/text",
|
||||
Route::SendAlertText,
|
||||
),
|
||||
(
|
||||
Get,
|
||||
Method::GET,
|
||||
"/session/{sessionId}/screenshot",
|
||||
Route::TakeScreenshot,
|
||||
),
|
||||
(
|
||||
Get,
|
||||
Method::GET,
|
||||
"/session/{sessionId}/element/{elementId}/screenshot",
|
||||
Route::TakeElementScreenshot,
|
||||
),
|
||||
(Post, "/session/{sessionId}/actions", Route::PerformActions),
|
||||
(Method::POST, "/session/{sessionId}/actions", Route::PerformActions),
|
||||
(
|
||||
Delete,
|
||||
Method::DELETE,
|
||||
"/session/{sessionId}/actions",
|
||||
Route::ReleaseActions,
|
||||
),
|
||||
(Get, "/status", Route::Status),
|
||||
(Method::GET, "/status", Route::Status),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -394,7 +393,7 @@ impl<U: WebDriverExtensionRoute> WebDriverHttpApi<U> {
|
|||
matcher.match_type.clone(),
|
||||
&captures.unwrap(),
|
||||
body,
|
||||
method == Post,
|
||||
method == Method::POST,
|
||||
);
|
||||
} else {
|
||||
error = ErrorStatus::UnknownMethod;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ extern crate base64;
|
|||
extern crate cookie;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate futures;
|
||||
extern crate http;
|
||||
extern crate hyper;
|
||||
extern crate regex;
|
||||
extern crate serde;
|
||||
|
|
@ -11,6 +13,7 @@ extern crate serde;
|
|||
extern crate serde_derive;
|
||||
extern crate serde_json;
|
||||
extern crate time;
|
||||
extern crate tokio;
|
||||
extern crate unicode_segmentation;
|
||||
extern crate url;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +1,18 @@
|
|||
use serde_json;
|
||||
use std::io::Read;
|
||||
use std::marker::PhantomData;
|
||||
use std::net::SocketAddr;
|
||||
use std::net::{SocketAddr, TcpListener as StdTcpListener};
|
||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
use std::sync::Mutex;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use hyper::header::{CacheControl, CacheDirective, ContentType};
|
||||
use hyper::method::Method;
|
||||
use hyper::mime::{Attr, Mime, SubLevel, TopLevel, Value};
|
||||
use hyper::server::{Handler, Listening, Request, Response, Server};
|
||||
use hyper::status::StatusCode;
|
||||
use hyper::uri::RequestUri::AbsolutePath;
|
||||
use hyper::Result;
|
||||
use futures::{future, Future, Stream};
|
||||
use hyper::{self, Body, Method, Request, Response, StatusCode};
|
||||
use hyper::service::Service;
|
||||
use hyper::server::conn::Http;
|
||||
use http;
|
||||
use tokio::runtime::current_thread::Runtime;
|
||||
use tokio::reactor::Handle;
|
||||
use tokio::net::TcpListener;
|
||||
|
||||
use command::{WebDriverCommand, WebDriverMessage};
|
||||
use error::{ErrorStatus, WebDriverError, WebDriverResult};
|
||||
|
|
@ -93,7 +92,7 @@ impl<T: WebDriverHandler<U>, U: WebDriverExtensionRoute> Dispatcher<T, U> {
|
|||
};
|
||||
}
|
||||
Ok(DispatchMessage::Quit) => break,
|
||||
Err(_) => panic!("Error receiving message in handler"),
|
||||
Err(e) => panic!("Error receiving message in handler: {:?}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -152,96 +151,101 @@ impl<T: WebDriverHandler<U>, U: WebDriverExtensionRoute> Dispatcher<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
struct HttpHandler<U: WebDriverExtensionRoute> {
|
||||
chan: Mutex<Sender<DispatchMessage<U>>>,
|
||||
api: Mutex<WebDriverHttpApi<U>>,
|
||||
chan: Arc<Mutex<Sender<DispatchMessage<U>>>>,
|
||||
api: Arc<Mutex<WebDriverHttpApi<U>>>,
|
||||
}
|
||||
|
||||
impl<U: WebDriverExtensionRoute> HttpHandler<U> {
|
||||
fn new(api: WebDriverHttpApi<U>, chan: Sender<DispatchMessage<U>>) -> HttpHandler<U> {
|
||||
impl <U: WebDriverExtensionRoute> HttpHandler<U> {
|
||||
fn new(api: Arc<Mutex<WebDriverHttpApi<U>>>, chan: Sender<DispatchMessage<U>>) -> HttpHandler<U> {
|
||||
HttpHandler {
|
||||
chan: Mutex::new(chan),
|
||||
api: Mutex::new(api),
|
||||
chan: Arc::new(Mutex::new(chan)),
|
||||
api: api,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<U: WebDriverExtensionRoute> Handler for HttpHandler<U> {
|
||||
fn handle(&self, req: Request, res: Response) {
|
||||
let mut req = req;
|
||||
let mut res = res;
|
||||
impl<U: WebDriverExtensionRoute + 'static> Service for HttpHandler<U> {
|
||||
type ReqBody = Body;
|
||||
type ResBody = Body;
|
||||
|
||||
let mut body = String::new();
|
||||
if let Method::Post = req.method {
|
||||
req.read_to_string(&mut body).unwrap();
|
||||
}
|
||||
type Error = hyper::Error;
|
||||
type Future = Box<future::Future<Item=Response<Self::ResBody>, Error=hyper::Error> + Send>;
|
||||
|
||||
debug!("-> {} {} {}", req.method, req.uri, body);
|
||||
fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future {
|
||||
let uri = req.uri().clone();
|
||||
let method = req.method().clone();
|
||||
let api = self.api.clone();
|
||||
let chan = self.chan.clone();
|
||||
|
||||
match req.uri {
|
||||
AbsolutePath(path) => {
|
||||
let msg_result = {
|
||||
// The fact that this locks for basically the whole request doesn't
|
||||
// matter as long as we are only handling one request at a time.
|
||||
match self.api.lock() {
|
||||
Ok(ref api) => api.decode_request(req.method, &path[..], &body[..]),
|
||||
Err(_) => return,
|
||||
}
|
||||
};
|
||||
let (status, resp_body) = match msg_result {
|
||||
Ok(message) => {
|
||||
let (send_res, recv_res) = channel();
|
||||
match self.chan.lock() {
|
||||
Ok(ref c) => {
|
||||
let res =
|
||||
c.send(DispatchMessage::HandleWebDriver(message, send_res));
|
||||
match res {
|
||||
Ok(x) => x,
|
||||
Err(_) => {
|
||||
error!("Something terrible happened");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
error!("Something terrible happened");
|
||||
return;
|
||||
}
|
||||
}
|
||||
match recv_res.recv() {
|
||||
Ok(data) => match data {
|
||||
Ok(response) => {
|
||||
(StatusCode::Ok, serde_json::to_string(&response).unwrap())
|
||||
}
|
||||
Err(err) => {
|
||||
(err.http_status(), serde_json::to_string(&err).unwrap())
|
||||
}
|
||||
},
|
||||
Err(e) => panic!("Error reading response: {:?}", e),
|
||||
}
|
||||
}
|
||||
Err(err) => (err.http_status(), serde_json::to_string(&err).unwrap()),
|
||||
};
|
||||
Box::new(req.into_body().concat2().and_then(move |body| {
|
||||
let body = String::from_utf8(body.to_vec()).unwrap();
|
||||
debug!("-> {} {} {}", method, uri, body);
|
||||
|
||||
debug!("<- {} {}", status, resp_body);
|
||||
|
||||
{
|
||||
let resp_status = res.status_mut();
|
||||
*resp_status = status;
|
||||
let msg_result = {
|
||||
// The fact that this locks for basically the whole request doesn't
|
||||
// matter as long as we are only handling one request at a time.
|
||||
match api.lock() {
|
||||
Ok(ref api) => api.decode_request(method, &uri.path(), &body[..]),
|
||||
Err(_) => panic!("Something terrible happened"),
|
||||
}
|
||||
res.headers_mut().set(ContentType(Mime(
|
||||
TopLevel::Application,
|
||||
SubLevel::Json,
|
||||
vec![(Attr::Charset, Value::Utf8)],
|
||||
)));
|
||||
res.headers_mut()
|
||||
.set(CacheControl(vec![CacheDirective::NoCache]));
|
||||
};
|
||||
|
||||
res.send(&resp_body.as_bytes()).unwrap();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let (status, resp_body) = match msg_result {
|
||||
Ok(message) => {
|
||||
let (send_res, recv_res) = channel();
|
||||
match chan.lock() {
|
||||
Ok(ref c) => {
|
||||
let res =
|
||||
c.send(DispatchMessage::HandleWebDriver(message, send_res));
|
||||
match res {
|
||||
Ok(x) => x,
|
||||
Err(_) => {
|
||||
panic!("Something terrible happened");
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => panic!("Error reading response: {:?}", e),
|
||||
}
|
||||
|
||||
match recv_res.recv() {
|
||||
Ok(data) => match data {
|
||||
Ok(response) => {
|
||||
(StatusCode::OK, serde_json::to_string(&response).unwrap())
|
||||
}
|
||||
Err(err) => {
|
||||
(err.http_status(), serde_json::to_string(&err).unwrap())
|
||||
}
|
||||
},
|
||||
Err(e) => panic!("Error reading response: {:?}", e),
|
||||
}
|
||||
}
|
||||
Err(err) => (err.http_status(), serde_json::to_string(&err).unwrap()),
|
||||
};
|
||||
|
||||
debug!("<- {} {}", status, resp_body);
|
||||
|
||||
let response = Response::builder()
|
||||
.status(status)
|
||||
.header(http::header::CONTENT_TYPE, "application/json; charset=utf8")
|
||||
.header(http::header::CACHE_CONTROL, "no-cache")
|
||||
.body(resp_body.into())
|
||||
.unwrap();
|
||||
|
||||
Ok(response)
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Listener {
|
||||
_guard: Option<thread::JoinHandle<()>>,
|
||||
pub socket: SocketAddr,
|
||||
}
|
||||
|
||||
impl Drop for Listener {
|
||||
fn drop(&mut self) {
|
||||
let _ = self._guard.take().map(|j| j.join());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -249,17 +253,35 @@ pub fn start<T, U>(
|
|||
address: SocketAddr,
|
||||
handler: T,
|
||||
extension_routes: &[(Method, &str, U)],
|
||||
) -> Result<Listening>
|
||||
) -> ::std::io::Result<Listener>
|
||||
where
|
||||
T: 'static + WebDriverHandler<U>,
|
||||
U: 'static + WebDriverExtensionRoute,
|
||||
{
|
||||
let listener = StdTcpListener::bind(address)?;
|
||||
let addr = listener.local_addr()?;
|
||||
let (msg_send, msg_recv) = channel();
|
||||
|
||||
let api = WebDriverHttpApi::new(extension_routes);
|
||||
let http_handler = HttpHandler::new(api, msg_send);
|
||||
let mut server = Server::http(address)?;
|
||||
server.keep_alive(Some(Duration::from_secs(90)));
|
||||
let api = Arc::new(Mutex::new(WebDriverHttpApi::new(extension_routes)));
|
||||
|
||||
let builder = thread::Builder::new().name("webdriver server".to_string());
|
||||
let handle = builder.spawn(move || {
|
||||
let mut rt = Runtime::new().unwrap();
|
||||
let listener = TcpListener::from_std(listener, &Handle::default()).unwrap();
|
||||
|
||||
let http_handler = HttpHandler::new(api, msg_send.clone());
|
||||
let http = Http::new();
|
||||
let handle = rt.handle();
|
||||
|
||||
let fut = listener.incoming()
|
||||
.for_each(move |socket| {
|
||||
let fut = http.serve_connection(socket, http_handler.clone()).map_err(|_| ());
|
||||
handle.spawn(fut).unwrap();
|
||||
Ok(())
|
||||
});
|
||||
|
||||
rt.block_on(fut).unwrap();
|
||||
})?;
|
||||
|
||||
let builder = thread::Builder::new().name("webdriver dispatcher".to_string());
|
||||
builder.spawn(move || {
|
||||
|
|
@ -267,5 +289,5 @@ where
|
|||
dispatcher.run(msg_recv);
|
||||
})?;
|
||||
|
||||
server.handle(http_handler)
|
||||
Ok(Listener { _guard: Some(handle), socket: addr })
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue