improbable-eng/grpc-web


gRPC Web implementation for Golang and TypeScript

License: Apache-2.0

Language: TypeScript

Keywords: browser, golang, grpc, grpc-web, typescript


gRPC-Web: Typed Frontend Development

Master Build BrowserStack Status NPM GoDoc Apache 2.0 License quality: alpha Slack

gRPC is a modern, HTTP2-based protocol, that provides RPC semantics using the strongly-typed binary data format of protocol buffers across multiple languages (C++, C#, Golang, Java, Python, NodeJS, ObjectiveC, etc.)

gRPC-Web is a cutting-edge spec that enables invoking gRPC services from modern browsers.

If you are looking for gRPC support for Node.js there is an official Node.js gRPC library. This package supports Node.js, but requires that the server has the gRPC-Web compatibility layer (read on to understand more).

Components of the stack are based on Golang and TypeScript:

  • grpcweb - a Go package that wraps an existing grpc.Server as a gRPC-Web http.Handler for both HTTP2 and HTTP/1.1.
  • grpcwebproxy - a Go-based stand-alone reverse proxy for classic gRPC servers (e.g. in Java or C++) that exposes their services over gRPC-Web to modern browsers.
  • ts-protoc-gen - a TypeScript plugin for the protocol buffers compiler that provides strongly typed message classes and method definitions.
  • @improbable-eng/grpc-web - a TypeScript gRPC-Web client library for browsers (and Node.js).

Why?

With gRPC-Web, it is extremely easy to build well-defined, easy to reason about APIs between browser frontend code and microservices. Frontend development changes significantly:

  • no more hunting down API documentation - .proto is the canonical format for API contracts.
  • no more hand-crafted JSON call objects - all requests and responses are strongly typed and code-generated, with hints available in the IDE.
  • no more dealing with methods, headers, body and low level networking - everything is handled by grpc.invoke.
  • no more second-guessing the meaning of error codes - gRPC status codes are a canonical way of representing issues in APIs.
  • no more one-off server-side request handlers to avoid concurrent connections - gRPC-Web is based on HTTP2, with multiplexes multiple streams over the same connection.
  • no more problems streaming data from a server - gRPC-Web supports both 1:1 RPCs and 1:many streaming requests.
  • no more data parse errors when rolling out new binaries - backwards and forwards-compatibility of requests and responses.

In short, gRPC-Web moves the interaction between frontend code and microservices from the sphere of hand-crafted HTTP requests to well-defined user-logic methods.

Client-side (grpc-web) Docs

Note: You'll need to add gRPC-Web compatibility to your server through either grpcweb or grpcwebproxy.

API Docs for grpc-web client can be found here

Example

For a self-contained demo of a Golang gRPC service called from a TypeScript project, see example. It contains most of the initialization code that performs the magic. Here's the application code extracted from the example:

You use .proto files to define your service. In this example, one normal RPC (GetBook) and one server-streaming RPC (QueryBooks):

syntax = "proto3";

message Book {
  int64 isbn = 1;
  string title = 2;
  string author = 3;
}

message GetBookRequest {
  int64 isbn = 1;
}

message QueryBooksRequest {
  string author_prefix = 1;
}

service BookService {
  rpc GetBook(GetBookRequest) returns (Book) {}
  rpc QueryBooks(QueryBooksRequest) returns (stream Book) {}
}

And implement it in Go (or any other gRPC-supported language):

import pb_library "../_proto/examplecom/library"

type bookService struct{
        books []*pb_library.Book
}

func (s *bookService) GetBook(ctx context.Context, bookQuery *pb_library.GetBookRequest) (*pb_library.Book, error) {
	for _, book := range s.books {
		if book.Isbn == bookQuery.Isbn {
			return book, nil
		}
	}
	return nil, grpc.Errorf(codes.NotFound, "Book could not be found")
}

func (s *bookService) QueryBooks(bookQuery *pb_library.QueryBooksRequest, stream pb_library.BookService_QueryBooksServer) error {
	for _, book := range s.books {
		if strings.HasPrefix(s.book.Author, bookQuery.AuthorPrefix) {
			stream.Send(book)
		}
	}
	return nil
}

You will be able to access it in a browser using TypeScript (and equally JavaScript after transpiling):

import {grpc} from "@improbable-eng/grpc-web";

// Import code-generated data structures.
import {BookService} from "../_proto/examplecom/library/book_service_pb_service";
import {QueryBooksRequest, Book, GetBookRequest} from "../_proto/examplecom/library/book_service_pb";

const queryBooksRequest = new QueryBooksRequest();
queryBooksRequest.setAuthorPrefix("Geor");
grpc.invoke(BookService.QueryBooks, {
  request: queryBooksRequest,
  host: "https://example.com",
  onMessage: (message: Book) => {
    console.log("got book: ", message.toObject());
  },
  onEnd: (code: grpc.Code, msg: string | undefined, trailers: grpc.Metadata) => {
    if (code == grpc.Code.OK) {
      console.log("all ok")
    } else {
      console.log("hit an error", code, msg, trailers);
    }
  }
});

Usage with React

Browser Support

The @improbable-eng/grpc-web client uses multiple techniques to efficiently invoke gRPC services. Most modern browsers support the Fetch API, which allows for efficient reading of partial, binary responses. For older browsers, it automatically falls back to XMLHttpRequest.

The gRPC semantics encourage you to make multiple requests at once. With most modern browsers supporting HTTP2, these can be executed over a single TLS connection. For older browsers, gRPC-Web falls back to HTTP/1.1 chunk responses.

This library is tested against:

  • Chrome >= 41
  • Firefox >= 21
  • Edge >= 13
  • IE >= 11
  • Safari >= 6

Node.js Support

The @improbable-eng/grpc-web client also supports Node.js through a transport that uses the http and https packages. Usage does not vary from browser usage as transport is determined at runtime.

If you want to use the @improbable-eng/grpc-web client in a node.js environment with Typescript, you must include dom in the "lib" Array in your tsconfig.json otherwise tsc will be unable to find some type declarations to compile. Note that dom will be included automatically if you do not declare lib in your configration and your target is one of es5 or es6. (See Typescript compiler options).

{
  "compilerOptions": {
    "lib": [ "dom", /* ... */ ],
  }
}

Please note - There is an official Node.js gRPC library that does not require the server to support gRPC-Web

Client-side streaming

It is very important to note that the gRPC-Web spec currently does not support client-side streaming. This is unlikely to change until new whatwg fetch/streams API lands in browsers. As such, if you plan on using gRPC-Web you're limited to:

  • unary RPCs (1 request 1 response)
  • server-side streaming RPCs (1 request N responses)

This, however, is useful for a lot of frontend functionality.

Status

The code here is alpha quality. It is being used for a subset of Improbable's frontend single-page apps in production.

Known Limitations

See the @improbable-eng/grpc-web client Transport Documentation for a list of Web Browser caveats.

Contributing

See CONTRIBUTING

Project Statistics

Sourcerank 13
Repository Size 3.17 MB
Stars 2,476
Forks 230
Watchers 71
Open issues 66
Dependencies 2,561
Contributors 60
Tags 72
Created
Last updated
Last pushed

Top Contributors See all

Marcus Longmuir Jonny Reeves Michal Witkowski dependabot[bot] dependabot-preview[bot] Milan Pavlik Johan Brandhorst Runar Heggset Cristian Bodnar Filipe Azevedo vdods Anuraag Agrawal John Reeves midan888 Marcus Longmuir Tatsuyuki Ishi James Grant Mike Winstead Philip I. Thomas Dominic Green

Packages Referencing this Repo

grpc-web-node-http-transport
Node HTTP Transport for use with grpc-web-client
Latest release 0.0.1 - Published - 2.48K stars
github.com/improbable-eng/grpc-web/test/go/testserver
gRPC Web implementation for Golang and TypeScript
Latest release grpc-web-integration-test@0.11.0 - Published - 2.48K stars
github.com/improbable-eng/grpc-web/go/grpcweb
gRPC Web implementation for Golang and TypeScript
Latest release grpc-web-integration-test@0.11.0 - Published - 2.48K stars
github.com/improbable-eng/grpc-web/integration_test/go/testserver
gRPC Web implementation for Golang and TypeScript
Latest release grpc-web-integration-test@0.11.0 - Published - 2.48K stars
grpc-web-client
gRPC-Web client for browsers (JS/TS)
Latest release 0.7.0 - Updated - 2.48K stars
github.com/mwitkow/grpc-browser-compat
gRPC Web implementation for Golang and TypeScript
Latest release grpc-web-integration-test@0.11.0 - Published - 2.48K stars
github.com/improbable-eng/grpc-web/go/grpcwebproxy
gRPC Web implementation for Golang and TypeScript
Latest release grpc-web-integration-test@0.11.0 - Published - 2.48K stars
@improbable-eng/grpc-web
gRPC-Web client for browsers (JS/TS)
Latest release 0.11.0 - Updated - 2.48K stars
@improbable-eng/grpc-web-node-http-transport
Node HTTP Transport for use with @improbable-eng/grpc-web
Latest release 0.11.0 - Updated - 2.48K stars
github.com/improbable-eng/grpc-web/example/go/exampleserver
gRPC Web implementation for Golang and TypeScript
Latest release grpc-web-integration-test@0.11.0 - Published - 2.48K stars
grpc-web-client-dm-ws
gRPC-Web client for browsers (JS/TS)
Latest release 0.5.3 - Updated - 2.48K stars

Recent Tags See all

@improbable-eng/grpc-web-node-http-transport@0.11.0 August 06, 2019
@improbable-eng/grpc-web-fake-transport@0.11.0 August 06, 2019
@improbable-eng/grpc-web@0.11.0 August 06, 2019
@improbable-eng/grpc-web@0.11.0 August 06, 2019
grpc-web-react-example@0.11.0 August 06, 2019
grpc-web-integration-test@0.11.0 August 06, 2019
v0.11.0 August 06, 2019
@improbable-eng/grpc-web-node-http-transport@0.10.0 August 05, 2019
@improbable-eng/grpc-web-node-http-transport@0.10.0 August 05, 2019
@improbable-eng/grpc-web-fake-transport@0.10.0 August 05, 2019
@improbable-eng/grpc-web@0.10.0 August 05, 2019
@improbable-eng/grpc-web@0.10.0 August 05, 2019
grpc-web-react-example@0.10.0 August 05, 2019
grpc-web-integration-test@0.10.0 August 05, 2019
v0.10.0 August 05, 2019

Interesting Forks See all

MarcusLongmuir/grpc-web
gRPC Web implementation for Golang and TypeScript
TypeScript - Apache-2.0 - Last pushed - 1 stars - 1 forks
ctaggart/grpc-web
gRPC Web implementation for Golang and TypeScript
TypeScript - Apache-2.0 - Last pushed - 1 stars

Something wrong with this page? Make a suggestion

Last synced: 2019-08-06 14:18:00 UTC

Login to resync this repository