diff --git a/Cargo.lock b/Cargo.lock index f5cba5341..88b38d469 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2396,6 +2396,7 @@ dependencies = [ "flate2 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 9176404e2..613fc8549 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,7 @@ ws = "0.9.0" url = "2.1.0" walkdir = "2.2.9" percent-encoding = "1.0.1" +http = "0.1.1" [dev-dependencies] assert_cmd = "0.11.1" diff --git a/src/commands/kv/delete_bulk.rs b/src/commands/kv/delete_bulk.rs index 3fbf6a112..6c37398e2 100644 --- a/src/commands/kv/delete_bulk.rs +++ b/src/commands/kv/delete_bulk.rs @@ -12,6 +12,8 @@ use failure::bail; use crate::terminal::message; +const MAX_PAIRS: usize = 10000; + pub fn delete_bulk(namespace_id: &str, filename: &Path) -> Result<(), failure::Error> { let client = super::api_client()?; let account_id = super::account_id()?; @@ -36,10 +38,21 @@ pub fn delete_bulk(namespace_id: &str, filename: &Path) -> Result<(), failure::E Err(e) => bail!(e), }; + // Validate that bulk delete is within API constraints + let keys = keys?; + // Check number of pairs is under limit + if keys.len() > MAX_PAIRS { + bail!( + "Number of keys to delete ({}) exceeds max of {}", + keys.len(), + MAX_PAIRS + ); + } + let response = client.request(&DeleteBulk { account_identifier: &account_id, namespace_identifier: namespace_id, - bulk_keys: keys?, + bulk_keys: keys, }); match response { diff --git a/src/commands/kv/mod.rs b/src/commands/kv/mod.rs index e9b0819bb..e15bbbad3 100644 --- a/src/commands/kv/mod.rs +++ b/src/commands/kv/mod.rs @@ -4,6 +4,7 @@ use std::path::Path; use cloudflare::framework::auth::Credentials; use cloudflare::framework::response::ApiFailure; use cloudflare::framework::HttpApiClient; +use http::status::StatusCode; use failure::bail; use crate::settings; @@ -48,7 +49,8 @@ fn account_id() -> Result { fn print_error(e: ApiFailure) { match e { - ApiFailure::Error(_status, api_errors) => { + ApiFailure::Error(status, api_errors) => { + give_status_code_context(status); for error in api_errors.errors { message::warn(&format!("Error {}: {}", error.code, error.message)); @@ -62,6 +64,15 @@ fn print_error(e: ApiFailure) { } } +// For handling cases where the API gateway returns errors via HTTP status codes +// (no KV error code is given). +fn give_status_code_context(status_code: StatusCode) { + match status_code { + StatusCode::PAYLOAD_TOO_LARGE => message::warn("Returned status code 413, Payload Too Large. Make sure your upload is less than 100MB in size"), + _ => (), + } +} + fn help(error_code: u16) -> &'static str { // https://api.cloudflare.com/#workers-kv-namespace-errors match error_code { diff --git a/src/commands/kv/write_bulk.rs b/src/commands/kv/write_bulk.rs index 41f209b07..072b63f3a 100644 --- a/src/commands/kv/write_bulk.rs +++ b/src/commands/kv/write_bulk.rs @@ -13,6 +13,8 @@ use failure::bail; use crate::terminal::message; +const MAX_PAIRS: usize = 10000; + pub fn write_bulk(namespace_id: &str, filename: &Path) -> Result<(), failure::Error> { let client = super::api_client()?; let account_id = super::account_id()?; @@ -38,10 +40,22 @@ pub fn write_bulk(namespace_id: &str, filename: &Path) -> Result<(), failure::Er Err(e) => bail!(e), }; + // Validate that bulk upload is within size constraints + let pairs = pairs?; + if pairs.len() > MAX_PAIRS { + bail!( + "Number of key-value pairs to upload ({}) exceeds max of {}", + pairs.len(), + MAX_PAIRS + ); + } + + message::working("Parsing successful. Uploading all files above"); + let response = client.request(&WriteBulk { account_identifier: &account_id, namespace_identifier: namespace_id, - bulk_key_value_pairs: pairs?, + bulk_key_value_pairs: pairs, }); match response { @@ -64,7 +78,7 @@ fn parse_directory(directory: &Path) -> Result, failure::Error // Need to base64 encode value let b64_value = base64::encode(&value); - message::working(&format!("Uploading {}...", key.clone())); + message::working(&format!("Parsing {}...", key.clone())); upload_vec.push(KeyValuePair { key: key, value: b64_value,