For the complete documentation index, see llms.txt. This page is also available as Markdown.

Protoreg

The protoreg plugin provides a shared protobuf registry. It reads .proto definitions for gRPC server reflection, custom interceptors, and dynamic message handling. The RoadRunner v3 bundle includes this plugin.

Features

  • Parses and registers .proto files at startup

  • Provides a shared protoregistry accessible by other plugins

  • Supports multiple import paths for proto dependencies

  • Automatically resolves and registers proto file dependencies

  • Exposes service and method descriptors for reflection-based operations

  • Thread-safe registry access

Use Cases

  • Custom gRPC Interceptors: Build interceptors that need to inspect or modify messages based on their proto definitions

  • Dynamic Message Handling: Deserialize and serialize protobuf messages without compile-time generated code

  • Request/Response Validation: Validate gRPC requests against proto schemas

  • Logging & Monitoring: Create detailed logs with field-level message inspection

Configuration

Both grpc and protoreg configuration sections are required to start the plugin. Keep the service definitions in both sections consistent.

The plugin is configured under the protoreg section in your .rr.yaml configuration file:

Set server.command to your gRPC worker as shown in the gRPC configuration.

Configuration Options

proto_path (required)

A list of directories where the plugin will search for proto files and their dependencies. These paths work similarly to the --proto-path/-I flag in protoc.

Why it's needed: Proto files often import other proto files (e.g., import "google/protobuf/timestamp.proto"). The import paths tell the parser where to find these dependencies. You typically need:

  • A path containing your service definitions

  • A path containing shared/common message definitions

  • Paths to any third-party proto files (like Google's well-known types)

files (required)

A list of proto files to parse and register. Paths are relative to the proto_path directories. Use explicit file names. This list does not expand the glob patterns supported by grpc.proto.

Both proto_path and files must contain at least one entry. Blank entries fail initialization. Each file must exist under at least one configured import path.

Why it's needed: This explicitly declares which proto files define the services and messages you want to access at runtime. The plugin will:

  1. Parse each listed proto file

  2. Automatically resolve and register all imported dependencies

  3. Build a registry of all services and their methods

Server reflection

RR automatically uses the protoreg registry for server reflection. Configure the same service files in grpc.proto and protoreg.files. Paths in protoreg.files are relative to proto_path; they do not replace grpc.proto.

For the Hello World service, use:

Reflection clients can retrieve file and message descriptors for the PHP service. For the preceding listener without TLS, use grpcurl without a local .proto file:

Reflection streams do not call unary authentication interceptors. See reflection access controls.

Example: Project Structure

A typical project structure when using this plugin:

proto/commonapis/common/v1/message.proto:

proto/serviceapis/service/v1/service.proto:

Configuration (.rr.yaml):

Using the Registry in Your Plugin

Declare protoreg.Registry as an initialization dependency:

Registry Interface

The interface uses protoresolve.Registry from github.com/jhump/protoreflect/v2/protoresolve and descriptors from github.com/jhump/protoreflect/desc:

Example: gRPC Interceptor

This unary interceptor logs method descriptors without logging request bodies. Include it with grpc and protoreg in your custom build. Set grpc.interceptors: ["descriptor-logger"] to activate it.

Troubleshooting

"proto path does not exist"

Ensure all paths in proto_path exist and are accessible. Paths can be absolute or relative to the RoadRunner working directory.

"proto file does not exist"

The proto file must exist in one of the configured proto_path. Check that:

  1. The file path in files is relative to an import path, not an absolute path

  2. The directory structure matches the import path

"file already registered"

This occurs when the same proto file is included multiple times (e.g., listed in files and also imported by another file). The plugin handles dependencies automatically, so you typically only need to list your top-level service definitions in the files section.

License

MIT License - see LICENSE file for details.

Last updated

Was this helpful?