Dalam membangun aplikasi backend modern dengan gRPC, memastikan validitas data request adalah aspek krusial. Sama halnya seperti REST, pada gRPC kita bisa menggunakan interceptor untuk melakukan validasi request secara terpusat sebelum mencapai logic utama pada service handler.
Artikel ini akan membahas studi kasus bagaimana membangun interceptor validasi pada gRPC server di Golang — lengkap dengan contoh kode, alur diagram, dan tabel skenario request.
Konsep Interceptor di gRPC
Interceptor pada gRPC Go berperan layaknya middleware di Express. Interceptor dapat dipasang di:
- Unary RPC: untuk setiap request-response biasa
- Streaming RPC: untuk stream data masuk dan keluar
Interceptor dapat digunakan untuk:
- Validasi input
- Logging
- Monitoring
- Autentikasi
- Error handling
Pada studi kasus ini, kita akan fokus pada Unary Interceptor untuk validasi input.
Studi Kasus: Validasi Request CreateUser
Skema Request
message CreateUserRequest {
string name = 1;
string email = 2;
int32 age = 3;
}
message CreateUserResponse {
string message = 1;
}
service UserService {
rpc CreateUser(CreateUserRequest) returns (CreateUserResponse);
}
Validasi yang Diinginkan:
nameharus string dan tidak kosongemailharus valid formatageopsional, jika ada harus >= 0
Implementasi Interceptor Validasi
1. Interceptor Function
func ValidationInterceptor(
ctx context.Context,
req interface{},
info *grpc.UnaryServerInfo,
handler grpc.UnaryHandler,
) (interface{}, error) {
switch r := req.(type) {
case *pb.CreateUserRequest:
if r.GetName() == "" {
return nil, status.Error(codes.InvalidArgument, "Name is required")
}
if !isValidEmail(r.GetEmail()) {
return nil, status.Error(codes.InvalidArgument, "Email is invalid")
}
if r.Age < 0 {
return nil, status.Error(codes.InvalidArgument, "Age must be >= 0")
}
}
// lanjut ke handler
return handler(ctx, req)
}
func isValidEmail(email string) bool {
re := regexp.MustCompile(`^[^@\s]+@[^@\s]+\.[^@\s]+$`)
return re.MatchString(email)
}
2. Registrasi Interceptor ke Server
s := grpc.NewServer(
grpc.UnaryInterceptor(ValidationInterceptor),
)
pb.RegisterUserServiceServer(s, &UserService{})
Alur Request gRPC dengan Validasi Interceptor
sequenceDiagram
participant Client
participant gRPCServer
participant Interceptor
participant Handler
Client->>gRPCServer: CreateUser(request)
gRPCServer->>Interceptor: Validasi input
alt Valid
Interceptor->>Handler: Lanjut handler
Handler-->>Client: Response OK
else Tidak valid
Interceptor-->>Client: Error 400 (InvalidArgument)
end
Tabel Skenario Validasi
| # | Request Payload | Response | Status |
|---|---|---|---|
| 1 | Name OK, email OK, age 20 | OK | OK |
| 2 | Name kosong | Error: Name required | InvalidArgument |
| 3 | Email tidak valid | Error: Email invalid | InvalidArgument |
| 4 | Age -5 | Error: Age invalid | InvalidArgument |
| 5 | Email kosong | Error: Email invalid | InvalidArgument |
Manfaat Menggunakan Interceptor untuk Validasi
- Pemisahan tanggung jawab (SoC): handler hanya mengurus logic utama
- Konsistensi: validasi seragam di seluruh handler
- Mudah diuji: Interceptor bisa diunit-test
- Reusabilitas: bisa diextend ke endpoint lain
Kesimpulan
Validasi request menggunakan gRPC interceptor di Golang adalah pendekatan efisien, rapi, dan idiomatik. Dengan teknik ini, kita bisa menjaga handler tetap bersih dan memusatkan semua aturan validasi ke dalam interceptor, membuat codebase lebih scalable dan maintainable.
Gunakan pendekatan ini di setiap service RPC yang membutuhkan validasi — dan gabungkan dengan autentikasi, rate limit, dan logging untuk sistem backend yang solid dan profesional.