Skip to main content

gRPC (vania_grpc)

The vania_grpc package runs a gRPC server alongside your Vania HTTP server. It supports service registration, interceptors, health checking, and TLS.

Installation

dependencies:
vania_grpc: ^1.0.0
grpc: ^4.0.0
protobuf: ^3.0.0

Setup

1. Define Your Protobuf Services

Create .proto files and generate Dart code with protoc:

// protos/greeter.proto
syntax = "proto3";
package greeter;

service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
string name = 1;
}

message HelloReply {
string message = 1;
}

Generate:

protoc --dart_out=grpc:lib/src/generated protos/greeter.proto

2. Implement the Service

import 'package:grpc/grpc.dart';
import 'package:my_app/src/generated/greeter.pbgrpc.dart';

class GreeterService extends GreeterServiceBase {
@override
Future<HelloReply> sayHello(ServiceCall call, HelloRequest request) async {
return HelloReply()..message = 'Hello, ${request.name}!';
}
}

3. Register the Provider

import 'package:vania_grpc/vania_grpc.dart';

'providers': [
RouteServiceProvider(),
GrpcServiceProvider(services: [GreeterService()]),
],

Or register and start manually:

VaniaGrpcServer().register(GreeterService());
await VaniaGrpcServer().serve();

Configuration

GrpcServiceProvider(
services: [GreeterService(), UserService()],
config: GrpcConfig(
host: '0.0.0.0',
port: 50051,
autoStart: true,
healthEnabled: true,
),
);

Via .env:

GRPC_HOST=0.0.0.0
GRPC_PORT=50051
GRPC_ENABLED=true
GRPC_AUTO_START=true

Interceptors

Logging Interceptor

Logs every gRPC call with method name and duration:

VaniaGrpcServer().addServerInterceptor(GrpcLoggingInterceptor());

Exception Interceptor

Catches non-gRPC exceptions and wraps them in GrpcError.internal:

VaniaGrpcServer().addServerInterceptor(GrpcExceptionInterceptor());

Metadata (Auth) Interceptor

Validates client-provided metadata (e.g., API keys or tokens):

VaniaGrpcServer().addInterceptor(GrpcMetadataInterceptor());

Custom Interceptor

class RateLimitInterceptor implements ServerInterceptor {
@override
Future<GrpcError?> call(ServiceCall call, ServiceMethod method) async {
// Your logic here
return null; // return null to allow, or GrpcError to reject
}
}

VaniaGrpcServer().addServerInterceptor(RateLimitInterceptor());

Health Checking

When healthEnabled is true, the server exposes the standard gRPC Health Checking Protocol:

// Set service health status
VaniaGrpcServer().setHealthStatus('greeter.Greeter', ServingStatus.serving);

Clients can check health with the standard grpc.health.v1.Health/Check RPC.

TLS

GrpcConfig(
secure: true,
certificatePath: 'certs/server.crt',
privateKeyPath: 'certs/server.key',
);

Client Factory

Create client channels to call other gRPC services:

import 'package:vania_grpc/vania_grpc.dart';

// Insecure channel
var channel = GrpcClientFactory.insecure('localhost', port: 50051);

// With config
var channel = GrpcClientFactory.channel(GrpcClientConfig(
host: 'api.example.com',
port: 443,
secure: true,
));

// Use with generated client
var client = GreeterClient(channel);
var response = await client.sayHello(HelloRequest()..name = 'Alice');
print(response.message);

Server Lifecycle

// Check if running
bool running = VaniaGrpcServer().isRunning;

// Get port
int port = VaniaGrpcServer().port;

// Graceful shutdown
await VaniaGrpcServer().shutdown();