DEV Community

Cover image for ConnectRPC là gì: Giao thức Connect
Sebastian Petrus
Sebastian Petrus

Posted on • Originally published at apidog.com

ConnectRPC là gì: Giao thức Connect

Nếu bạn đã từng gọi một dịch vụ gRPC từ trình duyệt, bạn sẽ gặp ngay giới hạn: JavaScript trong trình duyệt không kiểm soát được HTTP trailers, nên không thể giao tiếp trực tiếp với gRPC gốc. Cách phổ biến là đặt thêm proxy như Envoy để dịch lưu lượng. ConnectRPC giải quyết vấn đề này bằng cách cho phép bạn xây dựng API dựa trên Protobuf mà trình duyệt có thể gọi trực tiếp, vẫn dùng được với curl, và vẫn tương thích với hệ sinh thái gRPC.

Dùng thử Apidog ngay hôm nay

Bài viết này đi thẳng vào cách ConnectRPC hoạt động, khi nào nên dùng Connect thay vì gRPC, gRPC-Web hoặc REST, cách một request Connect đi qua HTTP, và cách kiểm tra endpoint Connect/gRPC bằng công cụ API thông thường.

ConnectRPC là gì

ConnectRPC là một bộ thư viện để xây dựng API HTTP tương thích với trình duyệt và gRPC từ Protocol Buffers.

Quy trình cơ bản:

  1. Định nghĩa service trong file .proto.
  2. Generate code từ schema.
  3. Implement handler.
  4. Đăng ký handler vào HTTP server.
  5. Gọi service từ trình duyệt, Node.js, Go client, curl, hoặc gRPC client.

Connect xử lý các phần còn lại như routing, serialization, compression và client generation.

Dự án được tạo bởi Buf, công ty đứng sau bộ công cụ buf cho Protobuf, và hiện là một dự án sandbox của CNCF. Điều này khiến Connect phù hợp với workflow schema-first: schema .proto là nguồn sự thật, còn server/client được generate từ schema đó.

Một server ConnectRPC có thể phục vụ đồng thời ba giao thức:

  • gRPC: tương thích với gRPC gốc, bao gồm streaming và trailers.
  • gRPC-Web: hỗ trợ trực tiếp, không cần proxy riêng chỉ để dịch gRPC-Web.
  • Connect: giao thức HTTP riêng của Connect, thân thiện với trình duyệt và công cụ HTTP.

Điểm thực tế quan trọng: cùng một service có thể được gọi bởi browser client qua Connect, backend service qua gRPC, và công cụ debug qua HTTP/JSON.

Vấn đề Connect giải quyết

gRPC mạnh, nhanh và có kiểu dữ liệu rõ ràng, nhưng không phù hợp trực tiếp với trình duyệt.

Lý do chính:

  • gRPC dựa trên HTTP/2.
  • gRPC dùng HTTP trailers để truyền trạng thái.
  • Browser không expose trailers cho JavaScript theo cách mà gRPC gốc cần.

Vì vậy, nếu frontend muốn gọi backend gRPC, bạn thường cần:

Browser → gRPC-Web → Envoy/proxy → gRPC backend
Enter fullscreen mode Exit fullscreen mode

Mô hình này hoạt động, nhưng thêm chi phí vận hành:

  • Phải deploy và cấu hình proxy.
  • Phải debug thêm một tầng trung gian.
  • Cần hiểu mapping giữa gRPC-Web và gRPC gốc.
  • Local development phức tạp hơn.

Connect chọn hướng khác:

Browser → HTTP/JSON hoặc HTTP/Protobuf → Connect server
Enter fullscreen mode Exit fullscreen mode

Nếu bạn vẫn cần phục vụ gRPC client hiện có:

gRPC client → gRPC → cùng Connect server
Enter fullscreen mode Exit fullscreen mode

