Skip to content
Santekno.com | Level Up Your Engineering Skills
ID
📖 0%
26 Jun 2025 · 5 mnt baca ·Artikel 18 / 110
Go

18 Membaca Metadata di Server gRPC

IH
Ihsan Arif
Penulis di Santekno · Backend Engineer

gRPC telah menjadi salah satu framework komunikasi antar layanan paling populer di era cloud-native. Berkat performanya yang tinggi dan dukungannya terhadap berbagai bahasa pemrograman, gRPC sering diadopsi di berbagai proyek skala besar. Salah satu fitur gRPC yang powerful namun sering dianggap sepele adalah metadata. Metadata adalah pasangan key-value yang bisa dikirim bersama setiap permintaan (request) atau respons (response) dalam RPC, mirip dengan HTTP headers, namun lebih terintegrasi di level protokol gRPC.

Pada artikel kali ini, kita akan mengupas tuntas bagaimana membaca metadata pada sisi server gRPC dengan menggunakan contoh implementasi pada bahasa Go (Golang). Kita juga akan melihat contoh dan simulasi praktek, tabel, serta diagram alur untuk memudahkan pemahaman.


Mengenal Metadata di gRPC

Sebelum masuk ke implementasi, mari pahami dulu konsep metadata pada gRPC. Metadata memungkinkan kita untuk menyampaikan informasi tambahan seperti authentication token, request id, custom context, dan sebagainya yang sifatnya tidak rigid terikat pada protokol data utama (protobuf message).

Pada HTTP/2 (yang menjadi transport utama di gRPC), metadata biasanya diterjemahkan menjadi header. Namun, di gRPC, client dan server memiliki API khusus untuk berinteraksi dengan metadata.

Secara umum, metadata terdiri dari key-value pair sebagai berikut:

KeyValueKeterangan
authorizationBearer xxxxxToken otorisasi
client-id12345ID unik client
custom-datasome-informationData custom sesuai kebutuhan


Diagram Alur Membaca Metadata di Server gRPC

Pengolahan metadata pada sisi server gRPC dapat digambarkan seperti berikut:

MERMAID
flowchart TD
    A[Client] -- Kirim RPC + Metadata --> B[gRPC Server]
    B -- Interceptor/Handler Baca Metadata --> C[Business Logic]
    C -- Response + Metadata Opsional --> A

Pada alur di atas, ketika client mengirim request, metadata ikut terkirim. Server bisa membaca metadata tersebut baik di handler biasa maupun lewat interceptor untuk kebutuhan cross-cutting seperti otentikasi atau logging.


Struktur Metadata di Go

Di Go, package utama untuk berinteraksi dengan metadata adalah google.golang.org/grpc/metadata.

Berikut fungsi-fungsi pentingnya:

  • md, ok := metadata.FromIncomingContext(ctx)
    Mendapatkan metadata yang dikirim client dari context.
  • metadata.Pairs(“key”, “value”)
    Membuat metadata baru untuk outbound.

Membaca Metadata di Server Handler

Mari kita buat sebuah service sederhana yang dapat membaca metadata yang dikirimkan oleh client.

Definisi Service (Protobuf)

protobuf
 1syntax = "proto3";
 2
 3package hello;
 4
 5service Greeter {
 6   rpc SayHello (HelloRequest) returns (HelloResponse);
 7}
 8
 9message HelloRequest {
10    string name = 1;
11}
12
13message HelloResponse {
14    string message = 1;
15}

Implementasi Server di Go

Inti dari membaca metadata bisa dilakukan di dalam masing-masing RPC handler.

go
 1import (
 2    "context"
 3    "fmt"
 4    "google.golang.org/grpc"
 5    "google.golang.org/grpc/metadata"
 6    pb "path/to/your/proto"
 7)
 8
 9type server struct {
10    pb.UnimplementedGreeterServer
11}
12
13func (s *server) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloResponse, error) {
14    // Membaca metadata dari context
15    md, ok := metadata.FromIncomingContext(ctx)
16    if !ok {
17        fmt.Println("Tidak ada metadata yang dikirim")
18    } else {
19        // Menampilkan seluruh metadata yang diterima
20        for k, v := range md {
21            fmt.Printf("Metadata %s: %v\n", k, v)
22        }
23    }
24
25    // Ambil nilai tertentu
26    clientIds := md.Get("client-id")
27    if len(clientIds) > 0 {
28        fmt.Println("Client ID:", clientIds[0])
29    }
30
31    return &pb.HelloResponse{
32        Message: fmt.Sprintf("Hello, %s!", req.Name),
33    }, nil
34}

