gRPC-Web ile Tarayıcıdan gRPC Servislerine Erişim
gRPC, yüksek performanslı, tip güvenli ve HTTP/2 tabanlı bir RPC framework'üdür. Ancak tarayıcılar, HTTP/2'nin gRPC'nin ihtiyaç duyduğu ileri düzey özelliklerini (trailers, düşük seviyeli framing) JavaScript API'leri üzerinden doğrudan sunmaz. gRPC-Web, bu boşluğu doldurmak için tasarlanmış bir protokol adaptasyonudur . Tarayıcı tabanlı uygulamaların (JavaScript, Blazor WebAssembly) gRPC servislerini çağırmasını sağlar .
1. gRPC-Web Neden Gerekli?
Tarayıcıların gRPC'yi doğrudan desteklememesinin temel nedenleri:
-
Trailers Eksikliği: gRPC, durum bilgisini (grpc-status) HTTP trailers'da taşır. Ancak tarayıcı JavaScript API'leri, HTTP yanıtlarının trailers bölümüne erişemez .
-
HTTP/2 Framing Kontrolü Yok: gRPC, HTTP/2'nin düşük seviyeli framing özelliklerine ihtiyaç duyar. Tarayıcılar bu katmana erişim izni vermez .
-
Client Streaming Desteği Yok: Tarayıcı API'leri, çift yönlü akışları doğrudan desteklemez .
gRPC-Web, bu kısıtlamaları aşmak için protokolü HTTP/1.1 ve HTTP/2 üzerinde çalışabilir hale getirir . Durum bilgisi (grpc-status), yanıtın gövdesinin sonuna bir trailer frame olarak eklenir .
2. gRPC-Web Mimarisi: Proxy mi, Middleware mi?
gRPC-Web'i kullanmak için iki temel yaklaşım vardır:
A. Envoy Proxy ile Çeviri
Geleneksel yaklaşım, bir Envoy proxy kullanmaktır. Envoy, tarayıcıdan gelen gRPC-Web çağrısını alır, HTTP/1.1'den HTTP/2'ye çevirir ve arkasındaki gRPC sunucusuna iletir .
-
Avantaj: Mevcut gRPC servislerinizde hiçbir değişiklik yapmanız gerekmez.
-
Dezavantaj: Ek bir proxy katmanı ve operasyonel yük getirir.
B. ASP.NET Core Middleware ile Doğrudan Destek
ASP.NET Core, Grpc.AspNetCore.Web paketi ile gRPC-Web'i doğrudan destekler. Bu, ayrı bir proxy'ye ihtiyaç duymadan gRPC-Web çağrılarını kabul etmenizi sağlar .
-
Avantaj: Basit, ek altyapı gerektirmez.
-
Dezavantaj: Sadece ASP.NET Core sunucuları için geçerlidir.
3. ASP.NET Core'da gRPC-Web Sunucu Yapılandırması
Adım 1: Paket Ekleme
bash
dotnet add package Grpc.AspNetCore.Web
Adım 2: Program.cs Yapılandırması
csharp
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
builder.Services.AddCors(o => o.AddPolicy("GrpcWeb", policy =>
{
policy.WithOrigins("https://localhost:7001")
.AllowAnyHeader()
.AllowAnyMethod()
.WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding");
}));
var app = builder.Build();
app.UseRouting();
// gRPC-Web middleware'ini ekle
app.UseGrpcWeb(new GrpcWebOptions { DefaultEnabled = true });
app.UseCors("GrpcWeb");
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>().EnableGrpcWeb().RequireCors("GrpcWeb");
});
app.Run();
Kritik Nokta: gRPC-Web, tarayıcıdan çağrıldığında CORS yapılandırması gerekir. WithExposedHeaders ile gRPC'ye özel başlıkların tarayıcıya açılması sağlanır .
4. .NET İstemci ile gRPC-Web Kullanımı (Blazor WebAssembly)
Blazor WebAssembly uygulamaları tarayıcıda çalıştığı için aynı HTTP kısıtlamalarına tabidir. .NET istemcisi ile gRPC-Web çağrısı yapmak için kanal (channel) yapılandırması yeterlidir .
Adım 1: Paket Ekleme
bash
dotnet add package Grpc.Net.Client.Web
Adım 2: Kanal Yapılandırması
csharp
var channel = GrpcChannel.ForAddress("https://localhost:53305", new GrpcChannelOptions
{
HttpHandler = new GrpcWebHandler(new HttpClientHandler())
});
var client = new Greeter.GreeterClient(channel);
var response = await client.SayHelloAsync(new HelloRequest { Name = "Tarayıcı" });
GrpcWebHandler Seçenekleri:
-
GrpcWebMode.GrpcWeb: İçerik kodlaması yok (varsayılan).
-
GrpcWebMode.GrpcWebText: Base64 kodlu içerik. Tarayıcıda server streaming için gereklidir .
DI ile Kullanım (Önerilen):
csharp
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(options =>
{
options.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(
() => new GrpcWebHandler(new HttpClientHandler()));
Önemli: Blazor WebAssembly'de senkron metotlar (SayHello) uygulamayı kilitleyebilir. Her zaman asenkron metotları (SayHelloAsync) kullanın .
5. gRPC-Web'in Sınırlamaları
| Özellik | Destek Durumu |
|---|---|
| Unary RPC | ✅ Desteklenir |
| Server Streaming | ✅ Desteklenir (GrpcWebText modunda) |
| Client Streaming | ❌ Desteklenmez (tarayıcı kısıtlaması) |
| Bidirectional Streaming | ❌ Desteklenmez |
Not: ASP.NET Core gRPC servisleri Azure App Service veya IIS üzerinde barındırıldığında, client streaming ve bidirectional streaming desteklenmez .
6. gRPC-Web vs. REST ve WebSocket
gRPC-Web, aşağıdaki durumlarda güçlü bir alternatiftir:
-
Mevcut gRPC Servislerine Erişim: Sunucu tarafında zaten gRPC kullanıyorsanız, gRPC-Web ile tarayıcıdan aynı servislere erişebilirsiniz .
-
Tip Güvenliği: Protobuf tabanlı tip güvenliği, REST'teki JSON doğrulama ihtiyacını ortadan kaldırır .
-
Verimli Serileştirme: Protobuf, JSON'dan daha küçük ve hızlıdır .
-
Server Streaming: WebSocket'in karmaşıklığı olmadan sunucudan istemciye gerçek zamanlı veri akışı sağlar .
Ancak: Public API'ler ve geniş tarayıcı uyumluluğu gerektiren durumlar için REST hala daha uygun olabilir .
Sonuç
gRPC-Web, tarayıcı tabanlı uygulamaların gRPC servislerini kullanmasını sağlayan pratik bir çözümdür. ASP.NET Core, Grpc.AspNetCore.Web middleware'i ile gRPC-Web'i doğrudan destekler; ayrı bir Envoy proxy'sine ihtiyaç duymaz . Blazor WebAssembly uygulamaları, Grpc.Net.Client.Web paketi ile gRPC-Web çağrıları yapabilir . Client streaming ve bidirectional streaming desteklenmese de, unary ve server streaming çağrıları gRPC-Web ile sorunsuz çalışır . Mevcut gRPC servislerinizi tarayıcıya açmak istiyorsanız, gRPC-Web değerlendirmeniz gereken güçlü bir seçenektir.