Skip to content

Commit

Permalink
fix(CLI): simple and resumable upload works
Browse files Browse the repository at this point in the history
* fixed boundary syntax of multi-part message. Was --BOUNDARY, now is
  --BOUNDARY--
* Fixed ContentRange parsing and serialization. We actually managed
  to break it last time we tried to update it to match the Go
  implementation.
* fixed uploadType header parameter. It's based on chosen protocol and
  whether or not the method supports multipart operation for the given
  protocol.

Related to #76
  • Loading branch information
Byron committed Apr 25, 2015
1 parent 0bb30da commit 2f3b2d2
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 17 deletions.
24 changes: 16 additions & 8 deletions src/mako/api/lib/mbuild.mako
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,14 @@ match result {
% for p in field_params:
<%
pname = 'self.' + property(p.name) # property identifier
if media_params and 'mediaUpload' in m:
upload_type_map = dict()
for mp in media_params:
if mp.protocol == 'simple':
upload_type_map[mp.protocol] = m.mediaUpload.protocols.simple.multipart and 'multipart' or 'media'
break
# for each meadia param
# end build media param map
%>\
## parts can also be derived from the request, but we do that only if it's not set
% if p.name == 'part' and request_value:
Expand Down Expand Up @@ -561,21 +569,21 @@ match result {
% endif ## response schema
% if media_params:
let mut url = \
let (mut url, upload_type) =
% for mp in media_params:
% if loop.first:
if \
if \
% else:
else if \
% endif
protocol == "${mp.protocol}" {
"${join_url(rootUrl, mp.path)}".to_string()
("${join_url(rootUrl, mp.path)}".to_string(), "${upload_type_map.get(mp.protocol, mp.protocol)}")
} \
% endfor
else {
unreachable!()
};
params.push(("uploadType", protocol.to_string()));
};
params.push(("uploadType", upload_type.to_string()));
% else:
let mut url = "${baseUrl}${m.path}".to_string();
% endif
Expand Down Expand Up @@ -788,9 +796,9 @@ else {
${READER_SEEK | indent_all_but_first_by(6)}
let mut client = &mut *self.hub.client.borrow_mut();
let upload_result = {
let url = &res.headers.get::<Location>().expect("Location header is part of protocol").0;
let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0;
if upload_url_from_server {
dlg.store_upload_url(url);
dlg.store_upload_url(url_str);
}
cmn::ResumableUploadHelper {
Expand All @@ -800,7 +808,7 @@ else {
auth: &mut *self.hub.auth.borrow_mut(),
user_agent: &self.hub._user_agent,
auth_header: auth_header.clone(),
url: url,
url: url_str,
reader: &mut reader,
media_type: reader_mime_type.clone(),
content_length: size
Expand Down
6 changes: 3 additions & 3 deletions src/rust/api/cmn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ impl<'a> Read for MultiPartReader<'a> {
// before clearing the last part, we will add the boundary that
// will be written last
self.last_part_boundary = Some(Cursor::new(
format!("{}--{}", LINE_ENDING, BOUNDARY).into_bytes()))
format!("{}--{}--", LINE_ENDING, BOUNDARY).into_bytes()))
}
// We are depleted - this can trigger the next part to come in
self.current_part = None;
Expand Down Expand Up @@ -517,7 +517,7 @@ impl Header for ContentRange {

impl HeaderFormat for ContentRange {
fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
try!(fmt.write_str("bytes="));
try!(fmt.write_str("bytes "));
match self.range {
Some(ref c) => try!(c.fmt(fmt)),
None => try!(fmt.write_str("*"))
Expand All @@ -538,7 +538,7 @@ impl Header for RangeResponseHeader {
fn parse_header(raw: &[Vec<u8>]) -> Option<RangeResponseHeader> {
if let [ref v] = raw {
if let Ok(s) = std::str::from_utf8(v) {
const PREFIX: &'static str = "bytes=";
const PREFIX: &'static str = "bytes ";
if s.starts_with(PREFIX) {
if let Ok(c) = <Chunk as FromStr>::from_str(&s[PREFIX.len()..]) {
return Some(RangeResponseHeader(c))
Expand Down
11 changes: 5 additions & 6 deletions src/rust/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ mod test_api {
use self::hyper_mock::*;
use std::io::Read;
use std::default::Default;
use std::old_path::BytesContainer;
use hyper;
use std::str::FromStr;

Expand All @@ -38,9 +37,9 @@ Content-Length: 25\r\n\
Content-Type: application/plain\r\n\
\r\n\
bar\r\n\
--MDuXWGyeE33QFXGchb2VFWc4Z7945d";
--MDuXWGyeE33QFXGchb2VFWc4Z7945d--";

const EXPECTED_LEN: usize= 221;
const EXPECTED_LEN: usize= 223;

#[test]
fn multi_part_reader() {
Expand Down Expand Up @@ -130,9 +129,9 @@ bar\r\n\
#[test]
fn content_range() {
for &(ref c, ref expected) in
&[(ContentRange {range: None, total_length: 50 }, "Content-Range: bytes=*/50\r\n"),
&[(ContentRange {range: None, total_length: 50 }, "Content-Range: bytes */50\r\n"),
(ContentRange {range: Some(Chunk { first: 23, last: 40 }), total_length: 45},
"Content-Range: bytes=23-40/45\r\n")] {
"Content-Range: bytes 23-40/45\r\n")] {
let mut headers = hyper::header::Headers::new();
headers.set(c.clone());
assert_eq!(headers.to_string(), expected.to_string());
Expand All @@ -147,7 +146,7 @@ bar\r\n\

#[test]
fn parse_range_response() {
let r: RangeResponseHeader = hyper::header::Header::parse_header(&[b"bytes=2-42".to_vec()]).unwrap();
let r: RangeResponseHeader = hyper::header::Header::parse_header(&[b"bytes 2-42".to_vec()]).unwrap();
assert_eq!(r.0.first, 2);
assert_eq!(r.0.last, 42);
}
Expand Down

0 comments on commit 2f3b2d2

Please sign in to comment.