拓冰建站拓冰建站
首页 / 资讯中心 / 正文

如何用 remix/node-fetch-server 的 createRequestListener 启动 Node HTTP 服务器

如何用 remix/node-fetch-server 的 createRequestListener 启动 Node HTTP 服务器【免费下载链接】remixThe fully-stacked web framework项目地址: https://gitcode.com/GitHub_Trending/re/remix这篇文章解决一个具体的部署任务把你的 fetch 风格请求处理函数接收 web 标准Request、返回Response挂到一个真正的 Node.js HTTP 服务器上。remix/node-fetch-server提供的createRequestListener()会把 Node 的 HTTP 服务器接口转换成Request/Response流程可以直接用于node:http、node:https和node:http2。完成本文后你会得到一个在本地监听 3000 端口、能处理 GET/POST 请求并返回 JSON 的服务器并了解生产部署时的域名、反向代理和 HTTPS 配置项。准备条件安装命令来自 node-fetch-server 的 READMEnpm i remix包名是remix子路径导出为remix/node-fetch-servermonorepo 内部包名为remix-run/node-fetch-server发布后通过remix包的子路径引用。下面的示例代码使用 TypeScript 语法含request: Request类型标注你可以用支持直接运行 TypeScript 的 Node 运行时执行该文件或先转译成 JavaScript 再用 Node 运行。代码本身只依赖 Node 内置的node:http、node:https、node:fs、node:http2模块没有额外运行时依赖。最短主路径用 createRequestListener 启动 HTTP 服务器完整的 README 示例如下它是可直接运行的完整服务器文件import * as http from node:http import { createRequestListener } from remix/node-fetch-server async function handler(request: Request) { let url new URL(request.url) if (url.pathname / request.method GET) { return new Response(Welcome to the User API! Try GET /api/users) } if (url.pathname /api/users request.method GET) { return Response.json([ { id: 1, name: Alice, email: aliceexample.com }, { id: 2, name: Bob, email: bobexample.com }, ]) } return new Response(Not Found, { status: 404 }) } let server http.createServer(createRequestListener(handler)) server.listen(3000, () { console.log(Server running at http://localhost:3000) })各部分的职责handler是一个FetchHandler接收 web 标准Request返回Response或PromiseResponse。createRequestListener()会根据 handler 声明的参数个数选择处理方式接收request参数时按请求处理声明两个参数时还会收到第二个参数client客户端地址信息。http.createServer(createRequestListener(handler))把 listener 交给node:httpserver.listen(3000, ...)绑定 3000 端口。启动回调里的console.log(Server running at http://localhost:3000)是文档示例代码的启动提示进程能打印这行说明端口监听成功。handler 内抛错时listener 默认会发送 500 响应响应体为Internal Server Error见 请求监听器实现也可以在选项里传入onError自定义错误响应。验证服务器服务器运行后用 Node 自带的 fetch 发请求核对。以下响应体是 README 示例代码中硬编码的返回内容文档示例如果你的 handler 逻辑与示例一致应得到相同结果node -e fetch(http://localhost:3000/).then(r r.text()).then(console.log) # 文档示例输出Welcome to the User API! Try GET /api/users node -e fetch(http://localhost:3000/api/users).then(r r.json()).then(console.log)访问示例 handler 中未定义的其余路径按示例逻辑会返回 404 和Not Found。读取请求体和搜索参数处理 POST JSON、URL 搜索参数的写法同样来自 READMEhandler 中使用request.json()与url.searchParamsasync function handler(request: Request) { let url new URL(request.url) // 处理 JSON 数据 if (request.method POST url.pathname /api/users) { try { let userData await request.json() if (!userData.name || !userData.email) { return Response.json({ error: Name and email are required }, { status: 400 }) } let newUser { id: Date.now().toString(), ...userData } return Response.json(newUser, { status: 201 }) } catch (error) { return Response.json({ error: Invalid JSON }, { status: 400 }) } } // 处理 URL 搜索参数 if (url.pathname /api/search) { let query url.searchParams.get(q) let limit parseInt(url.searchParams.get(limit) || 10) return Response.json({ query, limit, results: [] }) } return new Response(Not Found, { status: 404 }) }GET 和 HEAD 请求不携带 body 流其余方法的请求体会以ReadableStream形式挂到request上request.json()、request.text()等标准 API 均可使用。部署配置自定义域名与反向代理固定域名host 选项部署在自有域名或 VPS 时README 建议用host选项覆盖request.url的 host 部分默认从 HTTPHost请求头推导import * as http from node:http import { createRequestListener } from remix/node-fetch-server let hostname process.env.HOST || api.example.com async function handler(request: Request) { console.log(request.url) // 文档示例http://api.example.com/path return Response.json({ message: Hello from custom domain!, url: request.url, }) } let server http.createServer(createRequestListener(handler, { host: hostname })) server.listen(3000)api.example.com是文档示例值替换为你自己的域名。注意优先级规则当host或protocol显式设置时它们优先于反向代理头生效。反向代理头trustProxy 选项应用部署在受信任反向代理后面时Node 看到的是代理连接而非原始客户端。启用trustProxy后以下请求头会参与构造request.url和客户端信息Forwarded: proto与X-Forwarded-Proto提供原始协议Forwarded: host与X-Forwarded-Host提供原始 hostForwarded: for与X-Forwarded-For提供原始客户端地址。let server http.createServer( createRequestListener(handler, { trustProxy: true, }), ) server.listen(3000)这里有一条明确的安全限制来自 README只有当服务器只能通过会覆写这些请求头的受信任代理访问时才应启用该选项否则客户端可以伪造 host、协议和客户端地址。获取客户端地址用于日志与限流声明第二个参数client即可获得客户端连接信息IP 地址、端口启用trustProxy后取可信代理头中的值import { type FetchHandler } from remix/node-fetch-server let handler: FetchHandler async (request, client) { console.log(Request from ${client.address}:${client.port}) // 可用于限流、地理定位等 if (isRateLimited(client.address)) { return new Response(Too Many Requests, { status: 429 }) } return Response.json({ message: Hello!, yourIp: client.address }) }可选分支HTTPS 与 HTTP/2HTTPSREADME 给出的 HTTPS 写法是把 listener 传给node:https的createServerprivate-key.pem、certificate.pem是文档示例中的证书文件名替换为你自己的私钥与证书文件路径import * as https from node:https import * as fs from node:fs import { createRequestListener } from remix/node-fetch-server let options { key: fs.readFileSync(private-key.pem), cert: fs.readFileSync(certificate.pem), } let server https.createServer(options, createRequestListener(handler)) server.listen(443, () { console.log(HTTPS Server running on port 443) })走 HTTPS 时request.url的协议默认由连接协议推导即https:开头无需额外配置。HTTP/2仓库提供了一个可运行的 HTTP/2 示例demos/http2其 server.js 使用http2.createSecureServer()加载同目录下的自签名证书文件server.key、server.crt监听 44100 端口通过request事件挂接 listenerimport * as http2 from node:http2 import * as fs from node:fs import * as path from node:path import { fileURLToPath } from node:url import { createRequestListener } from remix-run/node-fetch-server const __dirname path.dirname(fileURLToPath(import.meta.url)) const PORT 44100 const options { key: fs.readFileSync(path.join(__dirname, server.key)), cert: fs.readFileSync(path.join(__dirname, server.crt)), } const server http2.createSecureServer(options) server.on( request, createRequestListener((request) { let url new URL(request.url) if (url.pathname /) { return new Response(Hello HTTP/2!, { headers: { Content-Type: text/plain }, }) } return new Response(Not Found, { status: 404 }) }), ) server.listen(PORT, () { console.log(Server running at https://localhost:${PORT}) })注意与http的差别http2的 listener 挂在request事件上而不是直接传给createServer第二个参数。启动成功时控制台打印Server running at https://localhost:44100文档示例输出访问/返回Hello HTTP/2!。示例依赖的包名为remix-run/node-fetch-server这是 monorepo 内的包名对外发布后对应remix/node-fetch-server。替代路径底层 API 与流式响应createRequest / sendResponse 手动组合需要自己控制中间件、加响应耗时头或自定义错误处理时README 给出的底层 API 是createRequest(req, res, options)把 Node 请求转成 webRequest和sendResponse(res, response)把 webResponse写回 Node 响应对象import * as http from node:http import { createRequest, sendResponse } from remix/node-fetch-server let server http.createServer(async (req, res) { let request createRequest(req, res, { host: process.env.HOST }) try { let startTime Date.now() let response await handler(request) // 确保 response 可变 response new Response(response.body, response) let duration Date.now() - startTime response.headers.set(X-Response-Time, ${duration}ms) await sendResponse(res, response) } catch (error) { console.error(Server error:, error) res.writeHead(500, { Content-Type: text/plain }) res.end(Internal Server Error) } }) server.listen(3000)process.env.HOST由你按部署环境设置。流式响应Response支持以ReadableStream作为 bodyREADME 示例每 1 秒推送一个 chunk共 5 个async function handler(request: Request) { if (request.url.endsWith(/stream)) { let stream new ReadableStream({ async start(controller) { for (let i 0; i 5; i) { controller.enqueue(new TextEncoder().encode(Chunk ${i}\n)) await new Promise((resolve) setTimeout(resolve, 1000)) } controller.close() }, }) return new Response(stream, { headers: { Content-Type: text/plain }, }) } return new Response(Not Found, { status: 404 }) }限制与注意事项trustProxy只在受信任代理会覆写Forwarded/X-Forwarded-*请求头时启用否则可被客户端伪造host/protocol显式配置时优先于代理头。handler 抛错时的默认错误响应是 500Internal Server Error自定义onError后由其返回值决定响应。README 附带的基准数据如 raw throughput 场景下remix/node-fetch-server约61,587req/s环境为 Apple M5 Pro、Node.js v24.18.0是作者在特定硬件上测得的文档示例数据仅可作量级参考不要当作你环境的预期性能。参考文档README、createRequestListener 实现、HTTP/2 示例。【免费下载链接】remixThe fully-stacked web framework项目地址: https://gitcode.com/GitHub_Trending/re/remix创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门