All Projects → wisetime-io → pbts-grpc-transcoder

wisetime-io / pbts-grpc-transcoder

Licence: Apache-2.0 license
A TypeScript library that provides gRPC to HTTP/1 & JSON transcoding for the protobuf.js library

Programming Languages

typescript
32286 projects
Makefile
30231 projects
javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to pbts-grpc-transcoder

read-protobuf
Small library to read serialized protobuf(s) directly into Pandas Dataframe
Stars: ✭ 28 (+133.33%)
Mutual labels:  protobuf
protobuf-ue4
Build Protobuf for Unreal Engine 4 with Jenkins Pipeline.
Stars: ✭ 26 (+116.67%)
Mutual labels:  protobuf
protostuff-compiler
Protobuf parser, java code and documentation generator
Stars: ✭ 42 (+250%)
Mutual labels:  protobuf
Rabbit-OJ-Backend
Using Go & MySQL & Docker & Web Socket & gRPC & Kafka & Zookeeper & Protobuf. Distributed and Scalable Open Judge System for Algorithms.
Stars: ✭ 20 (+66.67%)
Mutual labels:  protobuf
protoconfig
ProtoConfig 1.0: Open Standard for using, defining, and consuming software configuration input in a unified way.
Stars: ✭ 24 (+100%)
Mutual labels:  protobuf
kafka-protobuf-serde
Serializer/Deserializer for Kafka to serialize/deserialize Protocol Buffers messages
Stars: ✭ 52 (+333.33%)
Mutual labels:  protobuf
yages
Yet another gRPC echo server (YAGES)
Stars: ✭ 28 (+133.33%)
Mutual labels:  protobuf
cocolian-rpc
使用Apache Thrift作为容器,Google Protobuf作为协议的一个RPC框架。
Stars: ✭ 19 (+58.33%)
Mutual labels:  protobuf
terraform-pb
Programmatic management of infrastructure using Terraform and Protocol Buffers
Stars: ✭ 18 (+50%)
Mutual labels:  protobuf
grpcweb-boilerplate
A minimal repo containing all the boilerplate for getting started with GopherJS using gRPC-Web
Stars: ✭ 45 (+275%)
Mutual labels:  protobuf
django-grpc
Easy gRPC service based on Django application
Stars: ✭ 177 (+1375%)
Mutual labels:  protobuf
AndroidNetworkProgramming
Android网络编程实战总结,涉及HTTP、TCP、UDP常用协议。
Stars: ✭ 34 (+183.33%)
Mutual labels:  protobuf
stockholm
💵 Modern Python library for working with money and monetary amounts. Human friendly and flexible approach for development. 100% test coverage + built-in support for GraphQL and Protocol Buffers transports using current best-practices.
Stars: ✭ 26 (+116.67%)
Mutual labels:  protobuf
protobuf-ipc-example
Protocol buffer IPC example
Stars: ✭ 19 (+58.33%)
Mutual labels:  protobuf
hsproto
Hearthstone Protobuf files
Stars: ✭ 31 (+158.33%)
Mutual labels:  protobuf
protobuf-example-java
Companion Repository for my Protocol Buffers course
Stars: ✭ 67 (+458.33%)
Mutual labels:  protobuf
Anakin
Codegeneration tool for isomorphic server and mobile Go apps with gRPC & Protobuf. Share code between your backend, Android & iOS app! 🌞
Stars: ✭ 17 (+41.67%)
Mutual labels:  protobuf
console-chat
Chat on your terminal with other users through a gRPC service
Stars: ✭ 21 (+75%)
Mutual labels:  protobuf
boilr-grpc
A boilr template for a gRPC service, with a REST Gateway
Stars: ✭ 15 (+25%)
Mutual labels:  protobuf
karate-grpc
gRPC Testing Made Simple by Karate
Stars: ✭ 43 (+258.33%)
Mutual labels:  protobuf

pbts-grpc-transcoder

pbts-grpc-transcoder is a TypeScript library that provides gRPC to HTTP/1 & JSON transcoding for the protobuf.js library.

The library is published via npm. Get it via:

npm i pbts-grpc-transcoder

Transcoding

gRPC uses HTTP/2 as its transfer protocol and typically sends messages as binary payloads. However, when we define a gRPC service, we can optionally specify HTTP Options for the RPCs, so that REST clients can interact with our service using HTTP/1 and JSON.

We can implement our service as usual in gRPC, and then pass client requests through a transcoding proxy to our service. The following applications can transcode HTTP/1 + JSON to gRPC:

Transcoding is useful if the client does not support gRPC and is not able to use gRPC-Web.

Example Service

Let's look at an example Todo service, defined using Protocol Buffers as:

