265 lines
4.8 KiB
Markdown
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)
|