Skip to content

feat(rpc): ease underlying HTTP server setup and fix Zod type resolution - #697

Open
yeziR4 wants to merge 1 commit into
autonomys:mainfrom
yeziR4:feat/rpc-ease-http-server
Open

yeziR4 wants to merge 1 commit into
autonomys:mainfrom
yeziR4:feat/rpc-ease-http-server

Conversation

@yeziR4

@yeziR4 yeziR4 commented Sep 16, 2026

Copy link
Copy Markdown

Resolves #356
Resolves #448

Summary

This PR addresses developer experience and typing issues in @autonomys/rpc:

  1. Ease Underlying HTTP Server ([@autonomys/rpc] Ease the underlying HTTP server #356):

    • Eliminates redundant internal server creation and unifies HTTP server management.
    • Makes httpServer, callbacks, and server configuration optional with sensible defaults.
    • Allows passing Express applications / RequestListener functions directly to httpServer.
    • Supports passing port directly in configuration options or calling server.listen(port).
    • Makes serverParams optional in apiDefinition.createServer.
    • Exposes httpServer: http.Server directly on WsServer and RpcServer.
  2. Zod Validator Type Resolution ([@autonomys/rpc] Type resolution fails when using zod validators #448):

    • Updates DefinitionTypeOutput to structurally extract output types from Zod schemas, resolving the Type instantiation is excessively deep and possibly infinite error on complex schemas.
  3. Test Suite:

    • Added comprehensive tests in __test__/rpc/httpServerDevEx.spec.ts covering Express app integration, port binding, default instantiation, and complex nested Zod schemas.

- Make underlying HTTP server, callbacks, and server configuration optional in createWsServer and createRpcServer
- Support Express applications / request listener functions directly in httpServer option
- Support automatic port binding via port option and expose httpServer on WsServer and RpcServer
- Make serverParams optional in apiDefinition.createServer
- Fix DefinitionTypeOutput to extract Zod output structurally, eliminating 'Type instantiation is excessively deep' errors on complex schemas
- Add comprehensive test suite covering all DevEx improvements and complex Zod schemas

Resolves autonomys#356, autonomys#448

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 541446c. Configure here.

httpServer.close()
httpServer.closeAllConnections?.()
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Close leaks server during listen race

Medium Severity

close only shuts down the HTTP server when httpServer.listening is already true. listen, including the new port option, starts an asynchronous bind, so listening is still false immediately afterward. Calling close in that window leaves the socket bound after startup completes.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 541446c. Configure here.

const listen = (port: number, cb?: () => void) => {
internalHttpServer.listen(port, cb)
if (typeof port === 'number') {
listen(port)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Listen mishandles overlapping bind attempts

Medium Severity

listen treats only httpServer.listening as already-started. After the port option kicks off an async bind, listening is still false, so a follow-up listen calls httpServer.listen again and throws. Once listening, a later listen with a different port still runs the success callback without rebinding.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 541446c. Configure here.

} else if (typeof rawHttpServer === 'function') {
httpServer = http.createServer(wrapRequestListener(rawHttpServer))
} else {
httpServer = http.createServer()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default server hangs non-RPC requests

Low Severity

When no httpServer is provided, the default http.createServer() has no fallback handler. Only POST /ws is answered later. Other HTTP requests never receive a response and hold the connection open until timeout.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 541446c. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[@autonomys/rpc] Type resolution fails when using zod validators [@autonomys/rpc] Ease the underlying HTTP server

1 participant