gRPC Node.js Server Reflection
This package provides an implementation of gRPC Server Reflection for Node.js applications, specifically designed to work with the `@grpc/grpc-js` library. It enables gRPC clients, such as `grpccurl` or `Postman`, to dynamically discover the services, methods, and message types exposed by a gRPC server at runtime, without needing pre-compiled `.proto` files on the client side. The current stable version is 1.0.2. As a utility library, its release cadence is primarily driven by updates to its core dependency, `@grpc/grpc-js`, or bug fixes, rather than a fixed schedule. Its key differentiator is its straightforward integration method, requiring only a single function call to wrap an existing `@grpc/grpc-js` server instance, thereby abstracting the complex details of implementing the `grpc.reflection.v1alpha.ServerReflection` service manually. Currently, it fully supports `ListServices` and `FileContainingSymbol` requests but explicitly notes that `FileByFilename` and `FileContainingExtension` requests are not yet implemented.
Common errors
-
grpcurl: rpc error: code = Unimplemented desc = Unknown method
cause The gRPC server reflection service itself has not been correctly added to the server, or the server is not running/accessible.fixVerify that `wrapServerWithReflection` has been successfully called on your `grpc.Server` instance. Also, confirm that your gRPC server is properly started and listening on the expected port. -
grpcurl: rpc error: code = Internal desc = Reflection service could not find symbol: [your_service_name]
cause Your application's gRPC services were added to the server instance *before* `wrapServerWithReflection` was called. The reflection wrapper needs to intercept `addService` calls to track them.fixReorder your server initialization. Call `wrapServerWithReflection(server)` first, then use the returned (wrapped) server object (`reflectedServer.addService(...)`) to register your application's services.
Warnings
- breaking Application services added to the gRPC server *before* calling `wrapServerWithReflection` will not be correctly registered or discoverable via the reflection service. The wrapper intercepts `addService` calls.
- gotcha The library explicitly states that `FileByFilename` and `FileContainingExtension` reflection request types are not supported. Attempting to use these specific reflection queries will result in an error or unexpected behavior.
Install
-
npm install grpc-node-server-reflection -
yarn add grpc-node-server-reflection -
pnpm add grpc-node-server-reflection
Imports
- wrapServerWithReflection
import { wrapServerWithReflection } from 'grpc-node-server-reflection';import wrapServerWithReflection from 'grpc-node-server-reflection';
Quickstart
import * as grpc from '@grpc/grpc-js';
import wrapServerWithReflection from 'grpc-node-server-reflection';
// A minimal example service for demonstration
const exampleServiceDefinition = {
ExampleService: {
sayHello: {
path: '/example.ExampleService/SayHello',
requestStream: false,
responseStream: false,
requestType: { deserializeBinary: () => ({ name: '' }) },
responseType: { serializeBinary: () => Buffer.from('') }
}
}
};
const exampleServiceImplementation = {
sayHello: (call, callback) => {
callback(null, { message: `Hello, ${call.request.name || 'Guest'}!` });
}
};
function main() {
const server = new grpc.Server();
// IMPORTANT: Wrap the server with reflection *before* adding any services.
const reflectedServer = wrapServerWithReflection(server);
reflectedServer.addService(exampleServiceDefinition.ExampleService, exampleServiceImplementation);
reflectedServer.bindAsync(
'0.0.0.0:50051',
grpc.ServerCredentials.createInsecure(),
(err, port) => {
if (err) {
console.error(`Server bind failed: ${err}`);
return;
}
reflectedServer.start();
console.log(`Server running at http://0.0.0.0:${port}`);
console.log('Try: grpcurl -plaintext localhost:50051 list');
console.log('Or: grpcurl -plaintext localhost:50051 describe example.ExampleService');
}
);
}
main();