Skip to content

Commit

Permalink
fix: skip leading whitespace (#783)
Browse files Browse the repository at this point in the history
  • Loading branch information
polachok authored May 25, 2022
1 parent f2025ce commit 47d36b9
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 18 deletions.
4 changes: 3 additions & 1 deletion core/src/http_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ pub async fn read_body(
return Err(GenericTransportError::TooLarge);
}

let single = match first_chunk.get(0) {
let first_non_whitespace = first_chunk.iter().find(|byte| !byte.is_ascii_whitespace());

let single = match first_non_whitespace {
Some(b'{') => true,
Some(b'[') => false,
_ => return Err(GenericTransportError::Malformed),
Expand Down
26 changes: 18 additions & 8 deletions http-server/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,10 +275,6 @@ async fn garbage_request_fails() {
let response = http_request(req.into(), uri.clone()).await.unwrap();
assert_eq!(response.body, parse_error(Id::Null));

let req = r#" {"jsonrpc":"2.0","method":"add", "params":[1, 2],"id":1}"#;
let response = http_request(req.into(), uri.clone()).await.unwrap();
assert_eq!(response.body, parse_error(Id::Null));

let req = r#"{}"#;
let response = http_request(req.into(), uri.clone()).await.unwrap();
assert_eq!(response.body, parse_error(Id::Null));
Expand All @@ -295,10 +291,6 @@ async fn garbage_request_fails() {
let response = http_request(req.into(), uri.clone()).await.unwrap();
assert_eq!(response.body, parse_error(Id::Null));

let req = r#" [{"jsonrpc":"2.0","method":"add", "params":[1, 2],"id":1}]"#;
let response = http_request(req.into(), uri.clone()).await.unwrap();
assert_eq!(response.body, parse_error(Id::Null));

let req = r#"[]"#;
let response = http_request(req.into(), uri.clone()).await.unwrap();
assert_eq!(response.body, invalid_request(Id::Null));
Expand All @@ -308,6 +300,24 @@ async fn garbage_request_fails() {
assert_eq!(response.body, parse_error(Id::Null));
}

#[tokio::test]
async fn whitespace_is_not_significant() {
let (addr, _handle) = server().with_default_timeout().await.unwrap();
let uri = to_http_uri(addr);

let req = r#" {"jsonrpc":"2.0","method":"add", "params":[1, 2],"id":1}"#;
let response = http_request(req.into(), uri.clone()).await.unwrap();
let expected = r#"{"jsonrpc":"2.0","result":3,"id":1}"#;
assert_eq!(response.status, StatusCode::OK);
assert_eq!(response.body, expected);

let req = r#" [{"jsonrpc":"2.0","method":"add", "params":[1, 2],"id":1}]"#;
let response = http_request(req.into(), uri.clone()).await.unwrap();
let expected = r#"[{"jsonrpc":"2.0","result":3,"id":1}]"#;
assert_eq!(response.status, StatusCode::OK);
assert_eq!(response.body, expected);
}

#[tokio::test]
async fn should_return_method_not_found() {
let (addr, _handle) = server().with_default_timeout().await.unwrap();
Expand Down
4 changes: 3 additions & 1 deletion ws-server/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,9 @@ async fn background_task(

let request_start = middleware.on_request();

match data.get(0) {
let first_non_whitespace = data.iter().find(|byte| !byte.is_ascii_whitespace());

match first_non_whitespace {
Some(b'{') => {
if let Ok(req) = serde_json::from_slice::<Request>(&data) {
tracing::debug!("recv method call={}", req.method);
Expand Down
22 changes: 14 additions & 8 deletions ws-server/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,10 +349,6 @@ async fn garbage_request_fails() {
let response = client.send_request_text(req).await.unwrap();
assert_eq!(response, parse_error(Id::Null));

let req = r#" {"jsonrpc":"2.0","method":"add", "params":[1, 2],"id":1}"#;
let response = client.send_request_text(req).await.unwrap();
assert_eq!(response, parse_error(Id::Null));

let req = r#"{}"#;
let response = client.send_request_text(req).await.unwrap();
assert_eq!(response, parse_error(Id::Null));
Expand All @@ -369,10 +365,6 @@ async fn garbage_request_fails() {
let response = client.send_request_text(req).await.unwrap();
assert_eq!(response, parse_error(Id::Null));

let req = r#" [{"jsonrpc":"2.0","method":"add", "params":[1, 2],"id":1}]"#;
let response = client.send_request_text(req).await.unwrap();
assert_eq!(response, parse_error(Id::Null));

let req = r#"[]"#;
let response = client.send_request_text(req).await.unwrap();
assert_eq!(response, invalid_request(Id::Null));
Expand All @@ -382,6 +374,20 @@ async fn garbage_request_fails() {
assert_eq!(response, parse_error(Id::Null));
}

#[tokio::test]
async fn whitespace_is_not_significant() {
let addr = server().await;
let mut client = WebSocketTestClient::new(addr).await.unwrap();

let req = r#" {"jsonrpc":"2.0","method":"add", "params":[1, 2],"id":1}"#;
let response = client.send_request_text(req).await.unwrap();
assert_eq!(response, ok_response(JsonValue::Number(3u32.into()), Id::Num(1)));

let req = r#" [{"jsonrpc":"2.0","method":"add", "params":[1, 2],"id":1}]"#;
let response = client.send_request_text(req).await.unwrap();
assert_eq!(response, r#"[{"jsonrpc":"2.0","result":3,"id":1}]"#);
}

#[tokio::test]
async fn single_method_call_with_params_works() {
let addr = server().await;
Expand Down

0 comments on commit 47d36b9

Please sign in to comment.