aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2015-12-21 21:17:25 +0530
committerbors-servo <lbergstrom+bors@mozilla.com>2015-12-21 21:17:25 +0530
commita8783ad184ab6167803af44f4abf16754c410c2a (patch)
tree95668f8e57602487433baedc87fc22c9fbb850d8
parent552df7e79e283621b93028501a3362d698916f6b (diff)
parentf889b1ccd7849e594d66a27e5c0fd8095e7242ec (diff)
downloadservo-a8783ad184ab6167803af44f4abf16754c410c2a.tar.gz
servo-a8783ad184ab6167803af44f4abf16754c410c2a.zip
Auto merge of #8845 - akumar21NCSU:master, r=jdm
M1502: Expand HTTP request response monitoring-2 <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/8845) <!-- Reviewable:end -->
-rw-r--r--components/devtools/actors/network_event.rs283
-rw-r--r--components/devtools/lib.rs125
-rw-r--r--components/devtools_traits/lib.rs2
-rw-r--r--components/net/http_loader.rs20
-rw-r--r--tests/unit/net/http_loader.rs2
5 files changed, 405 insertions, 27 deletions
diff --git a/components/devtools/actors/network_event.rs b/components/devtools/actors/network_event.rs
index 262e1e4696b..317dc096157 100644
--- a/components/devtools/actors/network_event.rs
+++ b/components/devtools/actors/network_event.rs
@@ -12,17 +12,21 @@ use actor::{Actor, ActorMessageStatus, ActorRegistry};
use devtools_traits::HttpRequest as DevtoolsHttpRequest;
use devtools_traits::HttpResponse as DevtoolsHttpResponse;
use hyper::header::Headers;
+use hyper::header::{ContentType, Cookie};
use hyper::http::RawStatus;
use hyper::method::Method;
use protocol::JsonPacketStream;
use rustc_serialize::json;
use std::net::TcpStream;
+use time;
+use time::Tm;
struct HttpRequest {
url: String,
method: Method,
headers: Headers,
body: Option<Vec<u8>>,
+ startedDateTime: Tm
}
struct HttpResponse {
@@ -48,6 +52,11 @@ pub struct EventActor {
}
#[derive(RustcEncodable)]
+pub struct ResponseCookiesMsg {
+ pub cookies: u32,
+}
+
+#[derive(RustcEncodable)]
pub struct ResponseStartMsg {
pub httpVersion: String,
pub remoteAddress: String,
@@ -59,6 +68,27 @@ pub struct ResponseStartMsg {
}
#[derive(RustcEncodable)]
+pub struct ResponseContentMsg {
+ pub mimeType: String,
+ pub contentSize: u32,
+ pub transferredSize: u32,
+ pub discardResponseBody: bool,
+}
+
+
+#[derive(RustcEncodable)]
+pub struct ResponseHeadersMsg {
+ pub headers: u32,
+ pub headersSize: u32,
+}
+
+
+#[derive(RustcEncodable)]
+pub struct RequestCookiesMsg {
+ pub cookies: u32,
+}
+
+#[derive(RustcEncodable)]
struct GetRequestHeadersReply {
from: String,
headers: Vec<String>,
@@ -66,6 +96,64 @@ struct GetRequestHeadersReply {
rawHeaders: String
}
+#[derive(RustcEncodable)]
+struct GetResponseHeadersReply {
+ from: String,
+ headers: Vec<String>,
+ headerSize: u8,
+ rawHeaders: String
+}
+
+#[derive(RustcEncodable)]
+struct GetResponseContentReply {
+ from: String,
+ content: Option<Vec<u8>>,
+ contentDiscarded: bool,
+}
+
+#[derive(RustcEncodable)]
+struct GetRequestPostDataReply {
+ from: String,
+ postData: Option<Vec<u8>>,
+ postDataDiscarded: bool
+}
+
+#[derive(RustcEncodable)]
+struct GetRequestCookiesReply {
+ from: String,
+ cookies: Vec<u8>
+}
+
+#[derive(RustcEncodable)]
+struct GetResponseCookiesReply {
+ from: String,
+ cookies: Vec<u8>
+}
+
+#[derive(RustcEncodable)]
+struct Timings {
+ blocked: u32,
+ dns: u32,
+ connect: u32,
+ send: u32,
+ wait: u32,
+ receive: u32,
+}
+
+#[derive(RustcEncodable)]
+struct GetEventTimingsReply {
+ from: String,
+ timings: Timings,
+ totalTime: u32,
+}
+
+#[derive(RustcEncodable)]
+struct GetSecurityInfoReply {
+ from: String,
+ seuritInfo: String,
+}
+
+
impl Actor for NetworkEventActor {
fn name(&self) -> String {
self.name.clone()
@@ -79,29 +167,124 @@ impl Actor for NetworkEventActor {
Ok(match msg_type {
"getRequestHeaders" => {
// TODO: Pass the correct values for headers, headerSize, rawHeaders
+ let headersSize = self.request.headers.len() as u8;
+ let mut headerNames = Vec::new();
+ let mut rawHeadersString = "".to_owned();
+ for item in self.request.headers.iter() {
+ let name = item.name();
+ let value = item.value_string();
+ headerNames.push(name.to_owned());
+ rawHeadersString = rawHeadersString + name + ":" + &value + "\r\n";
+ }
let msg = GetRequestHeadersReply {
from: self.name(),
- headers: Vec::new(),
- headerSize: 10,
- rawHeaders: "Raw headers".to_owned(),
+ headers: headerNames,
+ headerSize: headersSize,
+ rawHeaders: rawHeadersString,
};
stream.write_json_packet(&msg);
ActorMessageStatus::Processed
}
"getRequestCookies" => {
- ActorMessageStatus::Ignored
+ let mut cookies = Vec::new();
+ if let Some(req_cookies) = self.request.headers.get_raw("Cookie") {
+ for cookie in &*req_cookies {
+ if let Ok(cookie_value) = String::from_utf8(cookie.clone()) {
+ cookies = cookie_value.into_bytes();
+ }
+ }
+ }
+
+ let msg = GetRequestCookiesReply {
+ from: self.name(),
+ cookies: cookies,
+ };
+ stream.write_json_packet(&msg);
+ ActorMessageStatus::Processed
}
"getRequestPostData" => {
- ActorMessageStatus::Ignored
+ let msg = GetRequestPostDataReply {
+ from: self.name(),
+ postData: self.request.body.clone(),
+ postDataDiscarded: false,
+ };
+ stream.write_json_packet(&msg);
+ ActorMessageStatus::Processed
}
"getResponseHeaders" => {
- ActorMessageStatus::Ignored
+ if let Some(ref headers) = self.response.headers {
+ let headersSize = headers.len() as u8;
+ let mut headerNames = Vec::new();
+ let mut rawHeadersString = "".to_owned();
+ for item in headers.iter() {
+ let name = item.name();
+ let value = item.value_string();
+ headerNames.push(name.to_owned());
+ rawHeadersString = rawHeadersString + name + ":" + &value + "\r\n";
+ }
+ let msg = GetResponseHeadersReply {
+ from: self.name(),
+ headers: headerNames,
+ headerSize: headersSize,
+ rawHeaders: rawHeadersString,
+ };
+ stream.write_json_packet(&msg);
+ }
+ ActorMessageStatus::Processed
}
"getResponseCookies" => {
- ActorMessageStatus::Ignored
+ let mut cookies = Vec::new();
+ if let Some(res_cookies) = self.request.headers.get_raw("set-cookie") {
+ for cookie in &*res_cookies {
+ if let Ok(cookie_value) = String::from_utf8(cookie.clone()) {
+ cookies = cookie_value.into_bytes();
+ }
+ }
+ }
+
+ let msg = GetResponseCookiesReply {
+ from: self.name(),
+ cookies: cookies,
+ };
+ stream.write_json_packet(&msg);
+ ActorMessageStatus::Processed
}
"getResponseContent" => {
- ActorMessageStatus::Ignored
+ let msg = GetResponseContentReply {
+ from: self.name(),
+ content: self.response.body.clone(),
+ contentDiscarded: false,
+ };
+ stream.write_json_packet(&msg);
+ ActorMessageStatus::Processed
+ }
+ "getEventTimings" => {
+ // TODO: This is a fake timings msg
+ let timingsObj = Timings {
+ blocked: 0,
+ dns: 0,
+ connect: 0,
+ send: 0,
+ wait: 0,
+ receive: 0,
+ };
+ // TODO: Send the correct values for all these fields.
+ let msg = GetEventTimingsReply {
+ from: self.name(),
+ timings: timingsObj,
+ totalTime: 0,
+ };
+ stream.write_json_packet(&msg);
+ ActorMessageStatus::Processed
+ }
+ "getSecurityInfo" => {
+ // TODO: Send the correct values for securityInfo.
+ let msg = GetSecurityInfoReply {
+ from: self.name(),
+ seuritInfo: "".to_owned(),
+ };
+ stream.write_json_packet(&msg);
+ ActorMessageStatus::Processed
}
_ => ActorMessageStatus::Ignored
})
@@ -116,7 +299,8 @@ impl NetworkEventActor {
url: String::new(),
method: Method::Get,
headers: Headers::new(),
- body: None
+ body: None,
+ startedDateTime: time::now(),
},
response: HttpResponse {
headers: None,
@@ -131,6 +315,7 @@ impl NetworkEventActor {
self.request.method = request.method.clone();
self.request.headers = request.headers.clone();
self.request.body = request.body;
+ self.request.startedDateTime = request.startedDateTime;
}
pub fn add_response(&mut self, response: DevtoolsHttpResponse) {
@@ -145,7 +330,7 @@ impl NetworkEventActor {
actor: self.name(),
url: self.request.url.clone(),
method: format!("{}", self.request.method),
- startedDateTime: "2015-04-22T20:47:08.545Z".to_owned(),
+ startedDateTime: format!("{}", self.request.startedDateTime.rfc3339()),
isXHR: false,
private: false,
}
@@ -153,15 +338,83 @@ impl NetworkEventActor {
pub fn response_start(&self) -> ResponseStartMsg {
// TODO: Send the correct values for all these fields.
- // This is a fake message.
+ let hSizeOption = self.response.headers.as_ref().map(|headers| headers.len() as u32);
+ let hSize = hSizeOption.unwrap_or(0);
+ let (status_code, status_message) =
+ self.response.status.as_ref().map(|&RawStatus(ref code, ref text)| (*code, text.clone().into_owned())).
+ unwrap_or((0, "".to_owned()));
+ // TODO: Send the correct values for remoteAddress and remotePort and http_version.
ResponseStartMsg {
httpVersion: "HTTP/1.1".to_owned(),
remoteAddress: "63.245.217.43".to_owned(),
remotePort: 443,
- status: "200".to_owned(),
- statusText: "OK".to_owned(),
- headersSize: 337,
- discardResponseBody: true
+ status: status_code.to_string(),
+ statusText: status_message,
+ headersSize: hSize,
+ discardResponseBody: false
}
}
+
+ pub fn response_content(&self) -> ResponseContentMsg {
+ let mut mString = "".to_owned();
+ if let Some(ref headers) = self.response.headers {
+ mString = match headers.get() {
+ Some(&ContentType(ref mime)) => mime.to_string(),
+ None => "".to_owned()
+ };
+ }
+ // TODO: Set correct values when response's body is sent to the devtools in http_loader.
+ ResponseContentMsg {
+ mimeType: mString,
+ contentSize: 0,
+ transferredSize: 0,
+ discardResponseBody: false,
+ }
+ }
+
+ pub fn response_cookies(&self) -> ResponseCookiesMsg {
+
+ let mut cookies_size = 0;
+ if let Some(ref headers) = self.response.headers {
+ cookies_size = match headers.get() {
+ Some(&Cookie(ref cookie)) => cookie.len(),
+ None => 0
+ };
+ }
+ ResponseCookiesMsg {
+ cookies: cookies_size as u32,
+ }
+ }
+
+ pub fn response_headers(&self) -> ResponseHeadersMsg {
+
+ let mut headers_size = 0;
+ let mut headers_byte_count = 0;
+ if let Some(ref headers) = self.response.headers {
+ headers_size = headers.len() as u32;
+ for item in headers.iter() {
+ headers_byte_count += item.name().len() + item.value_string().len();
+ }
+
+ }
+ ResponseHeadersMsg {
+ headers: headers_size,
+ headersSize: headers_byte_count as u32,
+ }
+ }
+
+ pub fn request_cookies(&self) -> RequestCookiesMsg {
+
+ let mut cookies_size = 0;
+ if let Some(ref headers) = self.response.headers {
+ cookies_size = match headers.get() {
+ Some(&Cookie(ref cookie)) => cookie.len(),
+ None => 0
+ };
+ }
+ RequestCookiesMsg {
+ cookies: cookies_size as u32,
+ }
+ }
+
}
diff --git a/components/devtools/lib.rs b/components/devtools/lib.rs
index 5d1a34b52e9..85d360e701c 100644
--- a/components/devtools/lib.rs
+++ b/components/devtools/lib.rs
@@ -35,7 +35,8 @@ use actor::{Actor, ActorRegistry};
use actors::console::ConsoleActor;
use actors::framerate::FramerateActor;
use actors::inspector::InspectorActor;
-use actors::network_event::{EventActor, NetworkEventActor, ResponseStartMsg};
+use actors::network_event::{EventActor, NetworkEventActor, RequestCookiesMsg, ResponseCookiesMsg };
+use actors::network_event::{ResponseContentMsg, ResponseHeadersMsg, ResponseStartMsg };
use actors::performance::PerformanceActor;
use actors::profiler::ProfilerActor;
use actors::root::RootActor;
@@ -102,13 +103,61 @@ struct NetworkEventMsg {
}
#[derive(RustcEncodable)]
-struct NetworkEventUpdateMsg {
+struct ResponseStartUpdateMsg {
from: String,
__type__: String,
updateType: String,
response: ResponseStartMsg,
}
+#[derive(RustcEncodable)]
+struct ResponseContentUpdateMsg {
+ from: String,
+ __type__: String,
+ updateType: String,
+ responseContent: ResponseContentMsg,
+}
+
+#[derive(RustcEncodable)]
+struct ResponseCookiesUpdateMsg {
+ from: String,
+ __type__: String,
+ updateType: String,
+ responseCookies: ResponseCookiesMsg,
+}
+
+#[derive(RustcEncodable)]
+struct ResponseHeadersUpdateMsg {
+ from: String,
+ __type__: String,
+ updateType: String,
+ responseHeaders: ResponseHeadersMsg,
+}
+
+#[derive(RustcEncodable)]
+struct RequestCookiesUpdateMsg {
+ from: String,
+ __type__: String,
+ updateType: String,
+ requestcookies: RequestCookiesMsg,
+}
+
+#[derive(RustcEncodable)]
+struct EventTimingsUpdateMsg {
+ from: String,
+ __type__: String,
+ updateType: String,
+ totalTime: u32,
+}
+
+#[derive(RustcEncodable)]
+struct SecurityInfoUpdateMsg {
+ from: String,
+ __type__: String,
+ updateType: String,
+ securityState: String,
+}
+
/// Spin up a devtools server that listens for connections on the specified port.
pub fn start_server(port: u16) -> Sender<DevtoolsControlMsg> {
let (sender, receiver) = channel();
@@ -348,14 +397,25 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
for stream in &mut connections {
stream.write_json_packet(&msg);
}
+
}
NetworkEvent::HttpResponse(httpresponse) => {
//Store the response information in the actor
actor.add_response(httpresponse);
+ let msg7 = RequestCookiesUpdateMsg {
+ from: netevent_actor_name.clone(),
+ __type__: "networkEventUpdate".to_owned(),
+ updateType: "requestCookies".to_owned(),
+ requestcookies: actor.request_cookies(),
+ };
+ for stream in &mut connections {
+ stream.write_json_packet(&msg7);
+ }
+
//Send a networkEventUpdate (responseStart) to the client
- let msg = NetworkEventUpdateMsg {
- from: netevent_actor_name,
+ let msg = ResponseStartUpdateMsg {
+ from: netevent_actor_name.clone(),
__type__: "networkEventUpdate".to_owned(),
updateType: "responseStart".to_owned(),
response: actor.response_start()
@@ -364,9 +424,62 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
for stream in &mut connections {
stream.write_json_packet(&msg);
}
+ let msg2 = EventTimingsUpdateMsg {
+ from: netevent_actor_name.clone(),
+ __type__: "networkEventUpdate".to_owned(),
+ updateType: "eventTimings".to_owned(),
+ totalTime: 0
+ };
+
+ for stream in &mut connections {
+ stream.write_json_packet(&msg2);
+ }
+
+ let msg3 = SecurityInfoUpdateMsg {
+ from: netevent_actor_name.clone(),
+ __type__: "networkEventUpdate".to_owned(),
+ updateType: "securityInfo".to_owned(),
+ securityState: "".to_owned(),
+ };
+
+ for stream in &mut connections {
+ stream.write_json_packet(&msg3);
+ }
+
+ let msg4 = ResponseContentUpdateMsg {
+ from: netevent_actor_name.clone(),
+ __type__: "networkEventUpdate".to_owned(),
+ updateType: "responseContent".to_owned(),
+ responseContent: actor.response_content(),
+ };
+
+ for stream in &mut connections {
+ stream.write_json_packet(&msg4);
+ }
+
+ let msg5 = ResponseCookiesUpdateMsg {
+ from: netevent_actor_name.clone(),
+ __type__: "networkEventUpdate".to_owned(),
+ updateType: "responseCookies".to_owned(),
+ responseCookies: actor.response_cookies(),
+ };
+
+ for stream in &mut connections {
+ stream.write_json_packet(&msg5);
+ }
+
+ let msg6 = ResponseHeadersUpdateMsg {
+ from: netevent_actor_name.clone(),
+ __type__: "networkEventUpdate".to_owned(),
+ updateType: "responseHeaders".to_owned(),
+ responseHeaders: actor.response_headers(),
+ };
+
+ for stream in &mut connections {
+ stream.write_json_packet(&msg6);
+ }
+
}
- //TODO: Send the other types of update messages at appropriate times
- // requestHeaders, requestCookies, responseHeaders, securityInfo, etc
}
}
diff --git a/components/devtools_traits/lib.rs b/components/devtools_traits/lib.rs
index 9b43581b72a..b914e8dfda2 100644
--- a/components/devtools_traits/lib.rs
+++ b/components/devtools_traits/lib.rs
@@ -34,6 +34,7 @@ use msg::constellation_msg::PipelineId;
use rustc_serialize::{Decodable, Decoder};
use std::net::TcpStream;
use time::Duration;
+use time::Tm;
use url::Url;
// Information would be attached to NewGlobal to be received and show in devtools.
@@ -264,6 +265,7 @@ pub struct HttpRequest {
pub headers: Headers,
pub body: Option<Vec<u8>>,
pub pipeline_id: PipelineId,
+ pub startedDateTime: Tm
}
#[derive(Debug, PartialEq)]
diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs
index d222e6fb11d..3a64c959570 100644
--- a/components/net/http_loader.rs
+++ b/components/net/http_loader.rs
@@ -37,6 +37,8 @@ use std::error::Error;
use std::io::{self, Read, Write};
use std::sync::mpsc::Sender;
use std::sync::{Arc, RwLock};
+use time;
+use time::Tm;
use url::Url;
use util::resource_files::resources_dir_path;
use util::task::spawn_named;
@@ -174,7 +176,9 @@ pub trait HttpResponse: Read {
fn headers(&self) -> &Headers;
fn status(&self) -> StatusCode;
fn status_raw(&self) -> &RawStatus;
-
+ fn http_version(&self) -> String {
+ return "HTTP/1.1".to_owned()
+ }
fn content_encoding(&self) -> Option<Encoding> {
self.headers().get::<ContentEncoding>().and_then(|h| {
match *h {
@@ -192,6 +196,7 @@ pub trait HttpResponse: Read {
}
}
+
struct WrappedHttpResponse {
response: Response
}
@@ -203,6 +208,8 @@ impl Read for WrappedHttpResponse {
}
}
+
+
impl HttpResponse for WrappedHttpResponse {
fn headers(&self) -> &Headers {
&self.response.headers
@@ -215,6 +222,10 @@ impl HttpResponse for WrappedHttpResponse {
fn status_raw(&self) -> &RawStatus {
self.response.status_raw()
}
+
+ fn http_version(&self) -> String {
+ self.response.version.to_string()
+ }
}
pub trait HttpRequestFactory {
@@ -468,11 +479,11 @@ fn send_request_to_devtools(devtools_chan: Option<Sender<DevtoolsControlMsg>>,
method: Method,
headers: Headers,
body: Option<Vec<u8>>,
- pipeline_id: PipelineId) {
+ pipeline_id: PipelineId, now: Tm) {
if let Some(ref chan) = devtools_chan {
let request = DevtoolsHttpRequest {
- url: url, method: method, headers: headers, body: body, pipeline_id: pipeline_id };
+ url: url, method: method, headers: headers, body: body, pipeline_id: pipeline_id, startedDateTime: now };
let net_event = NetworkEvent::HttpRequest(request);
let msg = ChromeToDevtoolsControlMsg::NetworkEvent(request_id, net_event);
@@ -660,12 +671,11 @@ pub fn load<A>(load_data: LoadData,
req.send(&None)
}
};
-
if let Some(pipeline_id) = load_data.pipeline_id {
send_request_to_devtools(
devtools_chan.clone(), request_id.clone(), url.clone(),
method.clone(), request_headers.clone(),
- cloned_data, pipeline_id
+ cloned_data, pipeline_id, time::now()
);
}
diff --git a/tests/unit/net/http_loader.rs b/tests/unit/net/http_loader.rs
index ed541b67046..75f334cd487 100644
--- a/tests/unit/net/http_loader.rs
+++ b/tests/unit/net/http_loader.rs
@@ -460,13 +460,13 @@ fn test_request_and_response_data_with_network_messages() {
]);
headers.set(accept);
headers.set(UserAgent(DEFAULT_USER_AGENT.to_owned()));
-
let httprequest = DevtoolsHttpRequest {
url: url,
method: Method::Get,
headers: headers,
body: None,
pipeline_id: pipeline_id,
+ startedDateTime: devhttprequest.startedDateTime
};
let content = "Yay!";