Kết quả là bạn có một backend duy nhất phục vụ được:

  • Trình duyệt.
  • CLI như curl.
  • API client thông thường.
  • gRPC client.
  • gRPC-Web client.

Connect so với gRPC, gRPC-Web và REST

Các lựa chọn này có điểm giao nhau, nhưng mục tiêu khác nhau.

gRPC

gRPC dùng Protobuf qua HTTP/2 với binary framing và trailers. Nó hiệu quả, có type safety tốt, và hỗ trợ bốn kiểu streaming.

Tuy nhiên, gRPC khó gọi trực tiếp từ trình duyệt hoặc shell. Nếu bạn muốn hiểu kỹ hơn lớp vận chuyển, xem cách gRPC và HTTP/2 hoạt động cùng nhau.

gRPC-Web

gRPC-Web là biến thể gRPC dành cho trình duyệt. Nó vẫn dựa trên Protobuf và service/method giống gRPC, nhưng thường cần proxy để kết nối tới backend gRPC gốc.

Bạn có thể xem thêm tại gRPC-Web là gì.

Connect

Connect giữ lại schema Protobuf và mô hình service/method giống gRPC, nhưng giao thức Connect chạy qua HTTP/1.1, HTTP/2 và HTTP/3.

Với unary call, request có thể là HTTP POST thông thường:

  • Body là JSON hoặc Protobuf binary.
  • Không cần gRPC binary framing.
  • Response dùng HTTP status code thật.
  • Có thể debug bằng curl hoặc API client.

Đây là lý do Connect dễ tiếp cận hơn gRPC gốc trong quá trình phát triển web.

REST

REST hướng tài nguyên và không bắt buộc schema. REST có độ phổ biến rất cao, dễ dùng với mọi HTTP client, nhưng thường thiếu type safety và code generation mạnh như Protobuf.

Nếu bạn đang cân nhắc giữa hai hướng, xem thêm gRPC so với REST.

Tóm lại:

  • Dùng gRPC khi bạn kiểm soát cả hai đầu service-to-service và cần hiệu năng/streaming.
  • Dùng gRPC-Web khi bạn đã có backend gRPC và cần browser access thông qua proxy.
  • Dùng Connect khi bạn muốn Protobuf + type safety + browser-friendly HTTP.
  • Dùng REST khi bạn cần API hướng tài nguyên, đơn giản, phổ biến.

Connect tận dụng Protobuf và mô hình phương thức của gRPC, nhưng loại bỏ phần gây khó khăn cho trình duyệt và shell.

Một request Connect qua HTTP

Một unary call trong Connect là HTTP POST thông thường.

Đường dẫn được tạo từ schema Protobuf theo định dạng:

/<package>.<Service>/<Method>
Enter fullscreen mode Exit fullscreen mode

Ví dụ, nếu bạn có:

package greet.v1;

service GreetService {
  rpc Greet(GreetRequest) returns (GreetResponse);
}
Enter fullscreen mode Exit fullscreen mode

Endpoint sẽ là:

/greet.v1.GreetService/Greet
Enter fullscreen mode Exit fullscreen mode

Bạn có thể gọi bằng curl:

curl \
  --header "Content-Type: application/json" \
  --data '{"name": "Jane"}' \
  http://localhost:8080/greet.v1.GreetService/Greet
Enter fullscreen mode Exit fullscreen mode

Response là JSON thường:

{"greeting": "Hello, Jane!"}
Enter fullscreen mode Exit fullscreen mode

Không cần custom client. Không cần proxy. Không cần decode binary framing.

Với unary request, Connect hỗ trợ hai content type chính:

  • application/json: dễ đọc, phù hợp khi phát triển và debug.
  • application/proto: Protobuf binary, nhỏ gọn hơn.

Ví dụ gửi Protobuf binary:

curl \
  --header "Content-Type: application/proto" \
  --data-binary @request.bin \
  http://localhost:8080/greet.v1.GreetService/Greet
Enter fullscreen mode Exit fullscreen mode

