Support responseCookies, responseContent, responseHeaders, requestCookies, getResponseHeaders,

getResponseContent, getRequestPostData, getRequestCookies, getResponseCookies, getEventTimings and
getSecurityInfo message for network devtools

Fixing Indentation
This commit is contained in:
Abhishek Kumar 2015-12-01 15:50:43 -05:00
parent 552df7e79e
commit f889b1ccd7
5 changed files with 405 additions and 27 deletions

View file

@ -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 {
@ -47,6 +51,11 @@ pub struct EventActor {
pub private: bool
}
#[derive(RustcEncodable)]
pub struct ResponseCookiesMsg {
pub cookies: u32,
}
#[derive(RustcEncodable)]
pub struct ResponseStartMsg {
pub httpVersion: String,
@ -58,6 +67,27 @@ pub struct ResponseStartMsg {
pub discardResponseBody: bool,
}
#[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,
@ -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,
}
}
}

View file

@ -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
}
}

View file

@ -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)]

View file

@ -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()
);
}

View file

@ -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!";