diff options
Diffstat (limited to 'ext/http/slab.rs')
-rw-r--r-- | ext/http/slab.rs | 62 |
1 files changed, 59 insertions, 3 deletions
diff --git a/ext/http/slab.rs b/ext/http/slab.rs index dbe1a6635..8c285c860 100644 --- a/ext/http/slab.rs +++ b/ext/http/slab.rs @@ -3,6 +3,8 @@ use crate::request_properties::HttpConnectionProperties; use crate::response_body::CompletionHandle; use crate::response_body::ResponseBytes; use deno_core::error::AnyError; +use deno_core::OpState; +use deno_core::ResourceId; use http::request::Parts; use http::HeaderMap; use hyper1::body::Incoming; @@ -18,10 +20,36 @@ pub type Request = hyper1::Request<Incoming>; pub type Response = hyper1::Response<ResponseBytes>; pub type SlabId = u32; +enum RequestBodyState { + Incoming(Incoming), + Resource(HttpRequestBodyAutocloser), +} + +impl From<Incoming> for RequestBodyState { + fn from(value: Incoming) -> Self { + RequestBodyState::Incoming(value) + } +} + +/// Ensures that the request body closes itself when no longer needed. +pub struct HttpRequestBodyAutocloser(ResourceId, Rc<RefCell<OpState>>); + +impl HttpRequestBodyAutocloser { + pub fn new(res: ResourceId, op_state: Rc<RefCell<OpState>>) -> Self { + Self(res, op_state) + } +} + +impl Drop for HttpRequestBodyAutocloser { + fn drop(&mut self) { + _ = self.1.borrow_mut().resource_table.close(self.0); + } +} + pub struct HttpSlabRecord { request_info: HttpConnectionProperties, request_parts: Parts, - request_body: Option<Incoming>, + request_body: Option<RequestBodyState>, // The response may get taken before we tear this down response: Option<Response>, promise: CompletionHandle, @@ -98,6 +126,7 @@ fn slab_insert_raw( let mut slab = slab.borrow_mut(); let body = ResponseBytes::default(); let trailers = body.trailers(); + let request_body = request_body.map(|r| r.into()); slab.insert(HttpSlabRecord { request_info, request_parts, @@ -174,8 +203,35 @@ impl SlabEntry { } /// Take the Hyper body from this entry. - pub fn take_body(&mut self) -> Incoming { - self.self_mut().request_body.take().unwrap() + pub fn take_body(&mut self) -> Option<Incoming> { + let body_holder = &mut self.self_mut().request_body; + let body = body_holder.take(); + match body { + Some(RequestBodyState::Incoming(body)) => Some(body), + x => { + *body_holder = x; + None + } + } + } + + pub fn take_resource(&mut self) -> Option<HttpRequestBodyAutocloser> { + let body_holder = &mut self.self_mut().request_body; + let body = body_holder.take(); + match body { + Some(RequestBodyState::Resource(res)) => Some(res), + x => { + *body_holder = x; + None + } + } + } + + /// Replace the request body with a resource ID and the OpState we'll need to shut it down. + /// We cannot keep just the resource itself, as JS code might be reading from the resource ID + /// to generate the response data (requiring us to keep it in the resource table). + pub fn put_resource(&mut self, res: HttpRequestBodyAutocloser) { + self.self_mut().request_body = Some(RequestBodyState::Resource(res)); } /// Complete this entry, potentially expunging it if it is complete. |