Streaming call dùng content type khác:

  • application/connect+proto
  • application/connect+json

Với streaming, mỗi message được bọc trong envelope gồm:

  1. 1 byte flag.
  2. 4 byte độ dài big-endian.
  3. Message payload.

Unary call không dùng envelope này, nên nó ánh xạ rất sạch vào HTTP request thông thường.

Nếu bạn đang chọn định dạng payload, xem thêm Protobuf so với JSON.

Hỗ trợ ngôn ngữ và bộ công cụ buf

ConnectRPC có triển khai trên nhiều ngôn ngữ:

  • Go.
  • TypeScript cho browser và Node.js.
  • Swift cho nền tảng Apple.
  • Kotlin cho JVM và Android.
  • Python, hiện đang trong giai đoạn beta.

Go và TypeScript là các triển khai ổn định, sẵn sàng cho production.

Điểm mạnh của workflow này là bạn có thể chia sẻ cùng một schema Protobuf giữa backend và frontend, thay vì viết client thủ công.

Ví dụ workflow với Go:

  1. Viết file .proto.
  2. Cấu hình buf.gen.yaml.
  3. Generate code bằng buf generate.
  4. Implement handler.
  5. Mount handler vào net/http.

Một project Go thường dùng hai plugin:

  • protoc-gen-go: generate message Protobuf.
  • protoc-gen-connect-go: generate handler và client Connect.

Chạy generate:

buf generate
Enter fullscreen mode Exit fullscreen mode

Sau đó bạn implement logic nghiệp vụ trong handler đã generate và đăng ký vào HTTP server.

Vì Connect Go dùng thư viện chuẩn net/http, handler Connect là HTTP handler thông thường. Bạn có thể mount nó cùng các route hiện có mà không cần runtime server riêng.

Ví dụ cấu trúc triển khai thường gặp:

mux := http.NewServeMux()

path, handler := greetv1connect.NewGreetServiceHandler(&GreetServer{})
mux.Handle(path, handler)

http.ListenAndServe(":8080", mux)
Enter fullscreen mode Exit fullscreen mode

Kiểm tra và gỡ lỗi endpoint Connect và gRPC

Vì unary call của Connect là HTTP request với body JSON, bạn có thể test giống REST endpoint.

Test Connect bằng curl

curl \
  --request POST \
  --header "Content-Type: application/json" \
  --data '{"name": "Jane"}' \
  http://localhost:8080/greet.v1.GreetService/Greet
Enter fullscreen mode Exit fullscreen mode

Kiểm tra các phần sau:

  • HTTP status code.
  • Response body.
  • Header Content-Type.
  • Schema của JSON response.
  • Error payload nếu request sai.

Test Connect bằng Apidog

Trong Apidog, bạn có thể gửi request Connect unary như HTTP request thông thường:

  1. Tạo request mới.
  2. Chọn method POST.
  3. Nhập URL theo schema:
http://localhost:8080/greet.v1.GreetService/Greet
Enter fullscreen mode Exit fullscreen mode
  1. Thêm header:
Content-Type: application/json
Enter fullscreen mode Exit fullscreen mode
  1. Nhập body JSON:
{"name": "Jane"}
Enter fullscreen mode Exit fullscreen mode
  1. Gửi request và kiểm tra response.

Apidog không cần là Connect-specific client cho unary call, vì Connect đã expose bề mặt HTTP rõ ràng giống như curl: URL, header, body và HTTP status code.

Nếu bạn cần ôn lại các method HTTP, xem các phương thức HTTP là gì.

Test phía gRPC của cùng server

Một server Connect cũng có thể giao tiếp bằng gRPC. Vì vậy, bạn nên test cả hai mặt nếu service của bạn phục vụ cả browser và backend client.

