gRPC یا REST؟ سؤال اشتباهیه
خلاصهٔ کاملتر
بحث «gRPC یا REST» مدام تو توییتر و ردیت تکرار میشه و جواب همیشگی اینه: REST برای APIهای عمومی و مرورگر، gRPC برای میکروسرویسها و زیرساختهایی مثل etcd و Kubernetes. نویسندههای بلاگ Buf میگن هر دو طرف نقاط قوت واقعی دارن، ولی چرا نشه هر دو رو با هم داشت؟ جوابشون Connect هست؛ یه پروتکل و کتابخونه که سرویس gRPC رو مستقیم برای مرورگر هم قابل استفاده میکنه.
مشکل اصلی اینه که gRPC به قابلیتهایی از HTTP/2 مثل trailers (یعنی هدرهایی که بعد از بدنهٔ پاسخ فرستاده میشن) تکیه داره که مرورگر در اختیار جاوااسکریپت نمیذاره. پروژهٔ رسمی gRPC-Web سعی کرد این شکاف رو پر کنه، ولی طبق roadmap خودش دیگه قابلیت جدیدی اضافه نمیکنه و به gRPC-Gateway ارجاع میده. راهحلهایی مثل gRPC-Gateway و Envoy هم یه پراکسی جلوی سرویس میذارن؛ یعنی برای تست یه درخواست ساده از مرورگر باید gateway رو هم بالا بیاری و مسیرهای سفارشی رو با annotationهای google.api.http تو فایل proto تعریف کنی.
سرور Connect روی یه پورت هم gRPC حرف میزنه، هم gRPC-Web و هم پروتکل خود Connect. مرورگر میتونه با JSON یا Protobuf باینری به همون URLی درخواست بفرسته که کلاینت gRPC میزنه و فقط یه پیادهسازی سرور لازمه. نویسنده تست «فرستادن یه دستور curl برای همکار» رو مثال میزنه: با gRPC و gRPC-Web باید فریم رو دستی بسازی (یه بایت flag و چهار بایت طول پیام)، که با هر تغییر متن باید دوباره حسابش کنی. ابزارهایی مثل grpcurl و buf curl کمک میکنن، ولی به schema نیاز دارن.
تو Connect یه فراخوانی unary (یعنی یه درخواست و یه پاسخ) فقط یه POST با Content-Type: application/json هست و پاسخ رو مستقیم تو ترمینال میخونی. کدهای وضعیت HTTP هم معنی دارن: اگه handler خطای NotFound برگردونه، 404 میگیری؛ در حالی که gRPC همون خطا رو با HTTP 200 و داخل trailer به اسم grpc-status برمیگردونه. متدهای بدون اثر جانبی رو هم میشه با یه option تو proto با GET صدا زد. اونوقت کل درخواست تو URL هست و با Cache-Control میشه تو CDN و مرورگر کشش کرد.
قابلیتهای gRPC هم سر جاشون میمونن. با Protobuf-ES و buf generate یه کلاینت TypeScript تولید میشه که نوعها رو چک میکنه؛ مثلاً اگه به فیلد رشتهای عدد بدی، تایپچک رد میشه. با useBinaryFormat: true هم بدون تغییر کد، Protobuf باینری فرستاده میشه. streaming سمت سرور تو مرورگر به شکل async iterable در دسترسه، ولی client streaming و bidi streaming فقط سمت بکاند کار میکنن، چون fetch مرورگر نمیتونه بدنهٔ درخواست رو stream کنه. buf breaking هم تغییرات ناسازگار مثل حذف فیلد یا عوض شدن نوع رو قبل از انتشار میگیره و چون همهٔ کلاینتها از یه فایل proto ساخته میشن، یه چک برای همهشون کافیه.
نکات کلیدی:
- gRPC استاندارد به خاطر وابستگی به trailers در HTTP/2 مستقیم از جاوااسکریپت مرورگر قابل فراخوانی نیست.
- پروژهٔ رسمی grpc/grpc-web دیگه قابلیت جدید اضافه نمیکنه و gRPC-Gateway رو پیشنهاد میده.
- سرور Connect سه پروتکل gRPC، gRPC-Web و Connect رو روی یه پورت پشتیبانی میکنه و پراکسی لازم نداره.
- خطای NotFound در Connect به HTTP 404 تبدیل میشه، ولی gRPC همیشه 200 برمیگردونه.
- متدهای بدون اثر جانبی رو میشه با GET صدا زد و با Cache-Control کش کرد.
- client streaming و bidi streaming به خاطر محدودیت fetch فقط خارج از مرورگر در دسترسن.