Pada contoh di atas, handler SayHello membaca semua metadata yang dikirimkan oleh client beserta value-nya.


Simulasi: Menjalankan Server dan Mengirim Metadata

Mari simulasikan client yang mengirimkan metadata.

Contoh Client

go
 1import (
 2    "context"
 3    "log"
 4    "google.golang.org/grpc"
 5    "google.golang.org/grpc/metadata"
 6    pb "path/to/your/proto"
 7    "time"
 8)
 9
10func main() {
11    conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
12    if err != nil {
13        log.Fatalf("gagal terkoneksi: %v", err)
14    }
15    defer conn.Close()
16
17    c := pb.NewGreeterClient(conn)
18    md := metadata.New(map[string]string{
19        "client-id":   "abc-123",
20        "custom-data": "example-info",
21    })
22    ctx := metadata.NewOutgoingContext(context.Background(), md)
23
24    resp, err := c.SayHello(ctx, &pb.HelloRequest{Name: "Budi"})
25    if err != nil {
26        log.Fatalf("Error saat request: %v", err)
27    }
28    log.Printf("Server reply: %s", resp.Message)
29}

Output pada Server

bash
1Metadata client-id: [abc-123]
2Metadata custom-data: [example-info]
3Client ID: abc-123

Server berhasil menangkap metadata yang dikirim oleh client.


Penggunaan Interceptor untuk Metadata

Dalam skala besar, membaca metadata biasanya dilakukan pada interceptor—middleware yang dapat menjalankan logic di luar business core, seperti otentikasi atau audit logging.

Contoh Unary Interceptor di Go

go
 1func metadataInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
 2    md, ok := metadata.FromIncomingContext(ctx)
 3    if ok {
 4        if tokens := md.Get("authorization"); len(tokens) > 0 {
 5            fmt.Println("Auth token:", tokens[0])
 6        }
 7    }
 8    // Melanjutkan ke handler utama
 9    return handler(ctx, req)
10}
11
12// Saat setup server
13grpc.NewServer(
14    grpc.UnaryInterceptor(metadataInterceptor),
15)

Kapan menggunakan interceptor:

  • Validasi token sesi di seluruh method gRPC
  • Audit logging metadata
  • Monitoring dan tracing

Tabel: Perbandingan Cara Membaca Metadata

CaraKeunggulanKekuranganUse Case
Di HandlerJadi satu dengan business logicRedundant jika multi-methodUse-case spesifik per-RPC
Di InterceptorDRY, sekali implementasi globalTidak per-RPC customOtentikasi, logging semua RPC
KombinasiFleksibel, bisa pilih kebutuhanMungkin perlu koordinasiCrosscut + per-RPC kustom data parsing

Best Practices

  1. Prefix metadata custom dengan identifier unik untuk menghindari bentrok (misal: x-myapp-userid).
  2. Hindari metadata untuk payload besar—gunakan untuk data kecil seperti token, trace-id, dsb.
  3. Case insensitive – Key metadata tidak case sensitive, tapi konvensi lower-case lebih baik.
  4. Gunakan Interceptor untuk Crosscutting, handler untuk kebutuhan per-method.

Kesimpulan

Membaca metadata di server gRPC bukan hanya sekadar membaca key-value dari context, tapi merupakan pondasi pengembangan layanan yang aman, maintainable, dan scalable. Dengan memahami cara kerja dan praktik terbaik penggunaan metadata, kita bisa membangun aplikasi yang lebih modular, mudah diektensi, sekaligus aman.

Jangan ragu untuk mengeksplorasi fitur metadata lebih dalam, misal untuk implementasi rate limiting, distributed tracing, atau sistem monitoring terintegrasi di ekosistem microservices Anda!


Referensi


Danger
Selamat bereksperimen dengan metadata gRPC, demi keamanan & observabilitas sistem yang lebih baik!

Artikel Terkait

💬 Komentar