Với Apidog, bạn có thể:

  1. Import file .proto.
  2. Duyệt danh sách service/method.
  3. Tạo request gRPC có kiểu dữ liệu.
  4. Gửi request đến endpoint gRPC.
  5. Kiểm tra response và metadata.

Điều này giúp bạn kiểm tra cùng một service qua:

  • Connect protocol cho HTTP/browser.
  • gRPC protocol cho service-to-service.

Nếu trọng tâm của bạn là gRPC, xem thêm cách kiểm tra API gRPC hiệu quả.

Tự động hóa kiểm thử Connect và gRPC trong CI

Sau khi request hoạt động đúng, bạn nên lưu chúng thành test scenario để chạy lặp lại trong CI.

Cài Apidog CLI bằng Node:

npm install -g apidog-cli
Enter fullscreen mode Exit fullscreen mode

Chạy scenario hoặc test suite đã lưu:

apidog run \
  --access-token "$APIDOG_ACCESS_TOKEN" \
  -t <scenarioOrSuiteId> \
  -e <environmentId> \
  -r cli,html,junit
Enter fullscreen mode Exit fullscreen mode

Trong đó:

  • --access-token: token truy cập Apidog.
  • -t: ID của scenario hoặc test suite.
  • -e: ID môi trường.
  • -r: định dạng báo cáo, ví dụ cli, html, junit.

CLI chạy headless, nên có thể tích hợp vào GitHub Actions, GitLab CI, Jenkins hoặc bất kỳ pipeline nào chạy được Node.

Workflow đề xuất:

  1. Test request Connect bằng HTTP/JSON trong local.
  2. Test request gRPC bằng file .proto.
  3. Lưu request thành scenario.
  4. Thêm assertion cho status code, field response và error case.
  5. Chạy scenario bằng Apidog CLI trong CI.
  6. Xuất báo cáo JUnit nếu CI cần hiển thị test result.

Xem hướng dẫn chi tiết tại hướng dẫn Apidog CLI để kiểm tra API từ dòng lệnh.

Câu hỏi thường gặp

ConnectRPC có giống gRPC không?

Không. ConnectRPC là framework hỗ trợ ba giao thức: gRPC, gRPC-Web và giao thức Connect riêng.

Một server Connect có thể tương tác với client/server gRPC, nên nó phù hợp với hệ sinh thái gRPC. Tuy nhiên, giao thức Connect là thiết kế HTTP riêng, có thể được gọi trực tiếp từ trình duyệt và shell.

Tôi có còn cần proxy như Envoy để truy cập từ trình duyệt không?

Không, nếu bạn dùng giao thức Connect.

Connect chạy qua HTTP tiêu chuẩn, nên trình duyệt có thể gọi Connect server trực tiếp mà không cần proxy dịch thuật.

Bạn chỉ cần proxy như Envoy nếu backend của bạn chỉ hỗ trợ gRPC gốc và bạn cần kết nối browser traffic đến backend đó.

ConnectRPC hỗ trợ những ngôn ngữ nào?

ConnectRPC hỗ trợ Go và TypeScript ổn định cho production. Ngoài ra còn có Swift, Kotlin và Python, trong đó Python đang ở giai đoạn beta.

Tất cả đều có thể được generate từ cùng một schema Protobuf.

Mối quan hệ giữa Connect và buf là gì?

ConnectRPC được tạo bởi Buf và thường dùng toolchain buf để generate code.

Bạn cấu hình plugin như protoc-gen-connect-go, sau đó chạy:

buf generate
Enter fullscreen mode Exit fullscreen mode

Lệnh này tạo handler và client từ file .proto.

Tôi có thể kiểm tra endpoint Connect bằng API client thông thường không?

Có.

Unary call của Connect là HTTP POST với body JSON hoặc Protobuf và HTTP status code thật. Vì vậy, bất kỳ HTTP client nào như curl hoặc Apidog đều có thể gửi request.

Apidog cũng có thể gọi phía gRPC của cùng server bằng cách import file .proto.

Top comments (0)