Path: blob/main/crates/wasi-http/src/http_impl.rs
1692 views
//! Implementation of the `wasi:http/outgoing-handler` interface.12use crate::{3WasiHttpImpl, WasiHttpView,4bindings::http::{5outgoing_handler,6types::{self, Scheme},7},8error::internal_error,9http_request_error,10types::{HostFutureIncomingResponse, HostOutgoingRequest, OutgoingRequestConfig},11};12use bytes::Bytes;13use http_body_util::{BodyExt, Empty};14use hyper::Method;15use wasmtime::component::Resource;1617impl<T> outgoing_handler::Host for WasiHttpImpl<T>18where19T: WasiHttpView,20{21fn handle(22&mut self,23request_id: Resource<HostOutgoingRequest>,24options: Option<Resource<types::RequestOptions>>,25) -> crate::HttpResult<Resource<HostFutureIncomingResponse>> {26let opts = options.and_then(|opts| self.table().get(&opts).ok());2728let connect_timeout = opts29.and_then(|opts| opts.connect_timeout)30.unwrap_or(std::time::Duration::from_secs(600));3132let first_byte_timeout = opts33.and_then(|opts| opts.first_byte_timeout)34.unwrap_or(std::time::Duration::from_secs(600));3536let between_bytes_timeout = opts37.and_then(|opts| opts.between_bytes_timeout)38.unwrap_or(std::time::Duration::from_secs(600));3940let req = self.table().delete(request_id)?;41let mut builder = hyper::Request::builder();4243builder = builder.method(match req.method {44types::Method::Get => Method::GET,45types::Method::Head => Method::HEAD,46types::Method::Post => Method::POST,47types::Method::Put => Method::PUT,48types::Method::Delete => Method::DELETE,49types::Method::Connect => Method::CONNECT,50types::Method::Options => Method::OPTIONS,51types::Method::Trace => Method::TRACE,52types::Method::Patch => Method::PATCH,53types::Method::Other(m) => match hyper::Method::from_bytes(m.as_bytes()) {54Ok(method) => method,55Err(_) => return Err(types::ErrorCode::HttpRequestMethodInvalid.into()),56},57});5859let (use_tls, scheme) = match req.scheme.unwrap_or(Scheme::Https) {60Scheme::Http => (false, http::uri::Scheme::HTTP),61Scheme::Https => (true, http::uri::Scheme::HTTPS),6263// We can only support http/https64Scheme::Other(_) => return Err(types::ErrorCode::HttpProtocolError.into()),65};6667let authority = req.authority.unwrap_or_else(String::new);6869builder = builder.header(hyper::header::HOST, &authority);7071let mut uri = http::Uri::builder()72.scheme(scheme)73.authority(authority.clone());7475if let Some(path) = req.path_with_query {76uri = uri.path_and_query(path);77}7879builder = builder.uri(uri.build().map_err(http_request_error)?);8081for (k, v) in req.headers.iter() {82builder = builder.header(k, v);83}8485let body = req.body.unwrap_or_else(|| {86Empty::<Bytes>::new()87.map_err(|_| unreachable!("Infallible error"))88.boxed()89});9091let request = builder92.body(body)93.map_err(|err| internal_error(err.to_string()))?;9495let future = self.send_request(96request,97OutgoingRequestConfig {98use_tls,99connect_timeout,100first_byte_timeout,101between_bytes_timeout,102},103)?;104105Ok(self.table().push(future)?)106}107}108109110