mirror of
https://github.com/denoland/deno.git
synced 2025-01-07 06:46:59 -05:00
refactor(ext/http): simpler ws server in http_next (#19133)
Merges `op_http_upgrade_next` and `op_ws_server_create`, significantly simplifying websocket construction in ext/http (next), and removing one JS -> Rust call. Also WS server now doesn't bypass `HttpPropertyExtractor`.
This commit is contained in:
parent
4df46b7056
commit
17b4e0627c
5 changed files with 12 additions and 67 deletions
|
@ -49,8 +49,6 @@ const {
|
||||||
} = primordials;
|
} = primordials;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
op_http_wait,
|
|
||||||
op_http_upgrade_next,
|
|
||||||
op_http_get_request_headers,
|
op_http_get_request_headers,
|
||||||
op_http_get_request_method_and_url,
|
op_http_get_request_method_and_url,
|
||||||
op_http_read_request_body,
|
op_http_read_request_body,
|
||||||
|
@ -63,10 +61,9 @@ const {
|
||||||
op_http_set_response_header,
|
op_http_set_response_header,
|
||||||
op_http_set_response_headers,
|
op_http_set_response_headers,
|
||||||
op_http_upgrade_raw,
|
op_http_upgrade_raw,
|
||||||
op_ws_server_create,
|
op_http_upgrade_websocket_next,
|
||||||
|
op_http_wait,
|
||||||
} = core.generateAsyncOpHandler(
|
} = core.generateAsyncOpHandler(
|
||||||
"op_http_wait",
|
|
||||||
"op_http_upgrade_next",
|
|
||||||
"op_http_get_request_headers",
|
"op_http_get_request_headers",
|
||||||
"op_http_get_request_method_and_url",
|
"op_http_get_request_method_and_url",
|
||||||
"op_http_read_request_body",
|
"op_http_read_request_body",
|
||||||
|
@ -79,7 +76,8 @@ const {
|
||||||
"op_http_set_response_header",
|
"op_http_set_response_header",
|
||||||
"op_http_set_response_headers",
|
"op_http_set_response_headers",
|
||||||
"op_http_upgrade_raw",
|
"op_http_upgrade_raw",
|
||||||
"op_ws_server_create",
|
"op_http_upgrade_websocket_next",
|
||||||
|
"op_http_wait",
|
||||||
);
|
);
|
||||||
const _upgraded = Symbol("_upgraded");
|
const _upgraded = Symbol("_upgraded");
|
||||||
|
|
||||||
|
@ -208,12 +206,11 @@ class InnerRequest {
|
||||||
// Start the upgrade in the background.
|
// Start the upgrade in the background.
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
// Returns the connection and extra bytes, which we can pass directly to op_ws_server_create
|
// Returns the upgraded websocket connection
|
||||||
const upgrade = await op_http_upgrade_next(
|
const wsRid = await op_http_upgrade_websocket_next(
|
||||||
slabId,
|
slabId,
|
||||||
response.headerList,
|
response.headerList,
|
||||||
);
|
);
|
||||||
const wsRid = op_ws_server_create(upgrade[0], upgrade[1]);
|
|
||||||
|
|
||||||
// We have to wait for the go-ahead signal
|
// We have to wait for the go-ahead signal
|
||||||
await goAhead;
|
await goAhead;
|
||||||
|
|
|
@ -29,10 +29,9 @@ use deno_core::OpState;
|
||||||
use deno_core::RcRef;
|
use deno_core::RcRef;
|
||||||
use deno_core::Resource;
|
use deno_core::Resource;
|
||||||
use deno_core::ResourceId;
|
use deno_core::ResourceId;
|
||||||
use deno_core::ZeroCopyBuf;
|
|
||||||
use deno_net::ops_tls::TlsStream;
|
use deno_net::ops_tls::TlsStream;
|
||||||
use deno_net::raw::put_network_stream_resource;
|
|
||||||
use deno_net::raw::NetworkStream;
|
use deno_net::raw::NetworkStream;
|
||||||
|
use deno_websocket::ws_create_server_stream;
|
||||||
use fly_accept_encoding::Encoding;
|
use fly_accept_encoding::Encoding;
|
||||||
use http::header::ACCEPT_ENCODING;
|
use http::header::ACCEPT_ENCODING;
|
||||||
use http::header::CACHE_CONTROL;
|
use http::header::CACHE_CONTROL;
|
||||||
|
@ -314,11 +313,11 @@ pub fn op_http_upgrade_raw(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
pub async fn op_http_upgrade_next(
|
pub async fn op_http_upgrade_websocket_next(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
index: u32,
|
index: u32,
|
||||||
headers: Vec<(ByteString, ByteString)>,
|
headers: Vec<(ByteString, ByteString)>,
|
||||||
) -> Result<(ResourceId, ZeroCopyBuf), AnyError> {
|
) -> Result<ResourceId, AnyError> {
|
||||||
// Stage 1: set the respnse to 101 Switching Protocols and send it
|
// Stage 1: set the respnse to 101 Switching Protocols and send it
|
||||||
let upgrade = with_http_mut(index, |http| {
|
let upgrade = with_http_mut(index, |http| {
|
||||||
// Manually perform the upgrade. We're peeking into hyper's underlying machinery here a bit
|
// Manually perform the upgrade. We're peeking into hyper's underlying machinery here a bit
|
||||||
|
@ -343,17 +342,9 @@ pub async fn op_http_upgrade_next(
|
||||||
// Stage 2: wait for the request to finish upgrading
|
// Stage 2: wait for the request to finish upgrading
|
||||||
let upgraded = upgrade.await?;
|
let upgraded = upgrade.await?;
|
||||||
|
|
||||||
// Stage 3: return the extracted raw network stream
|
// Stage 3: take the extracted raw network stream and upgrade it to a websocket, then return it
|
||||||
let (stream, bytes) = extract_network_stream(upgraded);
|
let (stream, bytes) = extract_network_stream(upgraded);
|
||||||
|
ws_create_server_stream(&mut state.borrow_mut(), stream, bytes)
|
||||||
// We're allocating for those extra bytes, but they are probably going to be empty most of the time
|
|
||||||
Ok((
|
|
||||||
put_network_stream_resource(
|
|
||||||
&mut state.borrow_mut().resource_table,
|
|
||||||
stream,
|
|
||||||
)?,
|
|
||||||
ZeroCopyBuf::from(bytes.to_vec()),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op(fast)]
|
#[op(fast)]
|
||||||
|
|
|
@ -116,8 +116,8 @@ deno_core::extension!(
|
||||||
http_next::op_http_set_response_header,
|
http_next::op_http_set_response_header,
|
||||||
http_next::op_http_set_response_headers,
|
http_next::op_http_set_response_headers,
|
||||||
http_next::op_http_track,
|
http_next::op_http_track,
|
||||||
|
http_next::op_http_upgrade_websocket_next,
|
||||||
http_next::op_http_upgrade_raw,
|
http_next::op_http_upgrade_raw,
|
||||||
http_next::op_http_upgrade_next,
|
|
||||||
http_next::op_http_wait,
|
http_next::op_http_wait,
|
||||||
],
|
],
|
||||||
esm = ["00_serve.js", "01_http.js"],
|
esm = ["00_serve.js", "01_http.js"],
|
||||||
|
|
|
@ -260,31 +260,6 @@ pub fn take_network_stream_resource(
|
||||||
Err(bad_resource_id())
|
Err(bad_resource_id())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inserts a raw stream (back?) into the resource table and returns a resource ID. This can then be used to create raw connection
|
|
||||||
/// objects on the JS side.
|
|
||||||
pub fn put_network_stream_resource(
|
|
||||||
resource_table: &mut ResourceTable,
|
|
||||||
stream: NetworkStream,
|
|
||||||
) -> Result<ResourceId, AnyError> {
|
|
||||||
let res = match stream {
|
|
||||||
NetworkStream::Tcp(conn) => {
|
|
||||||
let (r, w) = conn.into_split();
|
|
||||||
resource_table.add(TcpStreamResource::new((r, w)))
|
|
||||||
}
|
|
||||||
NetworkStream::Tls(conn) => {
|
|
||||||
let (r, w) = conn.into_split();
|
|
||||||
resource_table.add(TlsStreamResource::new((r, w)))
|
|
||||||
}
|
|
||||||
#[cfg(unix)]
|
|
||||||
NetworkStream::Unix(conn) => {
|
|
||||||
let (r, w) = conn.into_split();
|
|
||||||
resource_table.add(UnixStreamResource::new((r, w)))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// In some cases it may be more efficient to extract the resource from the resource table and use it directly (for example, an HTTP server).
|
/// In some cases it may be more efficient to extract the resource from the resource table and use it directly (for example, an HTTP server).
|
||||||
/// This method will extract a stream from the resource table and return it, unwrapped.
|
/// This method will extract a stream from the resource table and return it, unwrapped.
|
||||||
pub fn take_network_stream_listener_resource(
|
pub fn take_network_stream_listener_resource(
|
||||||
|
|
|
@ -16,7 +16,6 @@ use deno_core::Resource;
|
||||||
use deno_core::ResourceId;
|
use deno_core::ResourceId;
|
||||||
use deno_core::StringOrBuffer;
|
use deno_core::StringOrBuffer;
|
||||||
use deno_core::ZeroCopyBuf;
|
use deno_core::ZeroCopyBuf;
|
||||||
use deno_net::raw::take_network_stream_resource;
|
|
||||||
use deno_net::raw::NetworkStream;
|
use deno_net::raw::NetworkStream;
|
||||||
use deno_tls::create_client_config;
|
use deno_tls::create_client_config;
|
||||||
use deno_tls::RootCertStoreProvider;
|
use deno_tls::RootCertStoreProvider;
|
||||||
|
@ -367,22 +366,6 @@ pub fn ws_create_server_stream(
|
||||||
Ok(rid)
|
Ok(rid)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op]
|
|
||||||
pub fn op_ws_server_create(
|
|
||||||
state: &mut OpState,
|
|
||||||
conn: ResourceId,
|
|
||||||
extra_bytes: &[u8],
|
|
||||||
) -> Result<ResourceId, AnyError> {
|
|
||||||
let network_stream =
|
|
||||||
take_network_stream_resource(&mut state.resource_table, conn)?;
|
|
||||||
// Copying the extra bytes, but unlikely this will account for much
|
|
||||||
ws_create_server_stream(
|
|
||||||
state,
|
|
||||||
network_stream,
|
|
||||||
Bytes::from(extra_bytes.to_vec()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
pub async fn op_ws_send_binary(
|
pub async fn op_ws_send_binary(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
|
@ -534,7 +517,6 @@ deno_core::extension!(deno_websocket,
|
||||||
op_ws_send_text,
|
op_ws_send_text,
|
||||||
op_ws_send_ping,
|
op_ws_send_ping,
|
||||||
op_ws_send_pong,
|
op_ws_send_pong,
|
||||||
op_ws_server_create,
|
|
||||||
],
|
],
|
||||||
esm = [ "01_websocket.js", "02_websocketstream.js" ],
|
esm = [ "01_websocket.js", "02_websocketstream.js" ],
|
||||||
options = {
|
options = {
|
||||||
|
|
Loading…
Reference in a new issue