Skip to content

Commit

Permalink
fixes #32
Browse files Browse the repository at this point in the history
add validation method to endpoint trait.
implement payload size validation for bulk write endpoint.
  • Loading branch information
amaceiras-rmn committed Sep 12, 2019
1 parent 6c27cf3 commit 0f67c59
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 3 deletions.
76 changes: 74 additions & 2 deletions src/endpoints/workerskv/write_bulk.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::framework::endpoint::{Endpoint, Method};

use crate::framework::{response::ApiFailure, response::ApiErrors, response::ApiError, endpoint::{Endpoint, Method}};
use reqwest;
use std::collections::HashMap;
/// Write Key-Value Pairs in Bulk
/// Writes multiple key-value pairs to Workers KV at once.
/// A 404 is returned if a write action is for a namespace ID the account doesn't have.
Expand All @@ -23,6 +24,26 @@ impl<'a> Endpoint<(), (), Vec<KeyValuePair>> for WriteBulk<'a> {
fn body(&self) -> Option<Vec<KeyValuePair>> {
Some(self.bulk_key_value_pairs.clone())
}
fn validate(&self) -> Result<(), ApiFailure> {
if let Some(body) = self.body() {
// this matches the serialization in HttpApiClient
let len = serde_json::to_string(&body).unwrap().len();
if len >= 100_000_000 {
return Err(ApiFailure::Error(
reqwest::StatusCode::PAYLOAD_TOO_LARGE,
ApiErrors {
errors: vec![ApiError {
code: 413,
message: "request payload too large, must be less than 100MB".to_owned(),
other: HashMap::new(),
}],
other: HashMap::new(),
},
));
}
}
Ok(())
}
// default content-type is already application/json
}

Expand All @@ -35,3 +56,54 @@ pub struct KeyValuePair {
pub expiration_ttl: Option<i64>,
pub base64: Option<bool>,
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn write_bulk_validator_failure() {
let write_bulk_endpoint = WriteBulk{
account_identifier: "test_account_id",
namespace_identifier: "test_namespace",
bulk_key_value_pairs: vec![
KeyValuePair {
key: "test".to_owned(),
value: "X".repeat(100_000_000),
expiration: None,
expiration_ttl: None,
base64: None
}
]
};

match write_bulk_endpoint.validate() {
Ok(_) => assert!(false, "payload too large and validator passed incorrectly"),
Err(_) => assert!(true)
}
}

#[test]
fn write_bulk_validator_success() {
let write_bulk_endpoint = WriteBulk{
account_identifier: "test_account_id",
namespace_identifier: "test_namespace",
bulk_key_value_pairs: vec![
KeyValuePair {
key: "test".to_owned(),
// max is 99,999,972 chars for the val
// the other 28 chars are taken by the key, property names, and json formatting chars
value: "x".repeat(99_999_950),
expiration: None,
expiration_ttl: None,
base64: None
}
]
};

match write_bulk_endpoint.validate() {
Ok(_) => assert!(true),
Err(_) => assert!(false, "payload within bounds and validator failed incorrectly")
}
}
}
7 changes: 7 additions & 0 deletions src/framework/endpoint.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use crate::framework::response::ApiResult;
use crate::framework::response::ApiFailure;
use crate::framework::Environment;

use serde::Serialize;
use url::Url;

Expand All @@ -11,6 +13,7 @@ pub enum Method {
Patch,
}


pub trait Endpoint<ResultType = (), QueryType = (), BodyType = ()>
where
ResultType: ApiResult,
Expand All @@ -25,6 +28,10 @@ where
fn body(&self) -> Option<BodyType> {
None
}
/// Some endpoints dont need to validate. That's OK.
fn validate(&self) -> Result<(), ApiFailure> {
Ok(())
}
fn url(&self, environment: &Environment) -> Url {
Url::from(environment).join(&self.path()).unwrap()
}
Expand Down
3 changes: 2 additions & 1 deletion src/framework/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ impl<'a> ApiClient for HttpApiClient {
}
}

endpoint.validate()?;

// Build the request
let mut request = self
.http_client
Expand All @@ -97,7 +99,6 @@ impl<'a> ApiClient for HttpApiClient {
request = request.auth(&self.credentials);

let response = request.send()?;

map_api_response(response)
}
}

0 comments on commit 0f67c59

Please sign in to comment.