diff --git a/.changeset/perfect-boats-divide.md b/.changeset/perfect-boats-divide.md new file mode 100644 index 000000000..71abc16f2 --- /dev/null +++ b/.changeset/perfect-boats-divide.md @@ -0,0 +1,5 @@ +--- +'@lagon/serverless': patch +--- + +Reduce `clone()`ing diff --git a/crates/cli/src/commands/dev.rs b/crates/cli/src/commands/dev.rs index fee0c26b3..8ab5c149d 100644 --- a/crates/cli/src/commands/dev.rs +++ b/crates/cli/src/commands/dev.rs @@ -94,14 +94,15 @@ async fn handle_request( ); let run_result = match handle_asset(public_dir.unwrap(), asset) { - Ok(response) => RunResult::Response(response, None), + Ok((response_builder, body)) => RunResult::Response(response_builder, body, None), Err(error) => RunResult::Error(format!("Could not retrieve asset ({asset}): {error}")), }; tx.send_async(run_result).await.unwrap_or(()); } else if url == FAVICON_URL { tx.send_async(RunResult::Response( - Response::builder().status(404).body(Body::empty())?, + Response::builder().status(404), + Body::empty(), None, )) .await @@ -143,12 +144,6 @@ async fn handle_request( handle_response(rx, deployment, |event| async move { match event { - ResponseEvent::StreamDoneNoDataError => { - println!( - "{} The stream was done before sending a response/data", - style("✕").red() - ); - } ResponseEvent::UnexpectedStreamResult(result) => { println!( "{} Unexpected stream result: {:?}", diff --git a/crates/runtime/tests/allow_codegen.rs b/crates/runtime/tests/allow_codegen.rs index aa8c01fcb..8e540b894 100644 --- a/crates/runtime/tests/allow_codegen.rs +++ b/crates/runtime/tests/allow_codegen.rs @@ -1,4 +1,4 @@ -use hyper::{header::CONTENT_TYPE, Request, Response}; +use hyper::{header::CONTENT_TYPE, Body, Request, Response}; use lagon_runtime_isolate::options::IsolateOptions; mod utils; @@ -17,10 +17,8 @@ return new Response(result) utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("2".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("2"), ) .await; } @@ -39,10 +37,8 @@ async fn allow_function() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("2".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("2"), ) .await; } diff --git a/crates/runtime/tests/async_context.rs b/crates/runtime/tests/async_context.rs index ffd768fa9..412699266 100644 --- a/crates/runtime/tests/async_context.rs +++ b/crates/runtime/tests/async_context.rs @@ -1,4 +1,4 @@ -use hyper::{header::CONTENT_TYPE, Request, Response}; +use hyper::{header::CONTENT_TYPE, Body, Request, Response}; use lagon_runtime_isolate::options::IsolateOptions; mod utils; @@ -24,10 +24,8 @@ export function handler() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("true".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("true"), ) .await; } @@ -51,7 +49,7 @@ export function handler() { )); send(Request::default()); - utils::assert_response(&receiver, Response::default()).await; + utils::assert_response(&receiver, Response::builder(), Body::empty()).await; } #[tokio::test] @@ -74,7 +72,7 @@ export function handler() { )); send(Request::default()); - utils::assert_response(&receiver, Response::default()).await; + utils::assert_response(&receiver, Response::builder(), Body::empty()).await; } #[tokio::test] @@ -111,7 +109,7 @@ export function handler() { )); send(Request::default()); - utils::assert_response(&receiver, Response::default()).await; + utils::assert_response(&receiver, Response::builder(), Body::empty()).await; } #[tokio::test] @@ -160,7 +158,7 @@ export function handler() { )); send(Request::default()); - utils::assert_response(&receiver, Response::default()).await; + utils::assert_response(&receiver, Response::builder(), Body::empty()).await; } #[tokio::test] @@ -193,10 +191,8 @@ export async function handler() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("2".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("2"), ) .await; @@ -204,10 +200,8 @@ export async function handler() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("4".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("4"), ) .await; diff --git a/crates/runtime/tests/crypto.rs b/crates/runtime/tests/crypto.rs index 336bf8d24..fb2edebdf 100644 --- a/crates/runtime/tests/crypto.rs +++ b/crates/runtime/tests/crypto.rs @@ -1,4 +1,4 @@ -use hyper::{header::CONTENT_TYPE, Request, Response}; +use hyper::{header::CONTENT_TYPE, Body, Request, Response}; use lagon_runtime_http::RunResult; use lagon_runtime_isolate::options::IsolateOptions; use std::time::Duration; @@ -20,10 +20,8 @@ async fn crypto_random_uuid() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("string 36 false".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("string 36 false"), ) .await; } @@ -43,10 +41,8 @@ async fn crypto_get_random_values() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("true 3 3 false false".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("true 3 3 false false"), ) .await; } @@ -66,10 +62,8 @@ async fn crypto_get_random_values_update_in_place() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("3 false".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("3 false"), ) .await; } @@ -117,10 +111,8 @@ async fn crypto_key_value() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("object 6".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("object 6"), ) .await; } @@ -153,10 +145,8 @@ async fn crypto_unique_key_value() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("false".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("false"), ) .await; } @@ -186,10 +176,8 @@ async fn crypto_sign() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("true 32".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("true 32"), ) .await; } @@ -223,10 +211,8 @@ async fn crypto_verify() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("true".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("true"), ) .await; } @@ -246,12 +232,8 @@ async fn crypto_digest_sha1() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body( - "20 183,226,62,194,154,242,43,11,78,65,218,49,232,104,213,114,38,18,28,132".into(), - ) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("20 183,226,62,194,154,242,43,11,78,65,218,49,232,104,213,114,38,18,28,132"), ) .await; } @@ -272,11 +254,10 @@ async fn crypto_digest_string() { utils::assert_response( &receiver, Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body( - "32 9,202,126,78,170,110,138,233,199,210,97,22,113,41,24,72,131,100,77,7,223,186,124,191,188,76,138,46,8,54,13,91".into(), + .header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from( + "32 9,202,126,78,170,110,138,233,199,210,97,22,113,41,24,72,131,100,77,7,223,186,124,191,188,76,138,46,8,54,13,91" ) - .unwrap(), ) .await; } @@ -297,11 +278,10 @@ async fn crypto_digest_object() { utils::assert_response( &receiver, Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body( - "32 9,202,126,78,170,110,138,233,199,210,97,22,113,41,24,72,131,100,77,7,223,186,124,191,188,76,138,46,8,54,13,91".into(), + .header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from( + "32 9,202,126,78,170,110,138,233,199,210,97,22,113,41,24,72,131,100,77,7,223,186,124,191,188,76,138,46,8,54,13,91" ) - .unwrap(), ) .await; } @@ -335,10 +315,8 @@ async fn crypto_encrypt_aes_gcm() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("true 28".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("true 28"), ) .await; } @@ -378,10 +356,8 @@ async fn crypto_decrypt_aes_gcm() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("hello, world".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("hello, world"), ) .await; } @@ -415,10 +391,8 @@ async fn crypto_encrypt_aes_cbc() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("true 16".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("true 16"), ) .await; } @@ -458,10 +432,8 @@ async fn crypto_decrypt_aes_cbc() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("hello, world".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("hello, world"), ) .await; } @@ -495,10 +467,8 @@ async fn crypto_encrypt_aes_ctr() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("true 12".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("true 12"), ) .await; } @@ -538,10 +508,8 @@ async fn crypto_decrypt_aes_ctr() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("hello, world".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("hello, world"), ) .await; } @@ -578,10 +546,8 @@ async fn crypto_encrypt_rsa_oaep() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("true 128".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("true 128"), ) .await; } @@ -626,10 +592,8 @@ async fn crypto_decrypt_rsa_oaep() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("hello, world".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("hello, world"), ) .await; } @@ -666,10 +630,8 @@ async fn crypto_hkdf_derive_bits() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("16".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("16"), ) .await; } @@ -706,10 +668,8 @@ async fn crypto_pbkdf2_derive_bits() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("16".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("16"), ) .await; } @@ -766,10 +726,8 @@ async fn crypto_ecdh_derive_bits() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("256 384".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("256 384"), ) .await; } @@ -812,10 +770,8 @@ async fn crypto_derive_key() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("true true true true true".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("true true true true true"), ) .await; } @@ -856,10 +812,8 @@ async fn crypto_ecdsa_sign_verify() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("true".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("true"), ) .await; } @@ -905,10 +859,8 @@ async fn crypto_rsa_pss_sign_verify() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("true".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("true"), ) .await; } @@ -954,10 +906,8 @@ async fn crypto_rsa_ssa_sign_verify() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("true".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("true"), ) .await; } diff --git a/crates/runtime/tests/fetch.rs b/crates/runtime/tests/fetch.rs index 224d12a09..1040e9e04 100644 --- a/crates/runtime/tests/fetch.rs +++ b/crates/runtime/tests/fetch.rs @@ -1,5 +1,5 @@ use httptest::{matchers::*, responders::*, Expectation, Server}; -use hyper::{header::CONTENT_TYPE, Request, Response}; +use hyper::{header::CONTENT_TYPE, Body, Request, Response}; use lagon_runtime_http::RunResult; use lagon_runtime_isolate::options::IsolateOptions; @@ -25,10 +25,8 @@ async fn basic_fetch() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello, World".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello, World"), ) .await; } @@ -56,10 +54,8 @@ async fn request_method() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello, World".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello, World"), ) .await; } @@ -87,10 +83,8 @@ async fn request_method_fallback() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello, World".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello, World"), ) .await; } @@ -123,10 +117,8 @@ async fn request_headers() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello, World".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello, World"), ) .await; } @@ -159,10 +151,8 @@ async fn request_headers_class() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello, World".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello, World"), ) .await; } @@ -194,10 +184,8 @@ async fn request_body() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello, World".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello, World"), ) .await; } @@ -231,10 +219,8 @@ async fn response_headers() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("content-length: 0 content-type: text/plain;charset=UTF-8 x-token: hello".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("content-length: 0 content-type: text/plain;charset=UTF-8 x-token: hello"), ) .await; } @@ -265,10 +251,8 @@ async fn response_status() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Moved: 200".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Moved: 200"), ) .await; } @@ -295,10 +279,8 @@ async fn response_json() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body(r#"object {"hello":"world"}"#.into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from(r#"object {"hello":"world"}"#), ) .await; } @@ -323,7 +305,7 @@ async fn response_array_buffer() { ))); send(Request::default()); - utils::assert_response(&receiver, Response::new("Hello, World".into())).await; + utils::assert_response(&receiver, Response::builder(), Body::from("Hello, World")).await; } #[tokio::test] @@ -401,10 +383,8 @@ async fn abort_signal() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Aborted".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Aborted"), ) .await; } @@ -429,10 +409,8 @@ async fn redirect() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("200".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("200"), ) .await; } @@ -461,10 +439,8 @@ async fn redirect_relative_url() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("200".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("200"), ) .await; } @@ -554,10 +530,8 @@ export async function handler() {{ utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("ok".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("ok"), ) .await; } @@ -576,10 +550,8 @@ async fn fetch_https() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("200".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("200"), ) .await; @@ -620,10 +592,8 @@ async fn fetch_set_content_length() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Ok".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Ok"), ) .await; } @@ -658,10 +628,8 @@ async fn fetch_input_request() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello, World".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello, World"), ) .await; } @@ -702,10 +670,8 @@ async fn fetch_input_request_init() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello, World".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello, World"), ) .await; } diff --git a/crates/runtime/tests/promises.rs b/crates/runtime/tests/promises.rs index 0d6898d6e..ed2204fdd 100644 --- a/crates/runtime/tests/promises.rs +++ b/crates/runtime/tests/promises.rs @@ -1,5 +1,5 @@ use httptest::{matchers::*, responders::*, Expectation, Server}; -use hyper::{header::CONTENT_TYPE, Request, Response}; +use hyper::{header::CONTENT_TYPE, Body, Request, Response}; use lagon_runtime_isolate::options::IsolateOptions; mod utils; @@ -17,10 +17,8 @@ async fn execute_async_handler() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Async handler".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Async handler"), ) .await; } @@ -45,10 +43,8 @@ async fn execute_promise() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello, World".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello, World"), ) .await; } diff --git a/crates/runtime/tests/runtime.rs b/crates/runtime/tests/runtime.rs index 4670cb078..bd59bcd3c 100644 --- a/crates/runtime/tests/runtime.rs +++ b/crates/runtime/tests/runtime.rs @@ -20,10 +20,8 @@ async fn execute_function() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello world".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello world"), ) .await; } @@ -43,10 +41,8 @@ export { hello as handler }" utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello world".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello world"), ) .await; } @@ -64,10 +60,8 @@ async fn execute_function_twice() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello world".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello world"), ) .await; @@ -75,10 +69,8 @@ async fn execute_function_twice() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello world".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello world"), ) .await; } @@ -103,10 +95,8 @@ async fn environment_variables() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello world".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello world"), ) .await; } @@ -162,10 +152,8 @@ async fn get_body() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello world".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello world"), ) .await; } @@ -190,10 +178,8 @@ async fn get_input() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("https://hello.world/hello".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("https://hello.world/hello"), ) .await; } @@ -217,10 +203,8 @@ async fn get_method() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("POST".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("POST"), ) .await; } @@ -243,10 +227,8 @@ async fn get_headers() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("token".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("token"), ) .await; } @@ -271,9 +253,8 @@ async fn return_headers() { &receiver, Response::builder() .header(CONTENT_TYPE, "text/html") - .header("x-test", "test") - .body("Hello world".into()) - .unwrap(), + .header("x-test", "test"), + Body::from("Hello world"), ) .await; } @@ -298,9 +279,8 @@ async fn return_headers_from_headers_api() { &receiver, Response::builder() .header(CONTENT_TYPE, "text/html") - .header("x-test", "test") - .body("Hello world".into()) - .unwrap(), + .header("x-test", "test"), + Body::from("Hello world"), ) .await; } @@ -322,9 +302,8 @@ async fn return_status() { &receiver, Response::builder() .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .status(302) - .body("Moved permanently".into()) - .unwrap(), + .status(302), + Body::from("Moved permanently"), ) .await; } @@ -342,11 +321,7 @@ async fn return_uint8array() { )); send(Request::default()); - utils::assert_response( - &receiver, - Response::builder().body("Hello world".into()).unwrap(), - ) - .await; + utils::assert_response(&receiver, Response::builder(), Body::from("Hello world")).await; } #[tokio::test] @@ -368,10 +343,8 @@ async fn console_log() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from(""), ) .await; } @@ -389,10 +362,8 @@ async fn atob() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello"), ) .await; } @@ -410,10 +381,8 @@ async fn btoa() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("SGVsbG8=".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("SGVsbG8="), ) .await; } diff --git a/crates/runtime/tests/timers.rs b/crates/runtime/tests/timers.rs index 91bcc02fa..4b46a05a8 100644 --- a/crates/runtime/tests/timers.rs +++ b/crates/runtime/tests/timers.rs @@ -1,4 +1,4 @@ -use hyper::{header::CONTENT_TYPE, Request, Response}; +use hyper::{header::CONTENT_TYPE, Body, Request, Response}; use lagon_runtime_isolate::options::IsolateOptions; use serial_test::serial; @@ -22,10 +22,8 @@ async fn set_timeout() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("test".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("test"), ) .await; } @@ -58,10 +56,8 @@ async fn set_timeout_not_blocking_response() { ); utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello!".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello!"), ) .await; assert_eq!( @@ -93,10 +89,8 @@ async fn set_timeout_clear() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("second".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("second"), ) .await; } @@ -123,10 +117,8 @@ async fn set_timeout_clear_correct() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("first".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("first"), ) .await; } @@ -180,10 +172,8 @@ async fn set_interval() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello world".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello world"), ) .await; } @@ -221,10 +211,8 @@ async fn queue_microtask() { utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello world".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello world"), ) .await; } @@ -284,10 +272,8 @@ async fn timers_order() { ); utils::assert_response( &receiver, - Response::builder() - .header(CONTENT_TYPE, "text/plain;charset=UTF-8") - .body("Hello world".into()) - .unwrap(), + Response::builder().header(CONTENT_TYPE, "text/plain;charset=UTF-8"), + Body::from("Hello world"), ) .await; } diff --git a/crates/runtime/tests/utils/mod.rs b/crates/runtime/tests/utils/mod.rs index dcd19b4fe..85722e019 100644 --- a/crates/runtime/tests/utils/mod.rs +++ b/crates/runtime/tests/utils/mod.rs @@ -1,4 +1,7 @@ -use hyper::{http::Request, Body, Response}; +use hyper::{ + http::{response::Builder, Request}, + Body, +}; use lagon_runtime::{options::RuntimeOptions, Runtime}; use lagon_runtime_http::{RunResult, StreamResult}; use lagon_runtime_isolate::{options::IsolateOptions, Isolate, IsolateEvent, IsolateRequest}; @@ -99,8 +102,8 @@ pub async fn assert_run_result(receiver: &flume::Receiver, run_result let result = receiver.recv_async().await.unwrap(); match run_result { - RunResult::Response(response, _) => { - assert_response_inner(response, result.as_response()).await; + RunResult::Response(response, body, _) => { + assert_response_inner((response, body), result.as_response()).await; } RunResult::Error(error) => { assert_eq!(error, result.as_error()); @@ -149,16 +152,17 @@ pub async fn assert_run_result(receiver: &flume::Receiver, run_result _ => unreachable!(), }; - let response = response.body(Body::empty()).unwrap(); - let result_response = result_response.body(Body::empty()).unwrap(); - - assert_response_inner(response, result_response).await; + assert_response_inner((response, Body::empty()), (result_response, Body::empty())) + .await; } }, } } -async fn assert_response_inner(first: Response, second: Response) { +async fn assert_response_inner(first: (Builder, Body), second: (Builder, Body)) { + let first = first.0.body(first.1).unwrap(); + let second = second.0.body(second.1).unwrap(); + assert_eq!(first.status(), second.status(), "Status mismatch"); assert_eq!(first.headers(), second.headers(), "Headers mismatch"); @@ -169,8 +173,12 @@ async fn assert_response_inner(first: Response, second: Response) { } #[allow(dead_code)] -pub async fn assert_response(receiver: &flume::Receiver, response: Response) { +pub async fn assert_response( + receiver: &flume::Receiver, + response_builder: Builder, + body: Body, +) { let result = receiver.recv_async().await.unwrap().as_response(); - assert_response_inner(result, response).await; + assert_response_inner(result, (response_builder, body)).await; } diff --git a/crates/runtime_http/src/lib.rs b/crates/runtime_http/src/lib.rs index 11f5d9ff2..97ea18737 100644 --- a/crates/runtime_http/src/lib.rs +++ b/crates/runtime_http/src/lib.rs @@ -1,4 +1,4 @@ -use hyper::{http::response::Builder, Body, Response}; +use hyper::{http::response::Builder, Body}; use std::time::Duration; mod headers; @@ -22,7 +22,7 @@ pub enum StreamResult { pub enum RunResult { // Isolate responses have a duration (cpu time) // Assets responses don't - Response(Response, Option), + Response(Builder, Body, Option), Stream(StreamResult), Timeout, MemoryLimit, @@ -46,9 +46,9 @@ impl RunResult { panic!("RunResult is not an Error: {:?}", self); } - pub fn as_response(self) -> Response { - if let RunResult::Response(response, _) = self { - return response; + pub fn as_response(self) -> (Builder, Body) { + if let RunResult::Response(response_builder, body, _) = self { + return (response_builder, body); } panic!("RunResult is not a Response: {:?}", self); diff --git a/crates/runtime_http/src/response.rs b/crates/runtime_http/src/response.rs index df5bf20b1..c94369b95 100644 --- a/crates/runtime_http/src/response.rs +++ b/crates/runtime_http/src/response.rs @@ -1,5 +1,5 @@ use anyhow::{anyhow, Result}; -use hyper::{body::Bytes, Body, HeaderMap, Response}; +use hyper::{body::Bytes, http::response::Builder, Body, HeaderMap, Response}; use lagon_runtime_v8_utils::{ extract_v8_headers_object, extract_v8_integer, extract_v8_string, v8_headers_object, v8_integer, v8_string, @@ -29,7 +29,7 @@ pub fn response_to_v8<'a>( pub fn response_from_v8<'a>( scope: &mut v8::HandleScope<'a>, response: v8::Local<'a, v8::Value>, -) -> Result<(Response, bool)> { +) -> Result<(Builder, Body, bool)> { let response = match response.to_object(scope) { Some(response) => response, None => return Err(anyhow!("Response is not an object")), @@ -70,11 +70,11 @@ pub fn response_from_v8<'a>( return match response.get(scope, body_key.into()) { Some(body_value) => match body_value.is_null_or_undefined() { - true => Ok((response_builder.body(Body::empty())?, true)), + true => Ok((response_builder, Body::empty(), true)), false => { let body = extract_v8_string(body_value, scope)?; - Ok((response_builder.body(body.into())?, false)) + Ok((response_builder, body.into(), false)) } }, None => Err(anyhow!("Could not find body")), diff --git a/crates/runtime_isolate/src/lib.rs b/crates/runtime_isolate/src/lib.rs index 73d9d516c..5780906d6 100644 --- a/crates/runtime_isolate/src/lib.rs +++ b/crates/runtime_isolate/src/lib.rs @@ -1,8 +1,5 @@ use futures::{future::poll_fn, stream::FuturesUnordered, Future, StreamExt}; -use hyper::{ - body::Bytes, - http::{request::Parts, response::Builder}, -}; +use hyper::{body::Bytes, http::request::Parts}; use lagon_runtime_http::{request_to_v8, response_from_v8, RunResult, StreamResult}; use lagon_runtime_v8_utils::v8_string; use linked_hash_map::LinkedHashMap; @@ -656,9 +653,10 @@ impl Isolate { v8::PromiseState::Fulfilled => { let response = promise.result(try_catch); let (run_result, is_streaming) = match response_from_v8(try_catch, response) { - Ok((response, is_streaming)) => ( + Ok((response_builder, body, is_streaming)) => ( RunResult::Response( - response, + response_builder, + body, Some(handler_result.start_time.elapsed()), ), is_streaming, @@ -667,13 +665,7 @@ impl Isolate { }; if is_streaming { - let response = run_result.as_response(); - let mut response_builder = Builder::new().status(response.status()); - let headers = response_builder.headers_mut().unwrap(); - - for (key, value) in response.headers().iter() { - headers.append(key, value.into()); - } + let (response_builder, _) = run_result.as_response(); handler_result .sender diff --git a/crates/runtime_utils/src/assets.rs b/crates/runtime_utils/src/assets.rs index de07c6437..50f427cb3 100644 --- a/crates/runtime_utils/src/assets.rs +++ b/crates/runtime_utils/src/assets.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use hyper::{body::Bytes, header::CONTENT_TYPE, Body, Response}; +use hyper::{body::Bytes, header::CONTENT_TYPE, http::response::Builder, Body, Response}; use std::{ collections::HashSet, fs, @@ -23,7 +23,7 @@ pub fn find_asset<'a>(url: &'a str, assets: &'a HashSet) -> Option<&'a S }) } -pub fn handle_asset(root: PathBuf, asset: &String) -> Result> { +pub fn handle_asset(root: PathBuf, asset: &String) -> Result<(Builder, Body)> { let path = root.join(asset); let body = fs::read(path)?; @@ -43,9 +43,10 @@ pub fn handle_asset(root: PathBuf, asset: &String) -> Result> { }, ); - Ok(Response::builder() - .header(CONTENT_TYPE, content_type) - .body(Body::from(Bytes::from(body)))?) + Ok(( + Response::builder().header(CONTENT_TYPE, content_type), + Body::from(Bytes::from(body)), + )) } #[cfg(test)] diff --git a/crates/runtime_utils/src/response.rs b/crates/runtime_utils/src/response.rs index d14f1bf62..e9a853234 100644 --- a/crates/runtime_utils/src/response.rs +++ b/crates/runtime_utils/src/response.rs @@ -3,6 +3,7 @@ use anyhow::Result; use flume::Receiver; use hyper::{ body::{Bytes, HttpBody}, + http::response::Builder, Body, Response, }; use lagon_runtime_http::{RunResult, StreamResult}; @@ -17,7 +18,6 @@ pub const FAVICON_URL: &str = "/favicon.ico"; #[derive(Debug)] pub enum ResponseEvent { Bytes(usize, Option), - StreamDoneNoDataError, UnexpectedStreamResult(RunResult), LimitsReached(RunResult), Error(RunResult), @@ -25,21 +25,26 @@ pub enum ResponseEvent { const X_ROBOTS_TAGS: &str = "x-robots-tag"; -fn enrich_response(response: &mut Response, deployment: &Deployment) { +fn build_response( + response_builder: Builder, + deployment: &Deployment, + body: Body, +) -> Result> { // We automatically add a X-Robots-Tag: noindex header to // all preview deployments to prevent them from being // indexed by search engines - if !deployment.is_production { - response - .headers_mut() - .insert(X_ROBOTS_TAGS, "noindex".parse().unwrap()); - } + let response_builder = match deployment.is_production { + true => response_builder, + false => response_builder.header(X_ROBOTS_TAGS, "noindex"), + }; + + Ok(response_builder.body(body)?) } pub async fn handle_response( rx: Receiver, deployment: Arc, - on_event: impl Fn(ResponseEvent) -> F + Send + Sync + 'static, + on_event: impl FnOnce(ResponseEvent) -> F + Send + Sync + 'static, ) -> Result> where F: Future> + Send, @@ -65,14 +70,14 @@ where stream_tx.send_async(Ok(bytes)).await.unwrap_or(()); } StreamResult::Done(_) => { - on_event(ResponseEvent::StreamDoneNoDataError).await?; - // Close the stream by sending empty bytes stream_tx.send_async(Ok(Bytes::new())).await.unwrap_or(()); } } tokio::spawn(async move { + let mut event = None; + while let Ok(result) = rx.recv_async().await { match result { RunResult::Stream(StreamResult::Start(response)) => { @@ -85,17 +90,14 @@ where stream_tx.send_async(Ok(bytes)).await.unwrap_or(()); } RunResult::Stream(StreamResult::Done(elapsed)) => { - on_event(ResponseEvent::Bytes(total_bytes, Some(elapsed.as_micros()))) - .await - .unwrap_or(()); + event = + Some(ResponseEvent::Bytes(total_bytes, Some(elapsed.as_micros()))); // Close the stream by sending empty bytes stream_tx.send_async(Ok(Bytes::new())).await.unwrap_or(()); } _ => { - on_event(ResponseEvent::UnexpectedStreamResult(result)) - .await - .unwrap_or(()); + event = Some(ResponseEvent::UnexpectedStreamResult(result)); // Close the stream by sending empty bytes stream_tx.send_async(Ok(Bytes::new())).await.unwrap_or(()); @@ -103,19 +105,23 @@ where } } } + + if let Some(event) = event { + on_event(event).await.unwrap_or(()); + } }); let response_builder = response_builder_rx.recv_async().await?; - let mut response = response_builder.body(body)?; + let response = build_response(response_builder, &deployment, body)?; - enrich_response(&mut response, &deployment); + println!("send res"); Ok(response) } - RunResult::Response(mut response, elapsed) => { - enrich_response(&mut response, &deployment); - + RunResult::Response(response_builder, body, elapsed) => { + let response = build_response(response_builder, &deployment, body)?; let bytes = response.body().size_hint().exact().unwrap_or(0); + let event = ResponseEvent::Bytes(bytes as usize, elapsed.map(|duration| duration.as_micros())); on_event(event).await?; @@ -166,7 +172,8 @@ mod tests { }); tx.send_async(RunResult::Response( - Response::new("Hello World".into()), + Builder::new(), + Body::from("Hello World"), None, )) .await @@ -202,7 +209,8 @@ mod tests { }); tx.send_async(RunResult::Response( - Response::new("Hello World".into()), + Builder::new(), + Body::from("Hello World"), None, )) .await diff --git a/crates/serverless/src/clickhouse.rs b/crates/serverless/src/clickhouse.rs index b8e091d23..0f2fa2f00 100644 --- a/crates/serverless/src/clickhouse.rs +++ b/crates/serverless/src/clickhouse.rs @@ -1,8 +1,7 @@ -use std::env; - use anyhow::Result; use clickhouse::{Client, Row}; use serde::{Deserialize, Serialize}; +use std::env; #[derive(Row, Serialize, Deserialize)] pub struct LogRow { diff --git a/crates/serverless/src/cronjob.rs b/crates/serverless/src/cronjob.rs index 0d25ce5ce..3e114422b 100644 --- a/crates/serverless/src/cronjob.rs +++ b/crates/serverless/src/cronjob.rs @@ -157,7 +157,8 @@ impl Cronjob { (String::from("warn"), String::from("Cron Functions can't return a stream")) } - RunResult::Response(response, elapsed) => { + RunResult::Response(response_builder, body, elapsed) => { + let response = response_builder.body(body).unwrap(); let status = response.status(); let body = body::to_bytes(response.into_body()).await.unwrap_or_else(|error| { error!( diff --git a/crates/serverless/src/serverless.rs b/crates/serverless/src/serverless.rs index 695b519f9..ca6e71928 100644 --- a/crates/serverless/src/serverless.rs +++ b/crates/serverless/src/serverless.rs @@ -146,7 +146,6 @@ async fn handle_request( return Ok(Response::builder().status(403).body(PAGE_403.into())?); } - let request_id_handle = request_id.clone(); let (sender, receiver) = flume::unbounded(); let mut bytes_in = 0; @@ -158,9 +157,9 @@ async fn handle_request( .join(&deployment.id); let run_result = match handle_asset(root, asset) { - Ok(response) => RunResult::Response(response, None), + Ok((response_builder, body)) => RunResult::Response(response_builder, body, None), Err(error) => { - error!(deployment = &deployment.id, asset = asset, request = request_id_handle; "Error while handing asset: {}", error); + error!(deployment = &deployment.id, asset = asset, request = request_id; "Error while handing asset: {}", error); RunResult::Error("Could not retrieve asset.".into()) } @@ -170,7 +169,8 @@ async fn handle_request( } else if url == FAVICON_URL { sender .send_async(RunResult::Response( - Response::builder().status(404).body(Body::empty())?, + Response::builder().status(404), + Body::empty(), None, )) .await @@ -186,6 +186,7 @@ async fn handle_request( let deployment = Arc::clone(&deployment); let isolate_workers = Arc::clone(&workers); + let request_id_handle = request_id.clone(); let isolate_sender = workers.entry(deployment.id.clone()).or_insert_with(|| { let handle = Handle::current(); @@ -260,10 +261,10 @@ async fn handle_request( .unwrap_or(()); } - handle_response(receiver, Arc::clone(&deployment), move |event| { + let deployment_handle = Arc::clone(&deployment); + + handle_response(receiver, deployment, move |event| { let inserters = Arc::clone(&inserters); - let request_id = request_id.clone(); - let deployment = Arc::clone(&deployment); async move { match event { @@ -275,8 +276,8 @@ async fn handle_request( .await .0 .write(&RequestRow { - function_id: deployment.function_id.clone(), - deployment_id: deployment.id.clone(), + function_id: deployment_handle.function_id.clone(), + deployment_id: deployment_handle.id.clone(), region: get_region().clone(), bytes_in, bytes_out: bytes as u32, @@ -286,23 +287,11 @@ async fn handle_request( .await .unwrap_or(()); } - ResponseEvent::StreamDoneNoDataError => { - handle_error( - RunResult::Error( - "The stream was done before sending a response/data".into(), - ), - deployment.function_id.clone(), - deployment.id.clone(), - &request_id, - inserters, - ) - .await; - } ResponseEvent::UnexpectedStreamResult(result) => { handle_error( result, - deployment.function_id.clone(), - deployment.id.clone(), + deployment_handle.function_id.clone(), + deployment_handle.id.clone(), &request_id, inserters, ) @@ -311,8 +300,8 @@ async fn handle_request( ResponseEvent::LimitsReached(result) | ResponseEvent::Error(result) => { handle_error( result, - deployment.function_id.clone(), - deployment.id.clone(), + deployment_handle.function_id.clone(), + deployment_handle.id.clone(), &request_id, inserters, )