Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1976,7 +1976,7 @@ jobs:
# stdlib/http/snippets.ts excluded since v0.5.886: it links
# against js_axios_response_data_parsed +
# js_node_http2_create_secure_server which live in
# perry-ext-axios / perry-ext-http-server. v0.5.885's
# perry-ext-axios / perry-ext-http. v0.5.885's
# PERRY_NO_AUTO_OPTIMIZE skips the well-known-binding probe
# that would route those .a files into the link surface.
# Proper fix: hoist well-known-binding lookup out of
Expand Down
15 changes: 1 addition & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ members = [
"crates/perry-ext-ws",
"crates/perry-ext-net",
"crates/perry-ext-http",
"crates/perry-ext-http-server",
"crates/perry-ext-streams",
"crates/perry-ext-fastify",
"crates/perry-ext-pdf",
Expand Down Expand Up @@ -371,6 +370,13 @@ similar = "2.4"
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "json", "multipart", "blocking"] }
tokio = { version = "1", features = ["full"] }
tokio-tungstenite = { version = "0.29", features = ["rustls-tls-webpki-roots"] }
hyper = "1.4"
hyper-util = "0.1"
http-body-util = "0.1"
tokio-rustls = "0.26"
rustls = "0.23"
rustls-pemfile = "2"
socket2 = "0.6"
futures-util = "0.3"
url = "2"
dirs = "6"
Expand Down Expand Up @@ -447,7 +453,6 @@ perry-ext-mongodb = { path = "crates/perry-ext-mongodb" }
perry-ext-ws = { path = "crates/perry-ext-ws" }
perry-ext-net = { path = "crates/perry-ext-net" }
perry-ext-http = { path = "crates/perry-ext-http" }
perry-ext-http-server = { path = "crates/perry-ext-http-server" }
perry-ext-streams = { path = "crates/perry-ext-streams" }
perry-ext-fastify = { path = "crates/perry-ext-fastify" }
perry-ext-pdf = { path = "crates/perry-ext-pdf" }
Expand Down
1 change: 1 addition & 0 deletions changelog.d/6826-http-server-consolidation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
refactor(http): merge the HTTP/1.1, HTTPS, HTTP/2, WebSocket upgrade, and event-loop pump implementation into `perry-ext-http` while preserving `libperry_ext_http.a` and its native ABI.
1 change: 1 addition & 0 deletions changelog.d/6834-http-ffi-boundary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
refactor(http): route production HTTP bindings through `perry-ffi` and remove the normal `perry-ext-http` dependency on `perry-runtime` while preserving the selected HTTP archive ABI.
1 change: 1 addition & 0 deletions changelog.d/6835-remove-stdlib-http-client.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
refactor(http): remove the duplicate bundled Node HTTP client and keep Node HTTP on `perry-ext-http`.
6 changes: 3 additions & 3 deletions crates/perry-codegen/src/ext_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,8 @@ const FFI_REGISTRY: &[(&str, OwnerKind)] = &[
("js_http_client_request_socket", OwnerKind::WellKnown("http")),

// ── #846: node:http server ───────────────────────────────────────
// `perry-ext-http-server` defines `js_node_http_*`. It's pulled in
// transitively via `perry-ext-http` (rlib dep), and the well-known
// `perry-ext-http` defines `js_node_http_*` in its internal server
// module, and the well-known
// table already has `[bindings.http]` / `[bindings.https]` /
// `[bindings.http2]` → `perry-ext-http`. So tagging these as
// `WellKnown("http")` makes the existing flip do the right thing:
Expand Down Expand Up @@ -834,7 +834,7 @@ mod tests {
}

/// #3954 regression: HTTP-suite native-table rows can emit newer
/// `perry-ext-http`, `perry-ext-http-server`, or `perry-ext-net`
/// `perry-ext-http` or `perry-ext-net`
/// symbols without the module-import path being visible to collection.
/// Each emitted external symbol must independently flip its well-known
/// owner so the wrapper joins the link line.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub(super) const HTTP_HTTP2_ROWS: &[NativeModSig] = &[
ret: NR_OBJ_FROM_JSON_STR,
},
// ========== node:http2 settings helpers (issue #3168) ==========
// Pure pack/unpack functions implemented in perry-ext-http-server (so
// Pure pack/unpack functions implemented in perry-ext-http (so
// their Buffer alloc/recognition shares the program's runtime copy).
NativeModSig {
module: "http2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[
// perry-codegen/src/expr.rs (not this table); the instance methods
// dispatch here once the let-binding gets registered as
// `("net", "Server")` in HIR lowering. Shape mirrors
// `js_node_http_server_*` from perry-ext-http-server (signatures
// `js_node_http_server_*` from perry-ext-http (signatures
// are deliberately parallel so the codegen side reads the same).
NativeModSig {
module: "net",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ pub(crate) fn declare_net_http(module: &mut LlModule) {
module.declare_function("js_https_request", I64, &[DOUBLE, I64]);

// ========== node:http / node:https / node:http2 SERVER (issue #577) ==========
// perry-ext-http-server — handler-push HTTP/1.1 + HTTP/2 + TLS via rustls.
// perry-ext-http — handler-push HTTP/1.1 + HTTP/2 + TLS via rustls.
// Symbols are linked through perry-ext-http (rlib dep), so the
// existing `bindings.http` / `bindings.https` / `bindings.http2`
// entries in well_known_bindings.toml route imports here.
Expand Down
12 changes: 6 additions & 6 deletions crates/perry-ext-fastify/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,24 @@ perry-ffi.workspace = true
# it from upgrade::handle_fastify_websocket_upgrade so the fastify
# `app.server.on("upgrade", …)` path produces a ws_id usable through
# the rest of the perry-ext-ws FFI surface. Mirrors the proven
# perry-ext-http-server (#577 Phase 4) dependency.
# perry-ext-http (#577 Phase 4) dependency.
perry-ext-ws = { path = "../perry-ext-ws" }
hyper = { version = "1.4", features = ["server", "http1", "http2"] }
hyper-util = { version = "0.1", features = ["server", "server-auto", "tokio"] }
http-body-util = "0.1"
hyper = { workspace = true, features = ["server", "http1", "http2"] }
hyper-util = { workspace = true, features = ["server", "server-auto", "tokio"] }
http-body-util.workspace = true
bytes.workspace = true
tokio = { workspace = true }
tokio-tungstenite = { workspace = true }
serde_json.workspace = true
lazy_static.workspace = true

# #cluster — SO_REUSEPORT bind for `cluster.fork()` workers (unix only),
# mirroring perry-ext-http-server's cluster_bind. The
# mirroring perry-ext-http's cluster_bind. The
# `perry_cluster_worker_listening` symbol it reports to resolves at final link
# (defined in perry-runtime), like perry-ffi's runtime helpers — no Cargo dep on
# perry-runtime is needed.
[target.'cfg(unix)'.dependencies]
socket2 = "0.6"
socket2.workspace = true

[dev-dependencies]
perry-ffi = { workspace = true, features = ["runtime-link"] }
Expand Down
8 changes: 4 additions & 4 deletions crates/perry-ext-fastify/src/cluster_bind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@
//!
//! This wires Fastify into the cluster machinery that already exists in
//! perry-runtime (`worker_reuseport_bind`, `perry_cluster_worker_listening`)
//! and is used by `net` and perry-ext-http-server. It mirrors the SO_REUSEPORT
//! (`SCHED_NONE`) path of perry-ext-http-server's HTTP/2 & HTTPS listen sites.
//! and is used by `net` and perry-ext-http. It mirrors the SO_REUSEPORT
//! (`SCHED_NONE`) path of perry-ext-http's HTTP/2 & HTTPS listen sites.
//! Round-robin fd-passing (`SCHED_RR`) and the shared ephemeral port for
//! `listen(0)` (#4962) are a follow-up here, exactly as for those sites today.

use std::net::{SocketAddr, TcpListener};

/// True when this process is a `cluster.fork()`ed worker (non-empty
/// `NODE_UNIQUE_ID` in the environment — the same check the runtime and
/// perry-ext-http-server use).
/// perry-ext-http use).
pub(crate) fn is_cluster_worker() -> bool {
std::env::var("NODE_UNIQUE_ID")
.map(|s| !s.is_empty())
Expand Down Expand Up @@ -62,7 +62,7 @@ pub(crate) fn bind_listener(addr: SocketAddr, reuse_port: bool) -> std::io::Resu
extern "C" {
// Defined in perry-runtime's cluster module. This crate has no Cargo dep on
// perry-runtime (dev-dep only); the symbol resolves at final link, the same
// way perry-ffi's runtime helpers do — matching perry-ext-http-server's
// way perry-ffi's runtime helpers do — matching perry-ext-http's
// `cluster_bind`.
fn perry_cluster_worker_listening(
addr_ptr: *const u8,
Expand Down
2 changes: 1 addition & 1 deletion crates/perry-ext-fastify/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ extern "C" {
/// `BufferHeader` registered with the runtime's BUFFER_REGISTRY.
/// Used to distinguish `Buffer` / `Uint8Array` payloads from
/// `StringHeader`-shaped objects when building response bodies.
/// Same C-exposed extern perry-ext-http-server uses (see
/// Same C-exposed extern perry-ext-http uses (see
/// `crates/perry-runtime/src/buffer.rs:601`).
fn js_buffer_is_buffer(ptr: i64) -> i32;
}
Expand Down
18 changes: 9 additions & 9 deletions crates/perry-ext-fastify/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ pub struct ErrorHeader {
/// user code never resumed and any subsequent code (an in-process
/// `fetch` against the same process, `app.close()`, etc.) never ran —
/// the compat-sweep fixture timed out at gtimeout(30s). The fix
/// mirrors what perry-ext-http-server did in #604: `listen()` returns
/// mirrors what perry-ext-http did in #604: `listen()` returns
/// immediately after spawning the accept loop, and a new
/// `js_fastify_process_pending` extern wired into perry-stdlib's main
/// pump drains the per-server mpsc each tick. The receiver lives
Expand Down Expand Up @@ -184,7 +184,7 @@ pub struct FastifyServerHandle {
/// `app.server.on("upgrade", …)` handlers. Sent by the hyper accept
/// task after `hyper::upgrade::on` resolves and the upgraded stream
/// has been registered with `perry_ext_ws::register_external_ws_stream`.
/// Mirror of perry-ext-http-server's `HttpPendingUpgrade`.
/// Mirror of perry-ext-http's `HttpPendingUpgrade`.
pub struct FastifyPendingUpgrade {
pub app_handle: Handle,
pub method: String,
Expand Down Expand Up @@ -257,7 +257,7 @@ pub unsafe extern "C" fn js_fastify_listen(app_handle: Handle, opts: f64, callba

let (request_tx, request_rx) = mpsc::channel::<FastifyPendingRequest>(1024);
// #1113 — separate channel for WebSocket upgrade events so a busy
// request stream can't starve them (mirror of perry-ext-http-server).
// request stream can't starve them (mirror of perry-ext-http).
let (upgrade_tx, upgrade_rx) = mpsc::channel::<FastifyPendingUpgrade>(256);
let (shutdown_tx, mut shutdown_rx) = oneshot::channel::<()>();
let request_tx = Arc::new(request_tx);
Expand Down Expand Up @@ -296,7 +296,7 @@ pub unsafe extern "C" fn js_fastify_listen(app_handle: Handle, opts: f64, callba
// hit). `spawn_blocking_with_reactor` runs the closure inside a worker
// task (`runtime().spawn(async { … })`), so `tokio::spawn`-ing the
// accept loop drives it and its fan-out serve tasks on the worker pool —
// mirroring perry-ext-http-server / -net / -ws. (A bare
// mirroring perry-ext-http / -net / -ws. (A bare
// `Handle::current().block_on` here would panic "Cannot start a runtime
// from within a runtime" inside the worker task; spawn instead.)
perry_ffi::spawn_blocking_with_reactor(move || {
Expand Down Expand Up @@ -585,7 +585,7 @@ pub extern "C" fn js_fastify_process_pending() -> i32 {
None => continue,
};
// #1113 — drain WebSocket upgrades FIRST so a busy request
// stream can't starve them (mirror of perry-ext-http-server's
// stream can't starve them (mirror of perry-ext-http's
// `js_node_http_server_process_pending`).
count += drain_server_upgrades(h);
while let Some(pending) = try_recv_pending_request(h) {
Expand Down Expand Up @@ -630,7 +630,7 @@ pub extern "C" fn js_fastify_process_pending() -> i32 {
}

/// #1113 — non-blocking try_recv for a pending WebSocket upgrade.
/// Mirror of perry-ext-http-server's `try_recv_upgrade`.
/// Mirror of perry-ext-http's `try_recv_upgrade`.
fn try_recv_fastify_upgrade(server_handle: Handle) -> Option<FastifyPendingUpgrade> {
if let Some(s) = get_handle::<FastifyServerHandle>(server_handle) {
let mut guard = s.upgrade_rx.lock().unwrap();
Expand All @@ -657,7 +657,7 @@ pub extern "C" fn js_fastify_has_active() -> i32 {
// Even after close(), the upgrade channel may still hold
// queued items the pump needs to drain on a later tick
// before the program can exit cleanly (mirror of
// perry-ext-http-server's `server_is_active`).
// perry-ext-http's `server_is_active`).
if let Ok(guard) = s.upgrade_rx.lock() {
if let Some(rx) = guard.as_ref() {
if !rx.is_closed() && !rx.is_empty() {
Expand Down Expand Up @@ -712,7 +712,7 @@ async fn handle_request(
// tungstenite server handshake, registers the WebSocketStream
// with perry-ext-ws, and queues a `FastifyPendingUpgrade` for the
// main-thread pump to fire the registered handlers. Mirror of
// perry-ext-http-server's #577 Phase 4 path.
// perry-ext-http's #577 Phase 4 path.
if crate::upgrade::is_websocket_upgrade(&req) {
return handle_fastify_websocket_upgrade(
app_handle, req, method, path, headers, upgrade_tx,
Expand Down Expand Up @@ -834,7 +834,7 @@ async fn handle_request(
}
}

/// #1113 — WebSocket upgrade dispatch (mirror of perry-ext-http-server's
/// #1113 — WebSocket upgrade dispatch (mirror of perry-ext-http's
/// `handle_websocket_upgrade`, issue #577 Phase 4).
///
/// Synchronously builds the 101 response (so hyper drives the protocol
Expand Down
4 changes: 2 additions & 2 deletions crates/perry-ext-fastify/src/upgrade.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! #1113 — `app.server.on("upgrade", (req, socket, head) => …)` for
//! HTTP Upgrade requests (WebSocket handshakes) on a fastify app.
//!
//! Mirrors perry-ext-http-server's `upgrade.rs` (issue #577 Phase 4),
//! Mirrors perry-ext-http's `upgrade.rs` (issue #577 Phase 4),
//! the proven template for bidirectional WebSocket upgrade dispatch.
//!
//! # Design
Expand Down Expand Up @@ -46,7 +46,7 @@ extern "C" {
/// `Connection: Upgrade` (case-insensitive contains) and
/// `Upgrade: websocket` (case-insensitive). Hyper's `headers()`
/// already lowercases names, so we only normalize values. Identical
/// to perry-ext-http-server's `is_websocket_upgrade`.
/// to perry-ext-http's `is_websocket_upgrade`.
pub(crate) fn is_websocket_upgrade(req: &hyper::Request<hyper::body::Incoming>) -> bool {
let h = req.headers();
let connection_ok = h
Expand Down
65 changes: 0 additions & 65 deletions crates/perry-ext-http-server/Cargo.toml

This file was deleted.

Loading
Loading