An xOneRS node can serve HTTP and WebSocket JSON-RPC on the same port. Set --ws.addr and --ws.port to the same values as --http.addr and --http.port, and the node binds one listener: plain HTTP requests go to the HTTP side, and WebSocket upgrades go to the WebSocket side. Each side keeps its own namespace list, origin and host policy, authentication and connection budget. This came with PR #1080 on 2026-11-15 (issue #500), so it is on main and not in v0.1.0.
One port means one firewall rule, one reverse-proxy upstream and one health target for both protocols. See exposing RPC safely for the rules that still apply.
How do I turn it on?
xone --network apothem \
--http --http.addr 127.0.0.1 --http.port 8545 --http.api eth,net,web3 \
--ws --ws.addr 127.0.0.1 --ws.port 8545 --ws.api eth
The start log then shows one line, rpc: http+ws listening on 127.0.0.1:8545, instead of two. The node shares the listener only when both listeners are on and the address and port are equal. Port 0 (a random port) never shares. The defaults are different ports, 8545 for HTTP and 8546 for WebSocket, so nothing changes unless you set them equal.
What stays separate on a shared port?
| Setting | HTTP side | WebSocket side |
|---|---|---|
| Namespaces | --http.api |
--ws.api |
| Browser origins and hosts | --http.corsdomain, --http.vhosts |
--ws.origins |
| Connection budget | HTTP connections and in-flight requests | WebSocket connections |
The test http_and_ws_share_one_port_with_separate_policy_and_budgets checks this on one listener (crates/xone-rpc/tests/rpc.rs):
- HTTP serves
ethandnet; WebSocket servesethonly, sonet_versionover WebSocket answers-32601. - With a WebSocket budget of one connection, a second upgrade is refused while the first is open, and HTTP still answers.
PR #1080 states that a WebSocket upgrade over the budget gets HTTP 429, and HTTP keeps working.
What about TLS?
A shared listener has one TLS setting. The node uses the HTTP side's TLS configuration if there is one, else the WebSocket side's (services/rpc.rs). Native TLS for RPC came with PR #1078. If you need different certificates per protocol, use two ports.
Can I stop one protocol at run time?
Not cleanly, today. We read the code after PR #1080 and found that on a shared listener:
admin_stopWSanswerstrue, but the shared server keeps accepting WebSocket upgrades.admin_stopHTTPstops the shared server, so WebSocket stops too.
We filed this as issue #1143. We found it by reading the code and did not reproduce it on a running node. Until it is fixed, restart the node with separate ports if you must turn one protocol off at run time.
How does a reverse proxy see a shared port?
As one upstream. nginx, for example, needs the usual Upgrade and Connection headers for WebSocket on that location, and plain proxying for HTTP; both go to the same 127.0.0.1:8545. The node tells the two apart by the upgrade request. The xOneRS repository has an nginx recipe for a follower RPC (PR #846).
Frequently asked questions
How do I serve HTTP and WebSocket RPC on the same port with xOne?
Set --ws.addr and --ws.port equal to --http.addr and --http.port, with both --http and --ws on. Use a build from main after PR #1080.
Can HTTP and WebSocket have different namespaces on one port?
Yes. --http.api and --ws.api stay separate, as do the origin rules and the connection budgets.
What happens when the WebSocket connection limit is reached on a shared port?
New WebSocket upgrades are refused, and HTTP requests keep working.
Does admin_stopWS work on a shared port?
Not as its name says: the code keeps serving WebSocket. Issue #1143 tracks the fix.
Sources
This article describes the source and evidence at its review date. Check the linked repository for current implementation and qualification status.
Explore the engineering evidenceEdit this page on GitHub opens the Markdown source (content/blog/xone-http-ws-one-port/index.md). GitHub may ask you to sign in. Report a correction opens a prefilled GitHub issue for this page.