Skip to content

Commit 4bf5e76

Browse files
committed
Move forbidden header validation to send, validate syntax in set/append
1 parent fe05c4d commit 4bf5e76

11 files changed

Lines changed: 126 additions & 163 deletions

File tree

crates/test-programs/src/bin/api_proxy.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,18 @@ pub mod bindings {
1010
});
1111
}
1212

13-
use bindings::wasi::http::types::{FieldsType, IncomingRequest, ResponseOutparam};
13+
use bindings::wasi::http::types::{IncomingRequest, ResponseOutparam};
1414

1515
struct T;
1616

1717
impl bindings::exports::wasi::http::incoming_handler::Guest for T {
1818
fn handle(_request: IncomingRequest, outparam: ResponseOutparam) {
19-
let hdrs = bindings::wasi::http::types::Headers::new(FieldsType::Response, &[]);
19+
let hdrs = bindings::wasi::http::types::Headers::new(&[]);
2020
let resp = bindings::wasi::http::types::OutgoingResponse::new(200, &hdrs);
2121
let body = resp.write().expect("outgoing response");
2222

23-
bindings::wasi::http::types::ResponseOutparam::set(outparam, Ok(resp));
23+
bindings::wasi::http::types::ResponseOutparam::set(outparam, Ok(resp))
24+
.expect("sending the response");
2425

2526
let out = body.write().expect("outgoing stream");
2627
out.blocking_write_and_flush(b"hello, world!")

crates/test-programs/src/bin/api_proxy_streaming.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use anyhow::{bail, Result};
22
use bindings::wasi::http::types::{
3-
Fields, FieldsType, IncomingRequest, Method, OutgoingBody, OutgoingRequest, OutgoingResponse,
3+
Fields, IncomingRequest, Method, OutgoingBody, OutgoingRequest, OutgoingResponse,
44
ResponseOutparam, Scheme,
55
};
66
use futures::{stream, SinkExt, StreamExt, TryStreamExt};
@@ -51,16 +51,13 @@ async fn handle_request(request: IncomingRequest, response_out: ResponseOutparam
5151

5252
let response = OutgoingResponse::new(
5353
200,
54-
&Fields::new(
55-
FieldsType::Response,
56-
&[("content-type".to_string(), b"text/plain".to_vec())],
57-
),
54+
&Fields::new(&[("content-type".to_string(), b"text/plain".to_vec())]),
5855
);
5956

6057
let mut body =
6158
executor::outgoing_body(response.write().expect("response should be writable"));
6259

63-
ResponseOutparam::set(response_out, Ok(response));
60+
ResponseOutparam::set(response_out, Ok(response)).expect("sending the response");
6461

6562
while let Some((url, result)) = results.next().await {
6663
let payload = match result {
@@ -79,7 +76,6 @@ async fn handle_request(request: IncomingRequest, response_out: ResponseOutparam
7976
let response = OutgoingResponse::new(
8077
200,
8178
&Fields::new(
82-
FieldsType::Response,
8379
&headers
8480
.into_iter()
8581
.filter_map(|(k, v)| (k == "content-type").then_some((k, v)))
@@ -90,7 +86,7 @@ async fn handle_request(request: IncomingRequest, response_out: ResponseOutparam
9086
let mut body =
9187
executor::outgoing_body(response.write().expect("response should be writable"));
9288

93-
ResponseOutparam::set(response_out, Ok(response));
89+
ResponseOutparam::set(response_out, Ok(response)).expect("sending the response");
9490

9591
let mut stream =
9692
executor::incoming_body(request.consume().expect("request should be readable"));
@@ -112,11 +108,11 @@ async fn handle_request(request: IncomingRequest, response_out: ResponseOutparam
112108
}
113109

114110
_ => {
115-
let response = OutgoingResponse::new(405, &Fields::new(FieldsType::Response, &[]));
111+
let response = OutgoingResponse::new(405, &Fields::new(&[]));
116112

117113
let body = response.write().expect("response should be writable");
118114

119-
ResponseOutparam::set(response_out, Ok(response));
115+
ResponseOutparam::set(response_out, Ok(response)).expect("sending the response");
120116

121117
OutgoingBody::finish(body, None);
122118
}
@@ -141,7 +137,7 @@ async fn hash(url: &Url) -> Result<String> {
141137
String::new()
142138
}
143139
)),
144-
&Fields::new(FieldsType::Request, &[]),
140+
&Fields::new(&[]),
145141
);
146142

147143
let response = executor::outgoing_request_send(request).await?;
Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
1-
use test_programs::wasi::http::types::{FieldsType, Headers};
1+
use test_programs::wasi::http::types::{Headers, Method, Scheme};
22

33
fn main() {
4-
let hdrs = Headers::new(FieldsType::Request, &[]);
4+
let hdrs = Headers::new(&[]);
55
assert!(hdrs
6-
.set(&"transfer-encoding".to_owned(), &[b"bad".to_vec()])
6+
.append(&"malformed header name".to_owned(), &b"bad".to_vec())
77
.is_err());
88

9-
assert!(hdrs
10-
.append(&"tRaNsFeR-eNcOdInG".to_owned(), &b"bad".to_vec())
11-
.is_err());
9+
let addr = std::env::var("HTTP_SERVER").unwrap();
10+
let err = test_programs::http::request(
11+
Method::Get,
12+
Scheme::Http,
13+
&addr,
14+
"/get?some=arg&goes=here",
15+
None,
16+
Some(&[("transfer-encoding".to_owned(), b"bad".to_vec())]),
17+
)
18+
.expect_err("invalid request");
19+
20+
assert_eq!(
21+
err.to_string(),
22+
"Error::HeaderNameError(\"forbidden header\")"
23+
);
1224
}

crates/test-programs/src/bin/http_outbound_request_response_build.rs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,10 @@ use test_programs::wasi::http::types as http_types;
33
fn main() {
44
println!("Called _start");
55
{
6-
let headers = http_types::Headers::new(
7-
http_types::FieldsType::Request,
8-
&[(
9-
"Content-Type".to_string(),
10-
"application/json".to_string().into_bytes(),
11-
)],
12-
);
6+
let headers = http_types::Headers::new(&[(
7+
"Content-Type".to_string(),
8+
"application/json".to_string().into_bytes(),
9+
)]);
1310
let request = http_types::OutgoingRequest::new(
1411
&http_types::Method::Get,
1512
None,
@@ -24,13 +21,10 @@ fn main() {
2421
.unwrap();
2522
}
2623
{
27-
let headers = http_types::Headers::new(
28-
http_types::FieldsType::Response,
29-
&[(
30-
"Content-Type".to_string(),
31-
"application/text".to_string().into_bytes(),
32-
)],
33-
);
24+
let headers = http_types::Headers::new(&[(
25+
"Content-Type".to_string(),
26+
"application/text".to_string().into_bytes(),
27+
)]);
3428
let response = http_types::OutgoingResponse::new(200, &headers);
3529
let outgoing_body = response.write().unwrap();
3630
let response_body = outgoing_body.write().unwrap();

crates/test-programs/src/http.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ pub fn request(
4343
v.to_string().into_bytes()
4444
}
4545
let headers = http_types::Headers::new(
46-
http_types::FieldsType::Request,
4746
&[
4847
&[
4948
("User-agent".to_string(), header_val("WASI-HTTP/0.0.1")),

crates/wasi-http/src/body.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ pub type HyperIncomingBody = BoxBody<Bytes, anyhow::Error>;
1919
/// one. The HostIncomingBody spawns a task that starts consuming the incoming body, and we don't
2020
/// want to do that unless the user asks to consume the body.
2121
pub struct HostIncomingBodyBuilder {
22-
pub ty: types::FieldsType,
2322
pub body: HyperIncomingBody,
2423
pub between_bytes_timeout: Duration,
2524
}
@@ -104,7 +103,6 @@ impl HostIncomingBodyBuilder {
104103
});
105104

106105
HostIncomingBody {
107-
ty: self.ty,
108106
worker,
109107
stream: Some(HostIncomingBodyStream::new(body_receiver)),
110108
trailers,
@@ -113,7 +111,6 @@ impl HostIncomingBodyBuilder {
113111
}
114112

115113
pub struct HostIncomingBody {
116-
ty: types::FieldsType,
117114
pub worker: AbortOnDropJoinHandle<()>,
118115
pub stream: Option<HostIncomingBodyStream>,
119116
pub trailers: oneshot::Receiver<Result<hyper::HeaderMap, anyhow::Error>>,
@@ -123,7 +120,6 @@ impl HostIncomingBody {
123120
pub fn into_future_trailers(self) -> HostFutureTrailers {
124121
HostFutureTrailers {
125122
_worker: self.worker,
126-
ty: self.ty,
127123
state: HostFutureTrailersState::Waiting(self.trailers),
128124
}
129125
}
@@ -220,7 +216,6 @@ impl Subscribe for HostIncomingBodyStream {
220216

221217
pub struct HostFutureTrailers {
222218
_worker: AbortOnDropJoinHandle<()>,
223-
pub ty: types::FieldsType,
224219
pub state: HostFutureTrailersState,
225220
}
226221

crates/wasi-http/src/http_impl.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::bindings::http::{
22
outgoing_handler,
3-
types::{RequestOptions, Scheme},
3+
types::{self as http_types, RequestOptions, Scheme},
44
};
55
use crate::types::{self, HostFutureIncomingResponse, OutgoingRequest};
66
use crate::WasiHttpView;
@@ -77,6 +77,12 @@ impl<T: WasiHttpView> outgoing_handler::Host for T {
7777
.header(hyper::header::HOST, &authority);
7878

7979
for (k, v) in req.headers.iter() {
80+
if self.is_forbidden_request_header(k) {
81+
return Ok(Err(http_types::Error::HeaderNameError(
82+
"forbidden header".to_owned(),
83+
)));
84+
}
85+
8086
builder = builder.header(k, v);
8187
}
8288

crates/wasi-http/src/types.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ pub trait WasiHttpView: Send {
3737
) -> wasmtime::Result<Resource<HostIncomingRequest>> {
3838
let (parts, body) = req.into_parts();
3939
let body = HostIncomingBodyBuilder {
40-
ty: types::FieldsType::Request,
4140
body,
4241
// TODO: this needs to be plumbed through
4342
between_bytes_timeout: std::time::Duration::from_millis(600 * 1000),
@@ -284,11 +283,9 @@ pub enum HostFields {
284283
// always be registered as a child of the entry with the `parent` id. This ensures that the
285284
// entry will always exist while this `HostFields::Ref` entry exists in the table, thus we
286285
// don't need to account for failure when fetching the fields ref from the parent.
287-
get_fields:
288-
for<'a> fn(elem: &'a mut (dyn Any + 'static)) -> (types::FieldsType, &'a mut FieldMap),
286+
get_fields: for<'a> fn(elem: &'a mut (dyn Any + 'static)) -> &'a mut FieldMap,
289287
},
290288
Owned {
291-
ty: types::FieldsType,
292289
fields: FieldMap,
293290
},
294291
}

0 commit comments

Comments
 (0)