1use crate::http::body::Body;
2use crate::Cf;
3use crate::Result;
4use crate::{http::redirect::RequestRedirect, AbortSignal};
5use worker_sys::ext::RequestExt;
6
7use crate::http::body::BodyStream;
8use crate::http::header::{header_map_from_web_sys_headers, web_sys_headers_from_header_map};
9use bytes::Bytes;
10
11fn version_from_string(version: &str) -> http::Version {
12 match version {
13 "HTTP/0.9" => http::Version::HTTP_09,
14 "HTTP/1.0" => http::Version::HTTP_10,
15 "HTTP/1.1" => http::Version::HTTP_11,
16 "HTTP/2" => http::Version::HTTP_2,
17 "HTTP/3" => http::Version::HTTP_3,
18 _ => unreachable!("no other versions exist"),
19 }
20}
21
22pub fn from_wasm(req: web_sys::Request) -> Result<http::Request<Body>> {
25 let mut builder = http::request::Builder::new()
26 .uri(req.url())
27 .extension(AbortSignal::from(req.signal()))
28 .extension(RequestRedirect::from(req.redirect()))
29 .method(&*req.method());
30
31 if let Some(headers) = builder.headers_mut() {
32 header_map_from_web_sys_headers(req.headers(), headers)?;
33 }
34
35 if let Some(cf) = req.cf() {
36 builder = builder
37 .version(version_from_string(&cf.http_protocol()?))
38 .extension(Cf::new(cf));
39 }
40
41 Ok(if let Some(body) = req.body() {
42 builder.body(Body::new(body))?
43 } else {
44 builder.body(Body::empty())?
45 })
46}
47
48pub fn to_wasm<B: http_body::Body<Data = Bytes> + 'static>(
51 mut req: http::Request<B>,
52) -> Result<web_sys::Request> {
53 let init = web_sys::RequestInit::new();
54 init.set_method(req.method().as_str());
55 let headers = web_sys_headers_from_header_map(req.headers())?;
56 init.set_headers(headers.as_ref());
57 let uri = req.uri().to_string();
58
59 let signal = req.extensions_mut().remove::<AbortSignal>();
60 init.set_signal(signal.as_ref().map(|s| s.inner()));
61
62 if let Some(redirect) = req.extensions_mut().remove::<RequestRedirect>() {
63 init.set_redirect(redirect.into());
64 }
65
66 if let Some(cf) = req.extensions_mut().remove::<Cf>() {
67 let r = ::js_sys::Reflect::set(
69 init.as_ref(),
70 &wasm_bindgen::JsValue::from("cf"),
71 &wasm_bindgen::JsValue::from(cf.inner()),
72 );
73 debug_assert!(
74 r.is_ok(),
75 "setting properties should never fail on our dictionary objects"
76 );
77 let _ = r;
78 }
79
80 let body = req.into_body();
81 if !body.is_end_stream() {
82 let readable_stream =
83 wasm_streams::ReadableStream::from_stream(BodyStream::new(body)).into_raw();
84 init.set_body(readable_stream.as_ref());
85 }
86
87 Ok(web_sys::Request::new_with_str_and_init(&uri, &init)?)
88}