Skip to content

Commit ce2b60e

Browse files
GlenDCsvix-jplatte
andcommitted
sync up relevant changes from axum
Only applicable and interesting to us was: <tokio-rs/axum@af6a595> Co-authored-by: Jonas Platte <jplatte@svix.com>
1 parent 0f18f51 commit ce2b60e

File tree

8 files changed

+132
-90
lines changed

8 files changed

+132
-90
lines changed

FORK.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ as a distant relative.
2525
<https://github.com/plabayo/tower-async/tree/57798b7baea8e212197a226a2481fa282591dda4>
2626

2727
## Relative Forks
28-
29-
- <https://github.com/tokio-rs/axum/tree/2b6ae09568f29451b731674a578275955314badc>
28+
- <https://github.com/tokio-rs/axum/tree/9c9cbb5c5f72452825388d63db4f1e36c0d9b3aa>
3029
- IntoResponse Code
3130
- (Optional)FromRequest/ (Optional)FromRequestParts code
3231
- Error/BoxError

docs/index.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ <h2>Built for Modularity</h2>
8585
<section class="installation-section">
8686
<h2>Get Started with Rama</h2>
8787
<p>
88-
Choose your preferred installation method: add Rama as a
88+
Choose your preferred installation method. Either add Rama as a
8989
framework dependency to your Rust project for maximum flexibility and control,
9090
or install the pre-built Rama CLI binary for immediate use as
9191
a standalone tool without writing code:
@@ -128,7 +128,7 @@ <h2>Get Started with Rama</h2>
128128

129129
<div class="installation-links">
130130
<a href="https://ramaproxy.org/book/deploy/rama-cli.html">Alternative Installation Methods</a>
131-
<a href="https://docs.rs/rama">API Documentation</a>
131+
<a href="https://docs.rs/rama">Rust Documentation</a>
132132
<a href="https://github.com/plabayo/rama">Source Code</a>
133133
</div>
134134
</section>
@@ -671,4 +671,4 @@ <h2>Supported by</h2>
671671
</footer>
672672
</body>
673673

674-
</html>
674+
</html>

