Scope
`perry-ext-http-server` is a real crate (crates/perry-ext-http-server/{lib,server,response,request,http2_server,https_server,tls,upgrade,types}.rs) with the FFI surface for node:http.createServer. But when a user program does import { createServer } from 'node:http' and Perry compiles with --features full (the default), the linker drops the symbols. The result is a hard link failure, not a runtime gap.
The docs page `docs/src/stdlib/http.md` still ships this paragraph:
"The canonical 'deploy a hono app as a native binary on a Linux VM' pattern — serve({ fetch: app.fetch, port: 3000 }) via @hono/node-server, or a hand-rolled node:http adapter that drives app.fetch — currently fails to link because the Web Fetch FFIs (Headers / Response constructors) aren't pulled in alongside perry-ext-http-server. Tracked at issue #589."
#589 is closed but the link error reproduces today on both my local Perry 0.5.1026 and the worker's source-built 0.5.1025 (/opt/perry-src/target/release/perry, perry-src HEAD f46c4c3). So either the fix from #589 didn't cover this case, or it regressed.
Why
node:http working is the difference between writing a 50-line adapter (Perry-owned hyper does HTTP parsing) and either (a) hand-rolling 400 LOC of HTTP/1.1 framing on node:net, or (b) committing to Fastify as the only HTTP path in perpetuity. #577 chose path (a) for the architecture; closing this gap is what makes that real.
Repro (Perry 0.5.1026, perry-src commit f46c4c3; worker /opt/perry-src/target/release/perry 0.5.1025 reproduces identically)
```typescript
// nh-smoke.ts
import { createServer } from "node:http";
createServer((_req, res) => res.end("ok")).listen(0);
```
```bash
perry compile nh-smoke.ts -o nh-smoke
```
Observed:
```
Undefined symbols for architecture arm64:
"_js_node_http_create_server", referenced from: _main
"_js_node_http_server_listen", referenced from: _main
"_js_node_http_res_end", referenced from: _perry_closure_nh_smoke_ts__3
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1
Error: Linking failed
```
(Linux worker yields equivalent undefined reference to \js_node_http_create_server`` etc. through GNU ld.)
Acceptance
- The snippet above compiles and links cleanly with
perry compile on a stock Perry binary (no extra flags).
./nh-smoke &; curl -fsS http://127.0.0.1:<port>/anything returns ok with HTTP 200.
- Add a CI smoke that compiles + runs that 2-line program once per Perry release so this can't silently regress again. Possibly extend to a 6-line variant that wires
app.fetch from a new Hono(); app.get('/', c => c.text('ok')) through and reads the body — i.e. the docs example from stdlib/http.md becomes the test fixture.
- When the fix lands, remove the "currently fails to link" paragraph from
docs/src/stdlib/http.md.
Hypothesis on where the fix lives
The http-server cargo feature in crates/perry-stdlib/Cargo.toml transitively pulls bundled-fastify (per a comment in the file: "http-server umbrella retained for backwards-compat — it now transitively pulls bundled-fastify"), but the perry-ext-http-server symbols aren't being marked as #[used] / aren't on a path that survives LTO dead-code elimination. Sibling commits like b47459ed perry-stdlib+ext-net: refs #421/#420 — issue #91 HANDLE_METHOD_DISPATCH for perry-ext-net and 31e51bf4 perry-stdlib+ext-net: refs #421/#420 — net pump registration + LTO black-box ran into the same pattern with perry-ext-net and resolved it via LTO black-box + pump registration. Likely the same shape applies here.
Related
Scope
`perry-ext-http-server` is a real crate (
crates/perry-ext-http-server/{lib,server,response,request,http2_server,https_server,tls,upgrade,types}.rs) with the FFI surface fornode:http.createServer. But when a user program doesimport { createServer } from 'node:http'and Perry compiles with--features full(the default), the linker drops the symbols. The result is a hard link failure, not a runtime gap.The docs page `docs/src/stdlib/http.md` still ships this paragraph:
#589 is closed but the link error reproduces today on both my local Perry 0.5.1026 and the worker's source-built 0.5.1025 (
/opt/perry-src/target/release/perry, perry-src HEAD f46c4c3). So either the fix from #589 didn't cover this case, or it regressed.Why
node:httpworking is the difference between writing a 50-line adapter (Perry-owned hyper does HTTP parsing) and either (a) hand-rolling 400 LOC of HTTP/1.1 framing onnode:net, or (b) committing to Fastify as the only HTTP path in perpetuity. #577 chose path (a) for the architecture; closing this gap is what makes that real.Repro (Perry 0.5.1026, perry-src commit f46c4c3; worker /opt/perry-src/target/release/perry 0.5.1025 reproduces identically)
```typescript
// nh-smoke.ts
import { createServer } from "node:http";
createServer((_req, res) => res.end("ok")).listen(0);
```
```bash
perry compile nh-smoke.ts -o nh-smoke
```
Observed:
```
Undefined symbols for architecture arm64:
"_js_node_http_create_server", referenced from: _main
"_js_node_http_server_listen", referenced from: _main
"_js_node_http_res_end", referenced from: _perry_closure_nh_smoke_ts__3
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1
Error: Linking failed
```
(Linux worker yields equivalent
undefined reference to \js_node_http_create_server`` etc. through GNU ld.)Acceptance
perry compileon a stock Perry binary (no extra flags)../nh-smoke &; curl -fsS http://127.0.0.1:<port>/anythingreturnsokwith HTTP 200.app.fetchfrom anew Hono(); app.get('/', c => c.text('ok'))through and reads the body — i.e. the docs example fromstdlib/http.mdbecomes the test fixture.docs/src/stdlib/http.md.Hypothesis on where the fix lives
The
http-servercargo feature incrates/perry-stdlib/Cargo.tomltransitively pullsbundled-fastify(per a comment in the file: "http-serverumbrella retained for backwards-compat — it now transitively pullsbundled-fastify"), but theperry-ext-http-serversymbols aren't being marked as#[used]/ aren't on a path that survives LTO dead-code elimination. Sibling commits likeb47459ed perry-stdlib+ext-net: refs #421/#420 — issue #91 HANDLE_METHOD_DISPATCH for perry-ext-netand31e51bf4 perry-stdlib+ext-net: refs #421/#420 — net pump registration + LTO black-boxran into the same pattern withperry-ext-netand resolved it via LTO black-box + pump registration. Likely the same shape applies here.Related
node:httpend-to-end shipped.node:http2missing named exports (separate issue, same area).