{"id":37122210,"url":"https://github.com/stackb/grpc-web","last_synced_at":"2026-01-14T14:04:58.136Z","repository":{"id":57632330,"uuid":"353893516","full_name":"stackb/grpc-web","owner":"stackb","description":"gRPC Web implementation for Golang and TypeScript","archived":false,"fork":true,"pushed_at":"2021-04-02T14:57:30.000Z","size":5463,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-06-20T14:21:37.902Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"improbable-eng/grpc-web","license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stackb.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-04-02T03:25:57.000Z","updated_at":"2021-04-02T03:25:58.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/stackb/grpc-web","commit_stats":null,"previous_names":[],"tags_count":76,"template":false,"template_full_name":null,"purl":"pkg:github/stackb/grpc-web","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackb%2Fgrpc-web","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackb%2Fgrpc-web/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackb%2Fgrpc-web/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackb%2Fgrpc-web/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stackb","download_url":"https://codeload.github.com/stackb/grpc-web/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackb%2Fgrpc-web/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28422405,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T13:30:50.153Z","status":"ssl_error","status_checked_at":"2026-01-14T13:29:08.907Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-14T14:04:57.394Z","updated_at":"2026-01-14T14:04:58.130Z","avatar_url":"https://github.com/stackb.png","language":null,"readme":"# gRPC-Web: Typed Frontend Development\n\n\n[![CircleCI](https://circleci.com/gh/improbable-eng/grpc-web/tree/master.svg?style=svg)](https://circleci.com/gh/improbable-eng/grpc-web/tree/master)\n[![Sauce Test Status](https://app.saucelabs.com/buildstatus/ImprobableEngBot)](https://app.saucelabs.com/u/ImprobableEngBot)\n[![NPM](https://img.shields.io/npm/v/@improbable-eng/grpc-web.svg)](https://www.npmjs.com/package/@improbable-eng/grpc-web)\n[![GoDoc](http://img.shields.io/badge/GoDoc-Reference-blue.svg)](https://godoc.org/github.com/improbable-eng/grpc-web/go/grpcweb) \n[![Apache 2.0 License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)\n[![quality: alpha](https://img.shields.io/badge/quality-alpha-orange.svg)](#status)\n[![Slack](https://img.shields.io/badge/join%20slack-%23grpc--web-brightgreen.svg)](https://join.slack.com/t/improbable-eng/shared_invite/enQtMzQ1ODcyMzQ5MjM4LWY5ZWZmNGM2ODc5MmViNmQ3ZTA3ZTY3NzQwOTBlMTkzZmIxZTIxODk0OWU3YjZhNWVlNDU3MDlkZGViZjhkMjc)\n\n[gRPC](http://www.grpc.io/) is a modern, [HTTP2](https://hpbn.co/http2/)-based protocol, that provides RPC semantics using the strongly-typed *binary* data format of [protocol buffers](https://developers.google.com/protocol-buffers/docs/overview) across multiple languages (C++, C#, Golang, Java, Python, NodeJS, ObjectiveC, etc.)\n\n[gRPC-Web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) is a cutting-edge spec that enables invoking gRPC services from *modern* browsers.\n\n*__If you are looking for gRPC support for Node.js there is an [official Node.js gRPC library](https://www.npmjs.com/package/grpc). This package supports Node.js, but requires that the server has the gRPC-Web compatibility layer (read on to understand more).__*\n\nComponents of the stack are based on Golang and TypeScript:\n\n * [`grpcweb`](./go/grpcweb) - a Go package that wraps an existing `grpc.Server` as a gRPC-Web `http.Handler` for both HTTP2 and HTTP/1.1.\n * [`grpcwebproxy`](./go/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.\n * [`ts-protoc-gen`](https://github.com/improbable-eng/ts-protoc-gen) - a TypeScript plugin for the protocol buffers compiler that provides strongly typed message classes and method definitions.\n * [`@improbable-eng/grpc-web`](./client/grpc-web) - a TypeScript gRPC-Web client library for browsers ([and Node.js](#nodejs-support)).\n \n## Why?\n\nWith 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:\n\n * no more hunting down API documentation - `.proto` is the canonical format for API contracts.\n * no more hand-crafted JSON call objects - all requests and responses are strongly typed and code-generated, with hints available in the IDE.\n * no more dealing with methods, headers, body and low level networking - everything is handled by `grpc.invoke`.\n * no more second-guessing the meaning of error codes - [gRPC status codes](https://godoc.org/google.golang.org/grpc/codes) are a canonical way of representing issues in APIs.\n * 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](https://hpbn.co/http2/#streams-messages-and-frames).\n * no more problems streaming data from a server -  gRPC-Web supports both *1:1* RPCs and *1:many* streaming requests.\n * no more data parse errors when rolling out new binaries - [backwards and forwards-compatibility](https://developers.google.com/protocol-buffers/docs/gotutorial#extending-a-protocol-buffer) of requests and responses.\n\nIn 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.\n\n## Client-side (grpc-web) Docs\n\n**Note: You'll need to add gRPC-Web compatibility to your server through either [`grpcweb`](go/grpcweb) or [`grpcwebproxy`](go/grpcwebproxy).**\n\n[API Docs for `grpc-web` client can be found here](./client/grpc-web)\n\n## Example \n\nFor a self-contained demo of a Golang gRPC service called from a TypeScript project, see [example](client/grpc-web-react-example). It contains most of the initialization code that performs the magic. Here's the application code extracted from the example:\n\nYou use `.proto` files to define your service. In this example, one normal RPC (`GetBook`) and one server-streaming RPC (`QueryBooks`):\n\n```proto\nsyntax = \"proto3\";\n\nmessage Book {\n  int64 isbn = 1;\n  string title = 2;\n  string author = 3;\n}\n\nmessage GetBookRequest {\n  int64 isbn = 1;\n}\n\nmessage QueryBooksRequest {\n  string author_prefix = 1;\n}\n\nservice BookService {\n  rpc GetBook(GetBookRequest) returns (Book) {}\n  rpc QueryBooks(QueryBooksRequest) returns (stream Book) {}\n}\n```\n\nAnd implement it in Go (or any other gRPC-supported language):\n\n```go\nimport pb_library \"../_proto/examplecom/library\"\n\ntype bookService struct{\n        books []*pb_library.Book\n}\n\nfunc (s *bookService) GetBook(ctx context.Context, bookQuery *pb_library.GetBookRequest) (*pb_library.Book, error) {\n\tfor _, book := range s.books {\n\t\tif book.Isbn == bookQuery.Isbn {\n\t\t\treturn book, nil\n\t\t}\n\t}\n\treturn nil, grpc.Errorf(codes.NotFound, \"Book could not be found\")\n}\n\nfunc (s *bookService) QueryBooks(bookQuery *pb_library.QueryBooksRequest, stream pb_library.BookService_QueryBooksServer) error {\n\tfor _, book := range s.books {\n\t\tif strings.HasPrefix(s.book.Author, bookQuery.AuthorPrefix) {\n\t\t\tstream.Send(book)\n\t\t}\n\t}\n\treturn nil\n}\n```\n\nYou will be able to access it in a browser using TypeScript (and equally JavaScript after transpiling):\n\n```javascript\nimport {grpc} from \"@improbable-eng/grpc-web\";\n\n// Import code-generated data structures.\nimport {BookService} from \"../_proto/examplecom/library/book_service_pb_service\";\nimport {QueryBooksRequest, Book, GetBookRequest} from \"../_proto/examplecom/library/book_service_pb\";\n\nconst queryBooksRequest = new QueryBooksRequest();\nqueryBooksRequest.setAuthorPrefix(\"Geor\");\ngrpc.invoke(BookService.QueryBooks, {\n  request: queryBooksRequest,\n  host: \"https://example.com\",\n  onMessage: (message: Book) =\u003e {\n    console.log(\"got book: \", message.toObject());\n  },\n  onEnd: (code: grpc.Code, msg: string | undefined, trailers: grpc.Metadata) =\u003e {\n    if (code == grpc.Code.OK) {\n      console.log(\"all ok\")\n    } else {\n      console.log(\"hit an error\", code, msg, trailers);\n    }\n  }\n});\n```\n\n### Usage with React\n* [Example project using gRPC-Web with React and Go](https://github.com/easyCZ/grpc-web-hacker-news)\n\n## Browser Support\n\nThe `@improbable-eng/grpc-web` client uses multiple techniques to efficiently invoke gRPC services. Most modern browsers support the [Fetch API](https://developer.mozilla.org/en/docs/Web/API/Fetch_API), which allows for efficient reading of partial, binary responses. For older browsers, it automatically falls back to [`XMLHttpRequest`](https://developer.mozilla.org/nl/docs/Web/API/XMLHttpRequest).\n\nThe gRPC semantics encourage you to make multiple requests at once. With most modern browsers [supporting HTTP2](http://caniuse.com/#feat=http2), these can be executed over a single TLS connection. For older browsers, gRPC-Web falls back to HTTP/1.1 chunk responses.\n\nThis library is tested against:\n  * Chrome \u003e= 41\n  * Firefox \u003e= 38\n  * Edge \u003e= 13\n  * IE \u003e= 11\n  * Safari \u003e= 8\n  \n## Node.js Support\n\nThe `@improbable-eng/grpc-web` client also [supports Node.js through a transport](./client/grpc-web/docs/transport.md#node-http-only-available-in-a-nodejs-environment) that uses the `http` and `https` packages. Usage does not vary from browser usage as transport is determined at runtime.\n\nIf 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](https://www.typescriptlang.org/docs/handbook/compiler-options.html)).\n\n```\n{\n  \"compilerOptions\": {\n    \"lib\": [ \"dom\", /* ... */ ],\n  }\n}\n```\n\n*__Please note - There is an [official Node.js gRPC library](https://www.npmjs.com/package/grpc) that does not require the server to support gRPC-Web__*\n\n### Client-side streaming\n\nIt 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](https://www.w3.org/TR/streams-api/) lands in browsers. As such, if you plan on using gRPC-Web you're limited to:\n * unary RPCs (1 request 1 response)\n * server-side streaming RPCs (1 request N responses)\n\nThis, however, is useful for a lot of frontend functionality.\n\n## Status\n\nThe code here is `alpha` quality. It is being used for a subset of Improbable's frontend single-page apps in production.\n\n## Known Limitations\nSee the `@improbable-eng/grpc-web` client Transport Documentation for [a list of Web Browser caveats](./client/grpc-web/docs/transport.md#http/2-based-transports).\n\n### Contributing\nSee [CONTRIBUTING](./CONTRIBUTING.md)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstackb%2Fgrpc-web","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstackb%2Fgrpc-web","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstackb%2Fgrpc-web/lists"}