Skip to main content
The Node.js adapter integrates with the node:http and node:https modules that ship with Node.js.

Installation

import { RPCHandler } from '@orpc/server/node'

Basic usage

import { createServer } from 'node:http'
import { RPCHandler } from '@orpc/server/node'
import { CORSPlugin } from '@orpc/server/plugins'
import { router } from './router'

const handler = new RPCHandler(router, {
  plugins: [new CORSPlugin()],
})

const server = createServer(async (req, res) => {
  const result = await handler.handle(req, res, {
    context: { headers: req.headers },
  })

  if (!result.matched) {
    res.statusCode = 404
    res.end('No procedure matched')
  }
})

server.listen(3000, '127.0.0.1', () =>
  console.log('Listening on http://127.0.0.1:3000'),
)

handle(req, res, options)

ParameterTypeDescription
reqIncomingMessageThe incoming Node.js HTTP request
resServerResponseThe outgoing Node.js HTTP response
options.contextInitial context typeContext passed to middleware
options.prefixstring (optional)Strip this prefix before routing
Returns { matched: true } if a procedure was matched, or { matched: false } otherwise.
Unlike the fetch adapter, the Node.js adapter writes the response to res directly rather than returning a Response object.

With Express

import express from 'express'
import { RPCHandler } from '@orpc/server/node'
import { router } from './router'

const app = express()
const handler = new RPCHandler(router)

app.use('/orpc', async (req, res, next) => {
  const result = await handler.handle(req, res, {
    prefix: '/orpc',
    context: { headers: req.headers },
  })

  if (!result.matched) {
    next()
  }
})

app.listen(3000)

Options

plugins
NodeHttpHandlerPlugin[]
Array of plugins to apply. See Plugins.
strictGetMethodPluginEnabled
boolean
default:"true"
Restricts non-mutation procedures to GET requests.
adapterInterceptors
Interceptor[]
Low-level interceptors around the full request handling cycle.

Build docs developers (and LLMs) love