ConnectRPC Protocol
ConnectRPC is the primary RPC framework used across all PiVirt inter-service communications, uniting the performance of gRPC with browser-friendly JSON/HTTP protocols.
What is ConnectRPC?
Section titled “What is ConnectRPC?”ConnectRPC provides:
- HTTP/1.1 and HTTP/2 support
- JSON and Protobuf encoding
- Browser compatibility (no gRPC-Web proxy needed)
- Streaming support
- Idiomatic Go, TypeScript, and Python clients
Protocol Comparison
Section titled “Protocol Comparison”| Feature | gRPC | ConnectRPC | REST |
|---|---|---|---|
| Transport | HTTP/2 | HTTP/1.1, HTTP/2 | HTTP/1.1, HTTP/2 |
| Encoding | Protobuf | Protobuf, JSON | JSON |
| Browser Support | Requires proxy | Native | Native |
| Streaming | Yes | Yes | Limited |
| Code Generation | Required | Optional | Optional |
ConnectRPC in PiVirt
Section titled “ConnectRPC in PiVirt”Service Definition
Section titled “Service Definition”syntax = "proto3";
package pivirt.vm.v1;
import "google/protobuf/timestamp.proto";
option go_package = "go.pilab.hu/cloud/virtpb/pilab/pivirtd/v1;pivirtdv1";
service VMService { // Create a new VM rpc CreateVM(CreateVMRequest) returns (VM);
// Get VM by ID rpc GetVM(GetVMRequest) returns (VM);
// List VMs with filters rpc ListVMs(ListVMsRequest) returns (stream VM);
// Update VM spec rpc UpdateVM(UpdateVMRequest) returns (VM);
// Delete VM rpc DeleteVM(DeleteVMRequest) returns (google.protobuf.Empty);}Client Usage
Section titled “Client Usage”import ( "context" "go.pilab.hu/cloud/virtpb/pilab/pivirtd/v1" "connectrpc.com/connect")
func main() { client := vmv1connect.NewVMServiceClient( http.DefaultClient, "https://agent.pilab.hu:8443", )
resp, err := client.GetVM( context.Background(), connect.NewRequest(&vmv1.GetVMRequest{ Id: "vm-abc123", }), ) if err != nil { log.Fatal(err) }
fmt.Printf("VM: %s\n", resp.Msg.Name)}TypeScript
Section titled “TypeScript”import { VMServiceClient } from '@pilab/pivirt';
const client = new VMServiceClient('https://agent.pilab.hu:8443');
const response = await client.getVM({ id: 'vm-abc123',});
console.log(`VM: ${response.name}`);Python
Section titled “Python”from pivirt.vm.v1 import VMServiceClient
client = VMServiceClient('https://agent.pilab.hu:8443')
response = client.get_vm(id='vm-abc123')print(f"VM: {response.name}")Protocol Details
Section titled “Protocol Details”Request Format
Section titled “Request Format”POST /pivirt.vm.v1.VMService/GetVM HTTP/1.1Host: agent.pilab.hu:8443Content-Type: application/jsonConnect-Protocol-Version: 1
{ "id": "vm-abc123"}Response Format
Section titled “Response Format”HTTP/1.1 200 OKContent-Type: application/jsonConnect-Content-Encoding: identity
{ "id": "vm-abc123", "name": "web-01", "status": "VM_STATUS_RUNNING", "spec": { "vcpus": 2, "memory_bytes": 4294967296 }}Streaming
Section titled “Streaming”POST /pivirt.vm.v1.VMService/ListVMs HTTP/1.1Host: agent.pilab.hu:8443Content-Type: application/jsonConnect-Protocol-Version: 1
{ "namespace": "production"}Response (server-streaming):
HTTP/1.1 200 OKContent-Type: application/jsonConnect-Protocol-Version: 1
{"id":"vm-001","name":"web-01"}{"id":"vm-002","name":"web-02"}{"id":"vm-003","name":"web-03"}Authentication
Section titled “Authentication”import ( "crypto/tls" "crypto/x509" "net/http")
func createTLSClient() *http.Client { cert, err := tls.LoadX509KeyPair("client.crt", "client.key") if err != nil { log.Fatal(err) }
caCert, err := os.ReadFile("ca.crt") if err != nil { log.Fatal(err) }
caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert)
tlsConfig := &tls.Config{ Certificates: []tls.Certificate{cert}, RootCAs: caCertPool, }
return &http.Client{ Transport: &http.Transport{ TLSClientConfig: tlsConfig, }, }}
client := vmv1connect.NewVMServiceClient( createTLSClient(), "https://agent.pilab.hu:8443",)Bearer Token
Section titled “Bearer Token”import ( "net/http" "connectrpc.com/connect")
type tokenAuth struct { token string}
func (t *tokenAuth) AddCredentials(req *http.Request) { req.Header.Set("Authorization", "Bearer "+t.token)}
client := vmv1connect.NewVMServiceClient( http.DefaultClient, "https://agent.pilab.hu:8443", connect.WithInterceptors(&tokenAuth{token: "your-jwt-token"}),)Error Handling
Section titled “Error Handling”Error Response
Section titled “Error Response”HTTP/1.1 404 Not FoundContent-Type: application/jsonConnect-Protocol-Version: 1
{ "code": "not_found", "message": "VM not found", "details": [ { "type": "pivirt.ErrorDetail", "value": { "resource": "virtualmachine", "id": "vm-abc123" } } ]}Error Codes
Section titled “Error Codes”| Code | HTTP Status | Description |
|---|---|---|
canceled |
499 | Operation canceled |
unknown |
500 | Unknown error |
invalid_argument |
400 | Invalid argument |
deadline_exceeded |
504 | Deadline exceeded |
not_found |
404 | Resource not found |
already_exists |
409 | Resource already exists |
permission_denied |
403 | Permission denied |
resource_exhausted |
429 | Resource exhausted |
failed_precondition |
400 | Failed precondition |
aborted |
409 | Operation aborted |
out_of_range |
400 | Out of range |
unimplemented |
501 | Unimplemented |
internal |
500 | Internal error |
unavailable |
503 | Service unavailable |
data_loss |
500 | Data loss |
unauthenticated |
401 | Unauthenticated |
Performance
Section titled “Performance”Benchmarks
Section titled “Benchmarks”| Operation | Latency (p99) | Throughput |
|---|---|---|
| GetVM | 5ms | 10,000 req/s |
| ListVMs | 50ms | 1,000 req/s |
| CreateVM | 100ms | 500 req/s |
Optimization Tips
Section titled “Optimization Tips”- Use HTTP/2 for multiplexing
- Enable compression for large payloads
- Use streaming for large datasets
- Implement caching for read-heavy workloads