4.8 KiB
4.8 KiB
gRPC Reflection
Enable gRPC reflection for development tools and service discovery.
Overview
gRPC reflection allows clients to discover available services and their methods at runtime without needing .proto files. This enables:
- ✅ grpcurl - Command-line testing
- ✅ Postman - GUI testing
- ✅ BloomRPC - Desktop gRPC client
- ✅ Service discovery - Dynamic client generation
- ✅ Development - Faster iteration
Setup
Install Package
dotnet add package Grpc.AspNetCore.Server.Reflection
Enable Reflection
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
builder.Services.AddGrpcReflection(); // Add reflection
var app = builder.Build();
app.MapGrpcService<CommandServiceImpl>();
app.MapGrpcService<QueryServiceImpl>();
app.MapGrpcReflectionService(); // Map reflection service
app.Run();
Using grpcurl
Installation
macOS:
brew install grpcurl
Windows:
choco install grpcurl
Linux:
# Download from GitHub releases
wget https://github.com/fullstorydev/grpcurl/releases/download/v1.8.9/grpcurl_1.8.9_linux_x86_64.tar.gz
tar -xvf grpcurl_1.8.9_linux_x86_64.tar.gz
sudo mv grpcurl /usr/local/bin/
List Services
grpcurl -plaintext localhost:5001 list
Output:
grpc.reflection.v1alpha.ServerReflection
myapp.CommandService
myapp.QueryService
Describe Service
grpcurl -plaintext localhost:5001 describe myapp.CommandService
Output:
myapp.CommandService is a service:
service CommandService {
rpc CreateUser ( .myapp.CreateUserCommand ) returns ( .myapp.CreateUserResponse );
rpc DeleteUser ( .myapp.DeleteUserCommand ) returns ( .google.protobuf.Empty );
}
Describe Message
grpcurl -plaintext localhost:5001 describe myapp.CreateUserCommand
Output:
myapp.CreateUserCommand is a message:
message CreateUserCommand {
string name = 1;
string email = 2;
int32 age = 3;
}
Call Method
grpcurl -plaintext \
-d '{"name": "John Doe", "email": "john@example.com", "age": 25}' \
localhost:5001 \
myapp.CommandService/CreateUser
Response:
{
"userId": 42
}
With Metadata
grpcurl -plaintext \
-H "Authorization: Bearer eyJhbGc..." \
-H "X-Request-ID: abc-123" \
-d '{"userId": 42}' \
localhost:5001 \
myapp.QueryService/GetUser
Using Postman
Setup
- Create new gRPC request
- Enter server URL:
localhost:5001 - Click "Use Server Reflection"
- Postman discovers all services
Making Requests
- Select service (e.g.,
CommandService) - Select method (e.g.,
CreateUser) - Fill in message fields
- Click "Invoke"
- View response
Adding Headers
- Click "Metadata" tab
- Add key-value pairs:
- Key:
Authorization - Value:
Bearer token...
- Key:
- Click "Invoke"
Using BloomRPC
Installation
Download from: https://github.com/bloomrpc/bloomrpc
Setup
- Launch BloomRPC
- Click "+" to add server
- Enter address:
localhost:5001 - Enable "Use Server Reflection"
- Services appear in left panel
Making Requests
- Select method from tree
- Edit JSON request
- Click play button
- View response
Production Considerations
Disable in Production
if (app.Environment.IsDevelopment())
{
app.MapGrpcReflectionService();
}
Conditional Registration
builder.Services.AddGrpc();
if (builder.Configuration.GetValue<bool>("EnableGrpcReflection"))
{
builder.Services.AddGrpcReflection();
}
var app = builder.Build();
if (app.Configuration.GetValue<bool>("EnableGrpcReflection"))
{
app.MapGrpcReflectionService();
}
With Authentication
app.MapGrpcReflectionService().RequireAuthorization("AdminOnly");
Alternatives to Reflection
Static .proto Files
Distribute .proto files to clients:
# Client downloads .proto files
curl https://api.example.com/protos/cqrs_services.proto > cqrs_services.proto
# Generate client code
protoc --csharp_out=. --grpc_out=. cqrs_services.proto
Client Libraries
Publish NuGet package with generated client code:
<ItemGroup>
<Protobuf Include="Protos\cqrs_services.proto" GrpcServices="Client" />
</ItemGroup>
dotnet pack -c Release
dotnet nuget push MyApi.Client.1.0.0.nupkg
Best Practices
✅ DO
- Use reflection in development
- Disable reflection in production (or secure it)
- Use grpcurl for quick testing
- Document gRPC endpoints
- Version your services
❌ DON'T
- Don't expose reflection publicly without auth
- Don't rely on reflection for production clients
- Don't skip .proto file documentation