rama-http-types/src/response/csv.rs

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::response::{IntoResponse, Response};
22
use crate::{Body, dep::http::StatusCode};
3+
use bytes::buf::Writer;
34
use bytes::{BufMut, BytesMut};
45
use csv;
56
use headers::ContentType;
@@ -87,12 +88,11 @@ where
8788
T: IntoIterator<Item: Serialize> + std::fmt::Debug,
8889
{
8990
fn into_response(self) -> Response {
90-
// Use a small initial capacity of 128 bytes like serde_json::to_vec
91-
// https://docs.rs/serde_json/1.0.82/src/serde_json/ser.rs.html#2189
92-
let mut buf = BytesMut::with_capacity(128).writer();
93-
{
94-
let mut wtr = csv::Writer::from_writer(&mut buf);
95-
let res: Result<Vec<_>, _> = self.0.into_iter().map(|rec| wtr.serialize(rec)).collect();
91+
// Extracted into separate fn so it's only compiled once for all T.
92+
fn make_respone(
93+
res: csv::Result<Vec<()>>,
94+
mut wtr: csv::Writer<Writer<BytesMut>>,
95+
) -> Response {
9696
if let Err(err) = res {
9797
return (
9898
StatusCode::INTERNAL_SERVER_ERROR,
@@ -109,13 +109,34 @@ where
109109
)
110110
.into_response();
111111
}
112+
113+
let bw = match wtr.into_inner() {
114+
Ok(bw) => bw,
115+
Err(err) => {
116+
return (
117+
StatusCode::INTERNAL_SERVER_ERROR,
118+
Headers::single(ContentType::text_utf8()),
119+
err.to_string(),
120+
)
121+
.into_response();
122+
}
123+
};
124+
125+
(
126+
[(CONTENT_TYPE, HeaderValue::from_static("text/csv"))],
127+
bw.into_inner().freeze(),
128+
)
129+
.into_response()
112130
}
113131

114-
(
115-
[(CONTENT_TYPE, HeaderValue::from_static("text/csv"))],
116-
buf.into_inner().freeze(),
117-
)
118-
.into_response()
132+
// Use a small initial capacity of 128 bytes like serde_json::to_vec
133+
// https://docs.rs/serde_json/1.0.82/src/serde_json/ser.rs.html#2189
134+
let buf = BytesMut::with_capacity(128).writer();
135+
136+
let mut wtr = csv::Writer::from_writer(buf);
137+
let res: Result<Vec<_>, _> = self.0.into_iter().map(|rec| wtr.serialize(rec)).collect();
138+
139+
make_respone(res, wtr)
119140
}
120141
}
121142

rama-http-types/src/response/form.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,19 @@ where
8989
T: Serialize,
9090
{
9191
fn into_response(self) -> Response {
92-
match serde_html_form::to_string(&self.0) {
93-
Ok(body) => (Headers::single(ContentType::form_url_encoded()), body).into_response(),
94-
Err(err) => {
95-
tracing::error!(error = %err, "response error");
96-
StatusCode::INTERNAL_SERVER_ERROR.into_response()
92+
// Extracted into separate fn so it's only compiled once for all T.
93+
fn make_response(ser_result: Result<String, serde_html_form::ser::Error>) -> Response {
94+
match ser_result {
95+
Ok(body) => {
96+
(Headers::single(ContentType::form_url_encoded()), body).into_response()
97+
}
98+
Err(err) => {
99+
tracing::error!(error = %err, "response error");
100+
StatusCode::INTERNAL_SERVER_ERROR.into_response()
101+
}
97102
}
98103
}
104+
make_response(serde_html_form::to_string(&self.0))
99105
}
100106
}
101107

rama-http-types/src/response/json.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -80,22 +80,23 @@ where
8080
T: Serialize,
8181
{
8282
fn into_response(self) -> Response {
83+
// Extracted into separate fn so it's only compiled once for all T.
84+
fn make_respone(buf: BytesMut, ser_result: serde_json::Result<()>) -> Response {
85+
match ser_result {
86+
Ok(()) => (Headers::single(ContentType::json()), buf.freeze()).into_response(),
87+
Err(err) => (
88+
StatusCode::INTERNAL_SERVER_ERROR,
89+
Headers::single(ContentType::text_utf8()),
90+
err.to_string(),
91+
)
92+
.into_response(),
93+
}
94+
}
8395
// Use a small initial capacity of 128 bytes like serde_json::to_vec
8496
// https://docs.rs/serde_json/1.0.82/src/serde_json/ser.rs.html#2189
8597
let mut buf = BytesMut::with_capacity(128).writer();
86-
match serde_json::to_writer(&mut buf, &self.0) {
87-
Ok(()) => (
88-
Headers::single(ContentType::json()),
89-
buf.into_inner().freeze(),
90-
)
91-
.into_response(),
92-
Err(err) => (
93-
StatusCode::INTERNAL_SERVER_ERROR,
94-
Headers::single(ContentType::text_utf8()),
95-
err.to_string(),
96-
)
97-
.into_response(),
98-
}
98+
let res = serde_json::to_writer(&mut buf, &self.0);
99+
make_respone(buf.into_inner(), res)
99100
}
100101
}
101102

rama-http/src/service/web/endpoint/extract/body/csv.rs

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::Request;
33
use crate::dep::http_body_util::BodyExt;
44
use crate::service::web::extract::FromRequest;
55
use crate::utils::macros::{composite_http_rejection, define_http_rejection};
6-
use bytes::Buf;
6+
use bytes::{Buf, Bytes};
77

88
pub use crate::response::Csv;
99

@@ -43,30 +43,35 @@ where
4343
type Rejection = CsvRejection;
4444

4545
async fn from_request(req: Request) -> Result<Self, Self::Rejection> {
46-
if !crate::service::web::extract::has_any_content_type(req.headers(), &[&mime::TEXT_CSV]) {
47-
return Err(InvalidCsvContentType.into());
46+
// Extracted into separate fn so it's only compiled once for all T.
47+
async fn req_to_csv_bytes(req: Request) -> Result<Bytes, CsvRejection> {
48+
if !crate::service::web::extract::has_any_content_type(
49+
req.headers(),
50+
&[&mime::TEXT_CSV],
51+
) {
52+
return Err(InvalidCsvContentType.into());
53+
}
54+
55+
let body = req.into_body();
56+
let bytes = body.collect().await.map_err(BytesRejection::from_err)?;
57+
58+
Ok(bytes.to_bytes())
4859
}
4960

50-
let body = req.into_body();
51-
match body.collect().await {
52-
Ok(c) => {
53-
let b = c.to_bytes();
54-
let mut rdr = csv::Reader::from_reader(b.clone().reader());
55-
56-
let out: Result<Vec<T>, _> = rdr
57-
.deserialize()
58-
.map(|rec| {
59-
let record: Result<T, _> = rec;
60-
record
61-
})
62-
.collect();
63-
64-
match out {
65-
Ok(s) => Ok(Self(s)),
66-
Err(err) => Err(FailedToDeserializeCsv::from_err(err).into()),
67-
}
68-
}
69-
Err(err) => Err(BytesRejection::from_err(err).into()),
61+
let b = req_to_csv_bytes(req).await?;
62+
let mut rdr = csv::Reader::from_reader(b.reader());
63+
64+
let out: Result<Vec<T>, _> = rdr
65+
.deserialize()
66+
.map(|rec| {
67+
let record: Result<T, _> = rec;
68+
record
69+
})
70+
.collect();
71+
72+
match out {
73+
Ok(s) => Ok(Self(s)),
74+
Err(err) => Err(FailedToDeserializeCsv::from_err(err).into()),
7075
}
7176
}
7277
}

rama-http/src/service/web/endpoint/extract/body/form.rs

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use bytes::Bytes;
2+
13
use super::BytesRejection;
24
use crate::dep::http_body_util::BodyExt;
35
use crate::service::web::extract::FromRequest;
@@ -42,14 +44,8 @@ where
4244
type Rejection = FormRejection;
4345

4446
async fn from_request(req: Request) -> Result<Self, Self::Rejection> {
45-
if req.method() == Method::GET {
46-
let query = req.uri().query().unwrap_or_default();
47-
let value = match serde_html_form::from_bytes(query.as_bytes()) {
48-
Ok(value) => value,
49-
Err(err) => return Err(FailedToDeserializeForm::from_err(err).into()),
50-
};
51-
Ok(Form(value))
52-
} else {
47+
// Extracted into separate fn so it's only compiled once for all T.
48+
async fn extract_form_body_bytes(req: Request) -> Result<Bytes, FormRejection> {
5349
if !crate::service::web::extract::has_any_content_type(
5450
req.headers(),
5551
&[&mime::APPLICATION_WWW_FORM_URLENCODED],
@@ -58,16 +54,24 @@ where
5854
}
5955

6056
let body = req.into_body();
61-
match body.collect().await {
62-
Ok(c) => {
63-
let value = match serde_html_form::from_bytes(&c.to_bytes()) {
64-
Ok(value) => value,
65-
Err(err) => return Err(FailedToDeserializeForm::from_err(err).into()),
66-
};
67-
Ok(Form(value))
68-
}
69-
Err(err) => Err(BytesRejection::from_err(err).into()),
70-
}
57+
let bytes = body.collect().await.map_err(BytesRejection::from_err)?;
58+
59+
Ok(bytes.to_bytes())
60+
}
61+
62+
if req.method() == Method::GET {
63+
let query = req.uri().query().unwrap_or_default();
64+
let value = match serde_html_form::from_bytes(query.as_bytes()) {
65+
Ok(value) => value,
66+
Err(err) => return Err(FailedToDeserializeForm::from_err(err).into()),
67+
};
68+
Ok(Form(value))
69+
} else {
70+
let b = extract_form_body_bytes(req).await?;
71+
Ok(Form(match serde_html_form::from_bytes(&b) {
72+
Ok(value) => value,
73+
Err(err) => return Err(FailedToDeserializeForm::from_err(err).into()),
74+
}))
7175
}
7276
}
7377
}

rama-http/src/service/web/endpoint/extract/body/json.rs

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use bytes::Bytes;
2+
13
use super::BytesRejection;
24
use crate::Request;
35
use crate::dep::http_body_util::BodyExt;
@@ -42,23 +44,27 @@ where
4244
type Rejection = JsonRejection;
4345

4446
async fn from_request(req: Request) -> Result<Self, Self::Rejection> {
45-
if !crate::service::web::extract::has_any_content_type(
46-
req.headers(),
47-
&[&mime::APPLICATION_JSON],
48-
) {
49-
return Err(InvalidJsonContentType.into());
50-
}
47+
// Extracted into separate fn so it's only compiled once for all T.
48+
async fn extract_json_bytes(req: Request) -> Result<Bytes, JsonRejection> {
49+
if !crate::service::web::extract::has_any_content_type(
50+
req.headers(),
51+
&[&mime::APPLICATION_JSON],
52+
) {
53+
return Err(InvalidJsonContentType.into());
54+
}
5155

52-
let body = req.into_body();
53-
match body.collect().await {
54-
Ok(c) => {
55-
let b = c.to_bytes();
56-
match serde_json::from_slice(&b) {
57-
Ok(s) => Ok(Self(s)),
58-
Err(err) => Err(FailedToDeserializeJson::from_err(err).into()),
59-
}
56+
let body = req.into_body();
57+
58+
match body.collect().await {
59+
Ok(c) => Ok(c.to_bytes()),
60+
Err(err) => Err(BytesRejection::from_err(err).into()),
6061
}
61-
Err(err) => Err(BytesRejection::from_err(err).into()),
62+
}
63+
64+
let b = extract_json_bytes(req).await?;
65+
match serde_json::from_slice(&b) {
66+
Ok(s) => Ok(Self(s)),
67+
Err(err) => Err(FailedToDeserializeJson::from_err(err).into()),
6268
}
6369
}
6470
}

0 commit comments

Comments
 (0)