package todo;

service TodoService {
  rpc CreateTodo(CreateTodoRequest) returns (Todo);
  rpc DeleteTodo(DeleteTodoRequest) returns (google.protobuf.Empty);
}

message CreateTodoRequest {
  string title = 1;
  bool completed = 2;
}

message Todo {
  string id = 1;
  string title = 2;
  bool completed = 3;
}

message DeleteTodoRequest {
  string id = 1;
}

If we define the following HTTP options for the RPCs:

service TodoService {
  rpc CreateTodo(CreateTodoRequest) returns (Todo) {
    option (google.api.http) = {
      post: "/v1/todos"
      body: "*"
    };
  }
  rpc DeleteTodo(DeleteTodoRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v1/todos/{id}"
    };
  }
}

We can then create a new Todo item by making a POST HTTP request to /v1/todos with the following JSON payload:

{
  "title": "Book flight to Mauritius",
  "completed": false
}

We can delete a Todo item by making a HTTP request such as:

DELETE /v1/todos/123

Reverse Transcoding

That's great, we can now communicate with a gRPC service through plain HTTP/1 and JSON. However, we have lost our strongly typed calls and messages and are now dealing with ad hoc HTTP requests and hand-crafted JSON.

What if we could still make fully-typed RPC calls to the server while still going over HTTP/1 with JSON payloads? We would like to use protobuf.js with TypeScript to call our service like this:

todoService
  .createTodo(CreateTodoRequest.create({
    title: "This request is type-checked",
    completed: true,
  }))
  .then(response => {
    console.log(`id: ${response.id}`)
    console.log(`title: ${response.title}`)
    console.log(`completed: ${response.completed}`)
  })

This is what pbts-grpc-transcoder allows us to do. We call our service as if we were making a normal gRPC call using protobuf.js. pbts-grpc-transcoder transcodes the call to HTTP/1 and JSON using the HTTP options specified for the RPC. The proxy receives the HTTP/1 and JSON request and transcodes that to a gRPC call to the underlying service.

Setup

Install pbts-grpc-transcoder via npm:

npm i pbts-grpc-transcoder

protobuf.js will be installed as a dependency and the pbjs and pbts utilities will be available in your node_modules/.bin directory.

Generate the JSON protobuf descriptor. This will be used by the transcoder. For example:

node_modules/.bin/pbjs -t json \
  -o src/generated/protobuf-descriptor.json \
  src/protobuf/todo.proto \

Next, generate the JavaScript client library as a static module that you can import:

node_modules/.bin/pbjs -t static-module \
  -o src/generated/protobuf.js \
  src/protobuf/todo.proto \

Finally, generate the TypeScript types:

node_modules/.bin/pbts \
  -o src/generated/protobuf.d.ts \
  src/generated/protobuf.js

Usage

pbts-grpc-transcoder provides a HTTP executor for protobuf.js. The executor supports automatic call retries via a RetryPolicy. Here's an example showing how to create an executor and provide it to protobuf.js.

import { todo as TodoApi } from "generated/protobuf"
const descriptor = require("generated/protobuf-descriptor.json")

// Request decorator to add the user's ID token for authentication.
const configureRequest = (): RequestInit => ({
  headers: {
    "Authorization": "Bearer ID_TOKEN_HERE",
  },
})

const willRetry = () => {
  // Here we could attempt to exchange user's refresh token for an ID token...
  // Call will be retried when the promise resolves.
  return Promise.resolve()
}

const onGiveUp = () => {
  // For example, force user logout...
}

// Set up a retry policy that will cause the RPC executor to automatically
// retry calls if they fail with status 401 Unauthorized. The executor will
// run willRetry() before retrying the call. It will retry up to 2 times with
// exponential backoff. If the call still fails after 2 retries, the executor
// calls the onGiveUp() callback.
const retryPolicy = responseNotOk(
  (response: Response) => response.status === 401,
  2,
  willRetry,
  onGiveUp,
)

// Create the RPC executor. The createHttpExecutor function is auto-curried.
// You can preconfigure various versions as needed.
const executor = createHttpExecutor(
  window.fetch, retryPolicy, "http://localhost", descriptor, configureRequest
)

const todoService = ReportApi.ReportService.create(
  executor(TodoApi.TodoService)
)

// An RPC message is type checked.
const deleteRequest = TodoApi.DeleteTodoRequest.create({ id: "123" })

// Call the service.
todoService
  .deleteTodo(deleteRequest)
  .then(response => {
    // ...
  })

Limitations

  • This library implements HTTP Options transcoding. It only supports unary RPCs.
  • Please ensure that the JavaScript files that are generated from Protobuf aren't minified.
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].