{"id":13552723,"url":"https://github.com/elixir-grpc/grpc","last_synced_at":"2025-05-12T15:38:04.461Z","repository":{"id":10881614,"uuid":"63799837","full_name":"elixir-grpc/grpc","owner":"elixir-grpc","description":"An Elixir implementation of gRPC","archived":false,"fork":false,"pushed_at":"2025-03-21T12:28:47.000Z","size":3727,"stargazers_count":1429,"open_issues_count":51,"forks_count":219,"subscribers_count":30,"default_branch":"master","last_synced_at":"2025-04-18T16:33:37.273Z","etag":null,"topics":["elixir","google-protocol-buffers","grpc","grpc-elixir","http2","proto","protobuf","rpc"],"latest_commit_sha":null,"homepage":"https://hex.pm/packages/grpc","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/elixir-grpc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-07-20T17:12:07.000Z","updated_at":"2025-04-08T03:49:55.000Z","dependencies_parsed_at":"2024-04-08T02:37:18.390Z","dependency_job_id":"df34c34a-c581-4be8-bc92-29d160c6772b","html_url":"https://github.com/elixir-grpc/grpc","commit_stats":{"total_commits":491,"total_committers":63,"mean_commits":"7.7936507936507935","dds":0.3360488798370672,"last_synced_commit":"c26acb9157d00cd59b3adfa01fcde89806864e99"},"previous_names":["tony612/grpc-elixir"],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-grpc%2Fgrpc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-grpc%2Fgrpc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-grpc%2Fgrpc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-grpc%2Fgrpc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/elixir-grpc","download_url":"https://codeload.github.com/elixir-grpc/grpc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250478462,"owners_count":21437173,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["elixir","google-protocol-buffers","grpc","grpc-elixir","http2","proto","protobuf","rpc"],"created_at":"2024-08-01T12:02:08.525Z","updated_at":"2025-05-12T15:38:04.448Z","avatar_url":"https://github.com/elixir-grpc.png","language":"Elixir","funding_links":[],"categories":["Elixir"],"sub_categories":[],"readme":"# gRPC Elixir\n\n[![GitHub CI](https://github.com/elixir-grpc/grpc/actions/workflows/ci.yml/badge.svg)](https://github.com/elixir-grpc/grpc/actions/workflows/ci.yml)\n[![Hex.pm](https://img.shields.io/hexpm/v/grpc.svg)](https://hex.pm/packages/grpc)\n[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/grpc/)\n[![License](https://img.shields.io/hexpm/l/grpc.svg)](https://github.com/elixir-grpc/grpc/blob/master/LICENSE.md)\n[![Total Download](https://img.shields.io/hexpm/dt/grpc.svg)](https://hex.pm/packages/elixir-grpc/grpc)\n[![Last Updated](https://img.shields.io/github/last-commit/elixir-grpc/grpc.svg)](https://github.com/elixir-grpc/grpc/commits/master)\n\nAn Elixir implementation of [gRPC](http://www.grpc.io/).\n\n## Table of contents\n\n- [Installation](#installation)\n- [Usage](#usage)\n  - [Simple RPC](#simple-rpc)\n  - [HTTP Transcoding](#http-transcoding)\n  - [CORS](#cors)\n  - [Start Application](#start-application)\n- [Features](#features)\n- [Benchmark](#benchmark)\n- [Contributing](#contributing)\n\n## Installation\n\nThe package can be installed as:\n\n```elixir\ndef deps do\n  [\n    {:grpc, \"~\u003e 0.10\"}\n  ]\nend\n```\n\n## Usage\n\n1. Write your protobuf file:\n\n```protobuf\nsyntax = \"proto3\";\n\npackage helloworld;\n\n// The request message containing the user's name.\nmessage HelloRequest {\n  string name = 1;\n}\n\n// The response message containing the greeting\nmessage HelloReply {\n  string message = 1;\n}\n\n// The greeting service definition.\nservice Greeter {\n  // Greeting function\n  rpc SayHello (HelloRequest) returns (HelloReply) {}\n}\n\n```\n\n2. Then generate Elixir code from proto file as [protobuf-elixir](https://github.com/elixir-protobuf/protobuf#usage):\n\n```shell\nprotoc --elixir_out=plugins=grpc:./lib -I./priv/protos helloworld.proto\n```\n\nIn the following sections you will see how to implement gRPC server logic.\n\n### **Simple RPC**\n\n1. Implement the server side code like below and remember to return the expected message types.\n\n```elixir\ndefmodule Helloworld.Greeter.Server do\n  use GRPC.Server, service: Helloworld.Greeter.Service\n\n  @spec say_hello(Helloworld.HelloRequest.t, GRPC.Server.Stream.t) :: Helloworld.HelloReply.t\n  def say_hello(request, _stream) do\n    Helloworld.HelloReply.new(message: \"Hello #{request.name}\")\n  end\nend\n```\n\n2. Define gRPC endpoints\n\n```elixir\n# Define your endpoint\ndefmodule Helloworld.Endpoint do\n  use GRPC.Endpoint\n\n  intercept GRPC.Server.Interceptors.Logger\n  run Helloworld.Greeter.Server\nend\n```\n\nWe will use this module [in the gRPC server startup section](#start-application).\n\n**Note:** For other types of RPC call like streams see [here](interop/lib/interop/server.ex).\n\n### **HTTP Transcoding**\n\n1. Adding [grpc-gateway annotations](https://cloud.google.com/endpoints/docs/grpc/transcoding) to your protobuf file definition:\n\n```protobuf\nimport \"google/api/annotations.proto\";\nimport \"google/protobuf/timestamp.proto\";\n\npackage helloworld;\n\n// The greeting service definition.\nservice Greeter {\n  // Sends a greeting\n  rpc SayHello (HelloRequest) returns (HelloReply) {\n    option (google.api.http) = {\n      get: \"/v1/greeter/{name}\"\n    };\n  }\n\n  rpc SayHelloFrom (HelloRequestFrom) returns (HelloReply) {\n    option (google.api.http) = {\n      post: \"/v1/greeter\"\n      body: \"*\"\n    };\n  }\n}\n```\n\n2. Add protoc plugin dependency and compile your protos using [protobuf_generate](https://github.com/drowzy/protobuf_generate) hex [package](https://hex.pm/packages/protobuf_generate):\n\nIn mix.exs:\n\n```elixir\ndef deps do\n  [\n    {:grpc, \"~\u003e 0.7\"},\n    {:protobuf_generate, \"~\u003e 0.1.1\"}\n  ]\nend\n```\n\nAnd in your terminal:\n\n```shell\nmix protobuf.generate \\\n  --include-path=priv/proto \\\n  --include-path=deps/googleapis \\\n  --generate-descriptors=true \\\n  --output-path=./lib \\\n  --plugins=ProtobufGenerate.Plugins.GRPCWithOptions \\\n  google/api/annotations.proto google/api/http.proto helloworld.proto\n```\n\n3. Enable http_transcode option in your Server module\n\n```elixir\ndefmodule Helloworld.Greeter.Server do\n  use GRPC.Server,\n    service: Helloworld.Greeter.Service,\n    http_transcode: true\n\n  @spec say_hello(Helloworld.HelloRequest.t, GRPC.Server.Stream.t) :: Helloworld.HelloReply.t\n  def say_hello(request, _stream) do\n    %Helloworld.HelloReply{message: \"Hello #{request.name}\"}\n  end\nend\n```\n\nSee full application code in [helloworld_transcoding](examples/helloworld_transcoding) example.\n\n### **CORS**\n\nWhen accessing gRPC from a browser via HTTP transcoding or gRPC-Web, CORS headers may be required for the browser to allow access to the gRPC endpoint. Adding CORS headers can be done by using `GRPC.Server.Interceptors.CORS` as an interceptor in your `GRPC.Endpoint` module, configuring it as decribed in the module documentation:\n\nExample:\n\n```elixir\n# Define your endpoint\ndefmodule Helloworld.Endpoint do\n  use GRPC.Endpoint\n\n  intercept GRPC.Server.Interceptors.Logger\n  intercept GRPC.Server.Interceptors.CORS, allow_origin: \"mydomain.io\"\n  run Helloworld.Greeter.Server\nend\n```\n\n### **Start Application**\n\n1. Start gRPC Server in your supervisor tree or Application module:\n\n```elixir\n# In the start function of your Application\ndefmodule HelloworldApp do\n  use Application\n  def start(_type, _args) do\n    children = [\n      # ...\n      {GRPC.Server.Supervisor, endpoint: Helloworld.Endpoint, port: 50051, start_server: true}\n    ]\n\n    opts = [strategy: :one_for_one, name: YourApp]\n    Supervisor.start_link(children, opts)\n  end\nend\n```\n\n2. Call rpc:\n\n```elixir\niex\u003e {:ok, channel} = GRPC.Stub.connect(\"localhost:50051\")\niex\u003e request = Helloworld.HelloRequest.new(name: \"grpc-elixir\")\niex\u003e {:ok, reply} = channel |\u003e Helloworld.Greeter.Stub.say_hello(request)\n\n# With interceptors\niex\u003e {:ok, channel} = GRPC.Stub.connect(\"localhost:50051\", interceptors: [GRPC.Client.Interceptors.Logger])\n...\n```\n\nCheck the [examples](examples) and [interop](interop) directories in the project's source code for some examples.\n\n## Client Adapter and Configuration\n\nThe default adapter used by `GRPC.Stub.connect/2` is `GRPC.Client.Adapter.Gun`. Another option is to use `GRPC.Client.Adapters.Mint` instead, like so:\n\n```elixir\nGRPC.Stub.connect(\"localhost:50051\",\n  # Use Mint adapter instead of default Gun\n  adapter: GRPC.Client.Adapters.Mint\n)\n```\n\nThe `GRPC.Client.Adapters.Mint` adapter accepts custom configuration. To do so, you can configure it from your mix application via:\n\n```elixir\n# File: your application's config file.\nconfig :grpc, GRPC.Client.Adapters.Mint, custom_opts\n```\n\nThe accepted options for configuration are the ones listed on [Mint.HTTP.connect/4](https://hexdocs.pm/mint/Mint.HTTP.html#connect/4-options)\n\n## Features\n\n- Various kinds of RPC:\n  - [Unary](https://grpc.io/docs/what-is-grpc/core-concepts/#unary-rpc)\n  - [Server-streaming](https://grpc.io/docs/what-is-grpc/core-concepts/#server-streaming-rpc)\n  - [Client-streaming](https://grpc.io/docs/what-is-grpc/core-concepts/#client-streaming-rpc)\n  - [Bidirectional-streaming](https://grpc.io/docs/what-is-grpc/core-concepts/#bidirectional-streaming-rpc)\n- [HTTP Transcoding](https://cloud.google.com/endpoints/docs/grpc/transcoding)\n- [TLS Authentication](https://grpc.io/docs/guides/auth/#supported-auth-mechanisms)\n- [Error handling](https://grpc.io/docs/guides/error/)\n- [Interceptors](`GRPC.Endpoint`)\n- [Connection Backoff](https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md)\n- Data compression\n- [gRPC Reflection](https://github.com/elixir-grpc/grpc-reflection)\n\n## Benchmark\n\n1. [Simple benchmark](examples/helloworld/README.md#Benchmark) by using [ghz](https://ghz.sh/)\n\n2. [Benchmark](benchmark) followed by official spec\n\n## Contributing\n\nYour contributions are welcome!\n\nPlease open issues if you have questions, problems and ideas. You can create pull\nrequests directly if you want to fix little bugs, add small features and so on.\nBut you'd better use issues first if you want to add a big feature or change a\nlot of code.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felixir-grpc%2Fgrpc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felixir-grpc%2Fgrpc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felixir-grpc%2Fgrpc/lists"}