dotnet-cqrs/docs/grpc-integration/grpc-reflection.md

265 lines
4.8 KiB
Markdown

# 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
```bash
dotnet add package Grpc.AspNetCore.Server.Reflection
```
### Enable Reflection
```csharp
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:**
```bash
brew install grpcurl
```
**Windows:**
```powershell
choco install grpcurl
```
**Linux:**
```bash
# 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
```bash
grpcurl -plaintext localhost:5001 list
```
**Output:**
```
grpc.reflection.v1alpha.ServerReflection
myapp.CommandService
myapp.QueryService
```
### Describe Service
```bash
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
```bash
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
```bash
grpcurl -plaintext \
-d '{"name": "John Doe", "email": "john@example.com", "age": 25}' \
localhost:5001 \
myapp.CommandService/CreateUser
```
**Response:**
```json
{
"userId": 42
}
```
### With Metadata
```bash
grpcurl -plaintext \
-H "Authorization: Bearer eyJhbGc..." \
-H "X-Request-ID: abc-123" \
-d '{"userId": 42}' \
localhost:5001 \
myapp.QueryService/GetUser
```
## Using Postman
### Setup
1. Create new gRPC request
2. Enter server URL: `localhost:5001`
3. Click "Use Server Reflection"
4. Postman discovers all services
### Making Requests
1. Select service (e.g., `CommandService`)
2. Select method (e.g., `CreateUser`)
3. Fill in message fields
4. Click "Invoke"
5. View response
### Adding Headers
1. Click "Metadata" tab
2. Add key-value pairs:
- Key: `Authorization`
- Value: `Bearer token...`
3. Click "Invoke"
## Using BloomRPC
### Installation
Download from: https://github.com/bloomrpc/bloomrpc
### Setup
1. Launch BloomRPC
2. Click "+" to add server
3. Enter address: `localhost:5001`
4. Enable "Use Server Reflection"
5. Services appear in left panel
### Making Requests
1. Select method from tree
2. Edit JSON request
3. Click play button
4. View response
## Production Considerations
### Disable in Production
```csharp
if (app.Environment.IsDevelopment())
{
app.MapGrpcReflectionService();
}
```
### Conditional Registration
```csharp
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
```csharp
app.MapGrpcReflectionService().RequireAuthorization("AdminOnly");
```
## Alternatives to Reflection
### Static .proto Files
Distribute .proto files to clients:
```bash
# 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:
```xml
<ItemGroup>
<Protobuf Include="Protos\cqrs_services.proto" GrpcServices="Client" />
</ItemGroup>
```
```bash
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
## See Also
- [gRPC Integration Overview](README.md)
- [Getting Started](getting-started-grpc.md)
- [gRPC Clients](grpc-clients.md)
- [grpcurl Documentation](https://github.com/fullstorydev/grpcurl)