Skip to content

Commit e6ac88f

Browse files
authored
Fix streaming prelude serialization (#692)
* Fix streaming prelude serialization HTTP headers can be multi-value, but the current implementation ignores this fact and only serializes the first value for each header. This changes uses http-serde to serialize the prelude correctly. Signed-off-by: David Calavera <[email protected]> * Update MSRV Some dependencies have dropped support for 1.62 already. Signed-off-by: David Calavera <[email protected]> * Remove unwrap Signed-off-by: David Calavera <[email protected]> --------- Signed-off-by: David Calavera <[email protected]>
1 parent 1781f89 commit e6ac88f

File tree

6 files changed

+40
-37
lines changed

6 files changed

+40
-37
lines changed

.github/workflows/build-events.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
strategy:
1515
matrix:
1616
toolchain:
17-
- "1.62.0" # Current MSRV
17+
- "1.64.0" # Current MSRV
1818
- stable
1919
env:
2020
RUST_BACKTRACE: 1

.github/workflows/build-extension.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
strategy:
1919
matrix:
2020
toolchain:
21-
- "1.62.0" # Current MSRV
21+
- "1.64.0" # Current MSRV
2222
- stable
2323
env:
2424
RUST_BACKTRACE: 1

.github/workflows/build-runtime.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
strategy:
2020
matrix:
2121
toolchain:
22-
- "1.62.0" # Current MSRV
22+
- "1.64.0" # Current MSRV
2323
- stable
2424
env:
2525
RUST_BACKTRACE: 1

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ This will make your function compile much faster.
440440

441441
## Supported Rust Versions (MSRV)
442442

443-
The AWS Lambda Rust Runtime requires a minimum of Rust 1.62, and is not guaranteed to build on compiler versions earlier than that.
443+
The AWS Lambda Rust Runtime requires a minimum of Rust 1.64, and is not guaranteed to build on compiler versions earlier than that.
444444

445445
## Security
446446

lambda-runtime/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,4 @@ tower = { version = "0.4", features = ["util"] }
4242
tokio-stream = "0.1.2"
4343
lambda_runtime_api_client = { version = "0.8", path = "../lambda-runtime-api-client" }
4444
serde_path_to_error = "0.1.11"
45+
http-serde = "1.1.3"

lambda-runtime/src/streaming.rs

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@ use crate::{
55
use bytes::Bytes;
66
use futures::FutureExt;
77
use http::header::{CONTENT_TYPE, SET_COOKIE};
8-
use http::{Method, Request, Response, Uri};
8+
use http::{HeaderMap, Method, Request, Response, StatusCode, Uri};
99
use hyper::body::HttpBody;
1010
use hyper::{client::connect::Connection, Body};
1111
use lambda_runtime_api_client::{build_request, Client};
12-
use serde::Deserialize;
13-
use serde_json::json;
14-
use std::collections::HashMap;
12+
use serde::{Deserialize, Serialize};
1513
use std::str::FromStr;
1614
use std::{
1715
env,
@@ -203,6 +201,16 @@ pub(crate) struct EventCompletionStreamingRequest<'a, B> {
203201
pub(crate) body: Response<B>,
204202
}
205203

204+
#[derive(Debug, Serialize)]
205+
#[serde(rename_all = "camelCase")]
206+
struct MetadataPrelude {
207+
#[serde(serialize_with = "http_serde::status_code::serialize")]
208+
status_code: StatusCode,
209+
#[serde(serialize_with = "http_serde::header_map::serialize")]
210+
headers: HeaderMap,
211+
cookies: Vec<String>,
212+
}
213+
206214
impl<'a, B> IntoRequest for EventCompletionStreamingRequest<'a, B>
207215
where
208216
B: HttpBody + Unpin + Send + 'static,
@@ -216,45 +224,39 @@ where
216224
let (parts, mut body) = self.body.into_parts();
217225

218226
let mut builder = build_request().method(Method::POST).uri(uri);
219-
let headers = builder.headers_mut().unwrap();
227+
let req_headers = builder.headers_mut().unwrap();
220228

221-
headers.insert("Transfer-Encoding", "chunked".parse()?);
222-
headers.insert("Lambda-Runtime-Function-Response-Mode", "streaming".parse()?);
223-
headers.insert(
229+
req_headers.insert("Transfer-Encoding", "chunked".parse()?);
230+
req_headers.insert("Lambda-Runtime-Function-Response-Mode", "streaming".parse()?);
231+
req_headers.insert(
224232
"Content-Type",
225233
"application/vnd.awslambda.http-integration-response".parse()?,
226234
);
227235

228-
let (mut tx, rx) = Body::channel();
236+
let mut prelude_headers = parts.headers;
237+
// default Content-Type
238+
prelude_headers
239+
.entry(CONTENT_TYPE)
240+
.or_insert("application/octet-stream".parse()?);
229241

230-
tokio::spawn(async move {
231-
let mut header_map = parts.headers;
232-
// default Content-Type
233-
header_map
234-
.entry(CONTENT_TYPE)
235-
.or_insert("application/octet-stream".parse().unwrap());
242+
let cookies = prelude_headers.get_all(SET_COOKIE);
243+
let cookies = cookies
244+
.iter()
245+
.map(|c| String::from_utf8_lossy(c.as_bytes()).to_string())
246+
.collect::<Vec<String>>();
247+
prelude_headers.remove(SET_COOKIE);
236248

237-
let cookies = header_map.get_all(SET_COOKIE);
238-
let cookies = cookies
239-
.iter()
240-
.map(|c| String::from_utf8_lossy(c.as_bytes()).to_string())
241-
.collect::<Vec<String>>();
249+
let metadata_prelude = serde_json::to_string(&MetadataPrelude {
250+
status_code: parts.status,
251+
headers: prelude_headers,
252+
cookies,
253+
})?;
242254

243-
let headers = header_map
244-
.iter()
245-
.filter(|(k, _)| *k != SET_COOKIE)
246-
.map(|(k, v)| (k.as_str(), String::from_utf8_lossy(v.as_bytes()).to_string()))
247-
.collect::<HashMap<&str, String>>();
255+
trace!(?metadata_prelude);
248256

249-
let metadata_prelude = json!({
250-
"statusCode": parts.status.as_u16(),
251-
"headers": headers,
252-
"cookies": cookies,
253-
})
254-
.to_string();
255-
256-
trace!("metadata_prelude: {}", metadata_prelude);
257+
let (mut tx, rx) = Body::channel();
257258

259+
tokio::spawn(async move {
258260
tx.send_data(metadata_prelude.into()).await.unwrap();
259261
tx.send_data("\u{0}".repeat(8).into()).await.unwrap();
260262

0 commit comments

Comments
 (0)