diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.rs | 1 | ||||
-rw-r--r-- | src/msg.fbs | 24 | ||||
-rw-r--r-- | src/msg_util.rs | 104 | ||||
-rw-r--r-- | src/ops.rs | 93 |
4 files changed, 155 insertions, 67 deletions
diff --git a/src/main.rs b/src/main.rs index 2c33583d0..6530c37fc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ extern crate dirs; extern crate flatbuffers; extern crate getopts; +extern crate http; extern crate hyper; extern crate hyper_rustls; extern crate libc; diff --git a/src/msg.fbs b/src/msg.fbs index 7fdc73946..2a9c013a3 100644 --- a/src/msg.fbs +++ b/src/msg.fbs @@ -194,18 +194,26 @@ table KeyValue { value: string; } -table Fetch { - id: uint; +// Note this represents The WHOLE header of an http message, not just the key +// value pairs. That means it includes method and url for Requests and status +// for responses. This is why it is singular "Header" instead of "Headers". +table HttpHeader { + is_request: bool; + // Request only: + method: string; url: string; - // TODO Supply request headers: - // header_line: [string]; + // Response only: + status: uint16; + // Both: + fields: [KeyValue]; +} + +table Fetch { + header: HttpHeader; } table FetchRes { - id: uint; - status: int; - header_key: [string]; - header_value: [string]; + header: HttpHeader; body_rid: uint32; } diff --git a/src/msg_util.rs b/src/msg_util.rs index d61be23f7..8634e2282 100644 --- a/src/msg_util.rs +++ b/src/msg_util.rs @@ -1,7 +1,18 @@ // Copyright 2018 the Deno authors. All rights reserved. MIT license. // Helpers for serialization. use flatbuffers; +use http::header::HeaderName; +use http::uri::Uri; +use http::Method; +use hyper::header::HeaderMap; +use hyper::header::HeaderValue; +use hyper::Body; +use hyper::Request; +use hyper::Response; use msg; +use std::str::FromStr; + +type Headers = HeaderMap<HeaderValue>; pub fn serialize_key_value<'bldr>( builder: &mut flatbuffers::FlatBufferBuilder<'bldr>, @@ -15,6 +26,99 @@ pub fn serialize_key_value<'bldr>( &msg::KeyValueArgs { key: Some(key), value: Some(value), + ..Default::default() + }, + ) +} + +pub fn serialize_request_header<'bldr>( + builder: &mut flatbuffers::FlatBufferBuilder<'bldr>, + r: &Request<Body>, +) -> flatbuffers::WIPOffset<msg::HttpHeader<'bldr>> { + let method = builder.create_string(r.method().as_str()); + let url = builder.create_string(r.uri().to_string().as_ref()); + + let mut fields = Vec::new(); + for (key, val) in r.headers().iter() { + let kv = serialize_key_value(builder, key.as_ref(), val.to_str().unwrap()); + fields.push(kv); + } + let fields = builder.create_vector(fields.as_ref()); + + msg::HttpHeader::create( + builder, + &msg::HttpHeaderArgs { + is_request: true, + method: Some(method), + url: Some(url), + fields: Some(fields), + ..Default::default() + }, + ) +} + +pub fn serialize_fields<'bldr>( + builder: &mut flatbuffers::FlatBufferBuilder<'bldr>, + headers: &Headers, +) -> flatbuffers::WIPOffset< + flatbuffers::Vector< + 'bldr, + flatbuffers::ForwardsUOffset<msg::KeyValue<'bldr>>, + >, +> { + let mut fields = Vec::new(); + for (key, val) in headers.iter() { + let kv = serialize_key_value(builder, key.as_ref(), val.to_str().unwrap()); + fields.push(kv); + } + return builder.create_vector(fields.as_ref()); +} + +// Not to be confused with serialize_response which has nothing to do with HTTP. +pub fn serialize_http_response<'bldr>( + builder: &mut flatbuffers::FlatBufferBuilder<'bldr>, + r: &Response<Body>, +) -> flatbuffers::WIPOffset<msg::HttpHeader<'bldr>> { + let status = r.status().as_u16(); + let fields = serialize_fields(builder, r.headers()); + msg::HttpHeader::create( + builder, + &msg::HttpHeaderArgs { + is_request: false, + status, + fields: Some(fields), + ..Default::default() }, ) } + +pub fn deserialize_request( + header_msg: msg::HttpHeader, + body: Body, +) -> Request<Body> { + let mut r = Request::new(body); + + assert!(header_msg.is_request() == true); + + let url = header_msg.url().unwrap(); + let uri = Uri::from_str(url).unwrap(); + *r.uri_mut() = uri; + + if let Some(method) = header_msg.method() { + let method = Method::from_str(method).unwrap(); + *r.method_mut() = method; + } + + if let Some(fields) = header_msg.fields() { + let headers = r.headers_mut(); + for i in 0..fields.len() { + let kv = fields.get(i); + let key = kv.key().unwrap(); + let name = HeaderName::from_bytes(key.as_bytes()).unwrap(); + let value = kv.value().unwrap(); + let v = HeaderValue::from_str(value).unwrap(); + headers.insert(name, v); + } + } + r +} diff --git a/src/ops.rs b/src/ops.rs index ef03630f5..d920d25cb 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -389,74 +389,49 @@ fn op_fetch( assert_eq!(data.len(), 0); let inner = base.inner_as_fetch().unwrap(); let cmd_id = base.cmd_id(); - let id = inner.id(); - let url = inner.url().unwrap(); + + let header = inner.header().unwrap(); + assert!(header.is_request()); + let url = header.url().unwrap(); + + let body = hyper::Body::empty(); + let req = msg_util::deserialize_request(header, body); if let Err(e) = state.check_net(url) { return odd_future(e); } - let url = url.parse::<hyper::Uri>().unwrap(); let client = http_util::get_client(); debug!("Before fetch {}", url); - let future = client.get(url).and_then(move |res| { - let status = i32::from(res.status().as_u16()); - debug!("fetch {}", status); - - let headers = { - let map = res.headers(); - let keys = map - .keys() - .map(|s| s.as_str().to_string()) - .collect::<Vec<_>>(); - let values = map - .values() - .map(|s| s.to_str().unwrap().to_string()) - .collect::<Vec<_>>(); - (keys, values) - }; - - let body = res.into_body(); - let body_resource = resources::add_hyper_body(body); - Ok((status, headers, body_resource)) - }); - - let future = future.map_err(|err| -> DenoError { err.into() }).and_then( - move |(status, headers, body_resource)| { - debug!("fetch body "); - let builder = &mut FlatBufferBuilder::new(); - // Send the first message without a body. This is just to indicate - // what status code. - let header_keys: Vec<&str> = headers.0.iter().map(|s| &**s).collect(); - let header_keys_off = - builder.create_vector_of_strings(header_keys.as_slice()); - let header_values: Vec<&str> = headers.1.iter().map(|s| &**s).collect(); - let header_values_off = - builder.create_vector_of_strings(header_values.as_slice()); - - let inner = msg::FetchRes::create( - builder, - &msg::FetchResArgs { - id, - status, - body_rid: body_resource.rid, - header_key: Some(header_keys_off), - header_value: Some(header_values_off), - }, - ); + let future = + client + .request(req) + .map_err(DenoError::from) + .and_then(move |res| { + let builder = &mut FlatBufferBuilder::new(); + let header_off = msg_util::serialize_http_response(builder, &res); + let body = res.into_body(); + let body_resource = resources::add_hyper_body(body); + let inner = msg::FetchRes::create( + builder, + &msg::FetchResArgs { + header: Some(header_off), + body_rid: body_resource.rid, + ..Default::default() + }, + ); - Ok(serialize_response( - cmd_id, - builder, - msg::BaseArgs { - inner: Some(inner.as_union_value()), - inner_type: msg::Any::FetchRes, - ..Default::default() - }, - )) - }, - ); + Ok(serialize_response( + cmd_id, + builder, + msg::BaseArgs { + inner: Some(inner.as_union_value()), + inner_type: msg::Any::FetchRes, + ..Default::default() + }, + )) + }); Box::new(future) } |