Skip to content

Commit

Permalink
fix(cmn): upload() return value handling
Browse files Browse the repository at this point in the history
Now deals with Cancellation and non-OK status codes correctly.

Fixes #18
  • Loading branch information
Byron committed Mar 22, 2015
1 parent 29ee94b commit cd1ff18
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 24 deletions.
1 change: 1 addition & 0 deletions gen/groupsmigration1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ match result {
Result::HttpError(err) => println!("HTTPERROR: {:?}", err),
Result::MissingAPIKey => println!("Auth: Missing API Key - used if there are no scopes"),
Result::MissingToken => println!("OAuth2: Missing Token"),
Result::Cancelled => println!("Operation cancelled by user"),
Result::UploadSizeLimitExceeded(size, max_size) => println!("Upload size too big: {} of {}", size, max_size),
Result::Failure(_) => println!("General Failure (hyper::client::Response doesn't print)"),
Result::FieldClash(clashed_field) => println!("You added custom parameter which is part of builder: {:?}", clashed_field),
Expand Down
24 changes: 16 additions & 8 deletions gen/groupsmigration1/src/cmn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,9 @@ pub enum Result<T = ()> {
/// We required a Token, but didn't get one from the Authenticator
MissingToken,

/// The delgate instructed to cancel the operation
Cancelled,

/// An additional, free form field clashed with one of the built-in optional ones
FieldClash(&'static str),

Expand Down Expand Up @@ -536,12 +539,15 @@ impl<'a, NC, A> ResumableUploadHelper<'a, NC, A>
}
}

pub fn upload(&mut self) -> hyper::HttpResult<hyper::client::Response> {
/// returns None if operation was cancelled by delegate, or the HttpResult.
/// It can be that we return the result just because we didn't understand the status code -
/// caller should check for status himself before assuming it's OK to use
pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> {
let mut start = match self.start_at {
Some(s) => s,
None => match self.query_transfer_status() {
(Some(s), _) => s,
(_, result) => return result
(_, result) => return Some(result)
}
};

Expand All @@ -565,32 +571,34 @@ impl<'a, NC, A> ResumableUploadHelper<'a, NC, A>
};
start += request_size;
if self.delegate.cancel_chunk_upload(&range_header) {
return Err(hyper::error::HttpError::HttpStatusError)
return None
}
match self.client.post(self.url)
.header(range_header)
.header(ContentType(self.media_type.clone()))
.header(UserAgent(self.user_agent.to_string()))
.body(&mut section_reader)
.send() {
Ok(res) => {
Ok(mut res) => {
if res.status == StatusCode::PermanentRedirect {
continue
}
if res.status != StatusCode::Ok {
if let Retry::After(d) = self.delegate.http_failure(&res, None) {
if !res.status.is_success() {
let mut json_err = String::new();
res.read_to_string(&mut json_err).unwrap();
if let Retry::After(d) = self.delegate.http_failure(&res, serde::json::from_str(&json_err).ok()) {
sleep(d);
continue;
}
}
return Ok(res)
return Some(Ok(res))
},
Err(err) => {
if let Retry::After(d) = self.delegate.http_error(&err) {
sleep(d);
continue;
}
return Err(err)
return Some(Err(err))
}
}
}
Expand Down
19 changes: 15 additions & 4 deletions gen/groupsmigration1/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
//! Result::HttpError(err) => println!("HTTPERROR: {:?}", err),
//! Result::MissingAPIKey => println!("Auth: Missing API Key - used if there are no scopes"),
//! Result::MissingToken => println!("OAuth2: Missing Token"),
//! Result::Cancelled => println!("Operation cancelled by user"),
//! Result::UploadSizeLimitExceeded(size, max_size) => println!("Upload size too big: {} of {}", size, max_size),
//! Result::Failure(_) => println!("General Failure (hyper::client::Response doesn't print)"),
//! Result::FieldClash(clashed_field) => println!("You added custom parameter which is part of builder: {:?}", clashed_field),
Expand Down Expand Up @@ -266,6 +267,7 @@ impl Default for Scope {
/// Result::HttpError(err) => println!("HTTPERROR: {:?}", err),
/// Result::MissingAPIKey => println!("Auth: Missing API Key - used if there are no scopes"),
/// Result::MissingToken => println!("OAuth2: Missing Token"),
/// Result::Cancelled => println!("Operation cancelled by user"),
/// Result::UploadSizeLimitExceeded(size, max_size) => println!("Upload size too big: {} of {}", size, max_size),
/// Result::Failure(_) => println!("General Failure (hyper::client::Response doesn't print)"),
/// Result::FieldClash(clashed_field) => println!("You added custom parameter which is part of builder: {:?}", clashed_field),
Expand Down Expand Up @@ -583,8 +585,7 @@ impl<'a, C, NC, A> ArchiveInsertCall<'a, C, NC, A> where NC: hyper::net::Network
if !res.status.is_success() {
let mut json_err = String::new();
res.read_to_string(&mut json_err).unwrap();
let error_info: cmn::JsonServerError = json::from_str(&json_err).unwrap();
if let oauth2::Retry::After(d) = dlg.http_failure(&res, Some(error_info)) {
if let oauth2::Retry::After(d) = dlg.http_failure(&res, json::from_str(&json_err).ok()) {
sleep(d);
continue;
}
Expand Down Expand Up @@ -618,11 +619,21 @@ impl<'a, C, NC, A> ArchiveInsertCall<'a, C, NC, A> where NC: hyper::net::Network
}.upload()
};
match upload_result {
Err(err) => {
None => {
dlg.finished(false);
return Result::Cancelled
}
Some(Err(err)) => {
dlg.finished(false);
return Result::HttpError(err)
}
Ok(upload_result) => res = upload_result,
Some(Ok(upload_result)) => {
res = upload_result;
if !res.status.is_success() {
dlg.finished(false);
return Result::Failure(res)
}
}
}
}
let result_value = {
Expand Down
19 changes: 15 additions & 4 deletions src/mako/lib/mbuild.mako
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ match result {
Result::HttpError(err) => println!("HTTPERROR: {:?}", err),
Result::MissingAPIKey => println!("Auth: Missing API Key - used if there are no scopes"),
Result::MissingToken => println!("OAuth2: Missing Token"),
Result::Cancelled => println!("Operation cancelled by user"),
Result::UploadSizeLimitExceeded(size, max_size) => println!("Upload size too big: {} of {}", size, max_size),
Result::Failure(_) => println!("General Failure (hyper::client::Response doesn't print)"),
Result::FieldClash(clashed_field) => println!("You added custom parameter which is part of builder: {:?}", clashed_field),
Expand Down Expand Up @@ -760,8 +761,7 @@ else {
if !res.status.is_success() {
let mut json_err = String::new();
res.read_to_string(&mut json_err).unwrap();
let error_info: cmn::JsonServerError = json::from_str(&json_err).unwrap();
if let oauth2::Retry::After(d) = dlg.http_failure(&res, Some(error_info)) {
if let oauth2::Retry::After(d) = dlg.http_failure(&res, json::from_str(&json_err).ok()) {
sleep(d);
continue;
}
Expand Down Expand Up @@ -792,14 +792,25 @@ else {
}.upload()
};
match upload_result {
Err(err) => {
None => {
${delegate_finish}(false);
return Result::Cancelled
}
Some(Err(err)) => {
## Do not ask the delgate again, as it was asked by the helper !
${delegate_finish}(false);
return Result::HttpError(err)
}
## Now the result contains the actual resource, if any ... it will be
## decoded next
Ok(upload_result) => res = upload_result,
Some(Ok(upload_result)) => {
res = upload_result;
if !res.status.is_success() {
## delegate was called in upload() already - don't tell him again
${delegate_finish}(false);
return Result::Failure(res)
}
}
}
}
% endif
Expand Down
24 changes: 16 additions & 8 deletions src/rust/cmn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ pub enum Result<T = ()> {
/// We required a Token, but didn't get one from the Authenticator
MissingToken,

/// The delgate instructed to cancel the operation
Cancelled,

/// An additional, free form field clashed with one of the built-in optional ones
FieldClash(&'static str),

Expand Down Expand Up @@ -534,12 +537,15 @@ impl<'a, NC, A> ResumableUploadHelper<'a, NC, A>
}
}

pub fn upload(&mut self) -> hyper::HttpResult<hyper::client::Response> {
/// returns None if operation was cancelled by delegate, or the HttpResult.
/// It can be that we return the result just because we didn't understand the status code -
/// caller should check for status himself before assuming it's OK to use
pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> {
let mut start = match self.start_at {
Some(s) => s,
None => match self.query_transfer_status() {
(Some(s), _) => s,
(_, result) => return result
(_, result) => return Some(result)
}
};

Expand All @@ -563,32 +569,34 @@ impl<'a, NC, A> ResumableUploadHelper<'a, NC, A>
};
start += request_size;
if self.delegate.cancel_chunk_upload(&range_header) {
return Err(hyper::error::HttpError::HttpStatusError)
return None
}
match self.client.post(self.url)
.header(range_header)
.header(ContentType(self.media_type.clone()))
.header(UserAgent(self.user_agent.to_string()))
.body(&mut section_reader)
.send() {
Ok(res) => {
Ok(mut res) => {
if res.status == StatusCode::PermanentRedirect {
continue
}
if res.status != StatusCode::Ok {
if let Retry::After(d) = self.delegate.http_failure(&res, None) {
if !res.status.is_success() {
let mut json_err = String::new();
res.read_to_string(&mut json_err).unwrap();
if let Retry::After(d) = self.delegate.http_failure(&res, serde::json::from_str(&json_err).ok()) {
sleep(d);
continue;
}
}
return Ok(res)
return Some(Ok(res))
},
Err(err) => {
if let Retry::After(d) = self.delegate.http_error(&err) {
sleep(d);
continue;
}
return Err(err)
return Some(Err(err))
}
}
}
Expand Down

0 comments on commit cd1ff18

Please sign in to comment.