mirror of
https://github.com/denoland/deno.git
synced 2024-12-01 16:51:13 -05:00
parent
ad7f6d4510
commit
fe9cee620a
3 changed files with 51 additions and 12 deletions
|
@ -200,3 +200,30 @@ unitTest(
|
||||||
client.close();
|
client.close();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
unitTest(
|
||||||
|
{ perms: { net: true } },
|
||||||
|
async function httpServerRegressionHang() {
|
||||||
|
const promise = (async () => {
|
||||||
|
const listener = Deno.listen({ port: 4501 });
|
||||||
|
const conn = await listener.accept();
|
||||||
|
const httpConn = Deno.serveHttp(conn);
|
||||||
|
const event = await httpConn.nextRequest();
|
||||||
|
assert(event);
|
||||||
|
const { request, respondWith } = event;
|
||||||
|
const reqBody = await request.text();
|
||||||
|
assertEquals("request", reqBody);
|
||||||
|
await respondWith(new Response("response"));
|
||||||
|
httpConn.close();
|
||||||
|
listener.close();
|
||||||
|
})();
|
||||||
|
|
||||||
|
const resp = await fetch("http://127.0.0.1:4501/", {
|
||||||
|
method: "POST",
|
||||||
|
body: "request",
|
||||||
|
});
|
||||||
|
const respBody = await resp.text();
|
||||||
|
assertEquals("response", respBody);
|
||||||
|
await promise;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
|
@ -130,7 +130,7 @@
|
||||||
zeroCopyBuf = null;
|
zeroCopyBuf = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const responseBodyRid = Deno.core.opSync("op_http_response", [
|
const responseBodyRid = await Deno.core.opAsync("op_http_response", [
|
||||||
responseSenderRid,
|
responseSenderRid,
|
||||||
resp.status ?? 200,
|
resp.status ?? 200,
|
||||||
flattenHeaders(resp.headers),
|
flattenHeaders(resp.headers),
|
||||||
|
|
|
@ -48,7 +48,7 @@ pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||||
super::reg_async(rt, "op_http_request_next", op_http_request_next);
|
super::reg_async(rt, "op_http_request_next", op_http_request_next);
|
||||||
super::reg_async(rt, "op_http_request_read", op_http_request_read);
|
super::reg_async(rt, "op_http_request_read", op_http_request_read);
|
||||||
|
|
||||||
super::reg_sync(rt, "op_http_response", op_http_response);
|
super::reg_async(rt, "op_http_response", op_http_response);
|
||||||
super::reg_async(rt, "op_http_response_write", op_http_response_write);
|
super::reg_async(rt, "op_http_response_write", op_http_response_write);
|
||||||
super::reg_async(rt, "op_http_response_close", op_http_response_close);
|
super::reg_async(rt, "op_http_response_close", op_http_response_close);
|
||||||
}
|
}
|
||||||
|
@ -312,16 +312,15 @@ struct RespondArgs(
|
||||||
Vec<String>,
|
Vec<String>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn op_http_response(
|
async fn op_http_response(
|
||||||
state: &mut OpState,
|
state: Rc<RefCell<OpState>>,
|
||||||
args: RespondArgs,
|
args: RespondArgs,
|
||||||
data: Option<ZeroCopyBuf>,
|
data: Option<ZeroCopyBuf>,
|
||||||
) -> Result<Option<ResourceId>, AnyError> {
|
) -> Result<Option<ResourceId>, AnyError> {
|
||||||
let rid = args.0;
|
let RespondArgs(rid, status, headers) = args;
|
||||||
let status = args.1;
|
|
||||||
let headers = args.2;
|
|
||||||
|
|
||||||
let response_sender = state
|
let response_sender = state
|
||||||
|
.borrow_mut()
|
||||||
.resource_table
|
.resource_table
|
||||||
.take::<ResponseSenderResource>(rid)
|
.take::<ResponseSenderResource>(rid)
|
||||||
.ok_or_else(bad_resource_id)?;
|
.ok_or_else(bad_resource_id)?;
|
||||||
|
@ -329,6 +328,12 @@ fn op_http_response(
|
||||||
.ok()
|
.ok()
|
||||||
.expect("multiple op_http_respond ongoing");
|
.expect("multiple op_http_respond ongoing");
|
||||||
|
|
||||||
|
let conn_resource = state
|
||||||
|
.borrow()
|
||||||
|
.resource_table
|
||||||
|
.get::<ConnResource>(response_sender.conn_rid)
|
||||||
|
.ok_or_else(bad_resource_id)?;
|
||||||
|
|
||||||
let mut builder = Response::builder().status(status);
|
let mut builder = Response::builder().status(status);
|
||||||
|
|
||||||
debug_assert_eq!(headers.len() % 2, 0);
|
debug_assert_eq!(headers.len() % 2, 0);
|
||||||
|
@ -348,7 +353,8 @@ fn op_http_response(
|
||||||
let (sender, body) = Body::channel();
|
let (sender, body) = Body::channel();
|
||||||
res = builder.body(body)?;
|
res = builder.body(body)?;
|
||||||
|
|
||||||
let response_body_rid = state.resource_table.add(ResponseBodyResource {
|
let response_body_rid =
|
||||||
|
state.borrow_mut().resource_table.add(ResponseBodyResource {
|
||||||
body: AsyncRefCell::new(sender),
|
body: AsyncRefCell::new(sender),
|
||||||
cancel: CancelHandle::default(),
|
cancel: CancelHandle::default(),
|
||||||
conn_rid: response_sender.conn_rid,
|
conn_rid: response_sender.conn_rid,
|
||||||
|
@ -364,6 +370,12 @@ fn op_http_response(
|
||||||
return Err(type_error("internal communication error"));
|
return Err(type_error("internal communication error"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
poll_fn(|cx| match conn_resource.poll(cx) {
|
||||||
|
Poll::Ready(x) => Poll::Ready(x),
|
||||||
|
Poll::Pending => Poll::Ready(Ok(())),
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(maybe_response_body_rid)
|
Ok(maybe_response_body_rid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue