gRPC with ignis-grpc ~15 min
ignis-grpc is a Connect RPC gateway built into Shell API. It receives gRPC-style calls over plain HTTP — no HTTP/2 or native gRPC client required.
How it works
Remote Service → POST /{package}.{Service}/{Method} → Shell API (ignis-grpc) → HandlerShell API validates the Shell JWT before the handler receives the request.
1. Define a proto
protobuf
// protos/auth/v1/auth.proto
syntax = "proto3";
package auth.v1;
service AuthGateway {
rpc ExchangeToken(ExchangeTokenRequest) returns (ExchangeTokenResponse);
}
message ExchangeTokenRequest {
string token = 1;
}
message ExchangeTokenResponse {
string access_token = 1;
string token_type = 2;
int32 expires_in = 3;
}2. Implement a handler
typescript
// shell/api/src/grpc/auth-gateway.handler.ts
import { BaseGrpcHandler, GrpcMethod } from '@/lib/ignis-grpc';
import { inject } from '@venizia/ignis';
import { AuthGatewayService } from '@/services';
export class AuthGatewayGrpcHandler extends BaseGrpcHandler {
constructor(
@inject({ key: 'services.AuthGatewayService' })
private authGateway: AuthGatewayService,
) {
super({ package: 'auth.v1', service: 'AuthGateway' });
}
@GrpcMethod('ExchangeToken')
async exchangeToken(request: { token: string }) {
return this.authGateway.exchangeToken(request.token);
}
}3. Register in application.ts
typescript
// shell/api/src/application.ts (bindServices)
this.service(AuthGatewayGrpcHandler);
// (initialize)
const handler = this.get<AuthGatewayGrpcHandler>({
key: 'services.AuthGatewayGrpcHandler',
});
this.grpcComponent.registerHandler(handler);
this.grpcComponent.mount(app, env.APP_ENV_SERVER_BASE_PATH ?? '/api');The handler is now reachable at /api/auth.v1.AuthGateway/ExchangeToken.
4. Call from a remote service
No gRPC client library needed — use plain fetch:
typescript
const response = await fetch(
`${SHELL_API_URL}/api/auth.v1.AuthGateway/ExchangeToken`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${shellJwt}`,
},
body: JSON.stringify({ token: keycloakToken }),
}
);
const result = await response.json();
// result.access_token = service JWT5. Configure service URL
Add the service URL to Shell API env:
env
APP_ENV_HRM_GRPC_URL=http://hrm-api:3000/apiOr add it to the JSON map for custom services:
env
APP_ENV_GRPC_URLS={"myapp":"http://myapp-api:3000/api"}URL must include the base path
The URL must include the service's route prefix (e.g. /api). ignis-grpc appends /{package}.{Service}/{Method} to this base URL.