gRPC Server Reflection for Node.js

0.1.5 · active · verified Tue Apr 21

grpc-server-reflection is a Node.js library that implements the gRPC server reflection protocol, allowing gRPC clients to discover services and methods exposed by a server at runtime without prior knowledge of its `.proto` definitions. Currently at version 0.1.5, it provides robust reflection capabilities by leveraging pre-generated binary descriptor sets (via `grpc_tools_node_protoc`) rather than relying on dynamic schema parsing or problematic `protobuf-js` binary formats. It is designed to be framework-agnostic and offers full support for both the modern `@grpc/grpc-js` library and the older `grpc` package. Key differentiators include its comprehensive service detection, full feature set compared to alternatives, and its ability to handle complex `proto` definitions via a static descriptor file. While the release cadence is not explicitly defined, given its pre-1.0 version, users can expect incremental updates for bug fixes and stability improvements.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to initialize a gRPC server with a placeholder service and then integrate `grpc-server-reflection` using a pre-generated descriptor set, enabling clients to introspect the server's capabilities.

import * as grpc from '@grpc/grpc-js';
import { addReflection } from 'grpc-server-reflection';
import * as path from 'path';
import * as fs from 'fs';

// --- Placeholder for your proto definition ---
// syntax = "proto3";
// package myapp;
// service Greeter {
//   rpc SayHello (HelloRequest) returns (HelloReply) {}
// }
// message HelloRequest { string name = 1; }
// message HelloReply { string message = 1; }
// ------------------------------------------

// Dummy service implementation
const greeterService = {
  SayHello: (call: grpc.ServerUnaryCall<any, any>, callback: grpc.sendUnaryData<any>) => {
    const name = call.request.name || 'World';
    callback(null, { message: `Hello, ${name}!` });
  },
};

// Resolve paths for descriptor set
const DESCRIPTOR_SET_PATH = path.resolve(__dirname, 'descriptor_set.bin');

// In a real application, you must generate descriptor_set.bin using grpc_tools_node_protoc:
// grpc_tools_node_protoc --descriptor_set_out=${DESCRIPTOR_SET_PATH} --include_imports your_protos/**/*.proto
if (!fs.existsSync(DESCRIPTOR_SET_PATH)) {
  console.warn(`
  WARNING: Descriptor set file not found at ${DESCRIPTOR_SET_PATH}.
  Reflection will not function without it. Please generate it.
  Example command:
  grpc_tools_node_protoc --descriptor_set_out=${DESCRIPTOR_SET_PATH} --include_imports --proto_path=./path/to/protos ./path/to/protos/*.proto
  `);
  // For quickstart to be runnable without actual proto generation, create a dummy file.
  // In production, this file *must* be correctly generated.
  fs.writeFileSync(DESCRIPTOR_SET_PATH, Buffer.from('DUMMY_DESCRIPTOR_SET'));
}

const server = new grpc.Server();

// Register your actual gRPC services
server.addService({
  // This is a minimal representation; real services use generated types.
  SayHello: {
    path: '/myapp.Greeter/SayHello',
    requestStream: false,
    responseStream: false,
    requestSerialize: (value: any) => Buffer.from(JSON.stringify(value)),
    requestDeserialize: (buffer: Buffer) => JSON.parse(buffer.toString()),
    responseSerialize: (value: any) => Buffer.from(JSON.stringify(value)),
    responseDeserialize: (buffer: Buffer) => JSON.parse(buffer.toString()),
  },
}, greeterService);

// Add gRPC server reflection to the server instance
addReflection(server, DESCRIPTOR_SET_PATH);

const port = '0.0.0.0:50051';
server.bindAsync(port, grpc.ServerCredentials.createInsecure(), (err, boundPort) => {
  if (err) {
    console.error(`Server bind failed on ${port}: ${err.message}`);
  } else {
    server.start();
    console.log(`gRPC server listening on ${boundPort} with reflection enabled.`);
  }
});

view raw JSON →