|
19 | 19 | - [Bidirectional Streaming](#bidirectional-streaming) |
20 | 20 | - [Application Startup](#application-startup) |
21 | 21 | - [Client Usage](#client-usage) |
| 22 | + - [Basic Connection and RPC](#basic-connection-and-rpc) |
| 23 | + - [Using Interceptors](#using-interceptors) |
| 24 | + - [Target Schemes and Resolvers](#target-schemes-and-resolvers) |
| 25 | + - [Supported formats](#supported-formats) |
| 26 | + - [Example (DNS)](#example-dns) |
| 27 | + - [Example (Unix socket)](#example-unix-socket) |
| 28 | + - [Compression and Metadata](#compression-and-metadata) |
| 29 | + - [Client Adapters](#client-adapters) |
| 30 | + - [Using Mint Adapter](#using-mint-adapter) |
22 | 31 | - [HTTP Transcoding](#http-transcoding) |
23 | 32 | - [CORS](#cors) |
24 | 33 | - [Features](#features) |
@@ -78,6 +87,8 @@ protoc --elixir_out=plugins=grpc:./lib -I./priv/protos helloworld.proto |
78 | 87 |
|
79 | 88 | All RPC calls must be implemented using the stream-based API, even for unary requests. |
80 | 89 |
|
| 90 | +>__NOTE__: The old API was deprecated based on `GRPC.Server.send_reply/2` and direct `struct` returns was deprecated as of version `0.10.x`. |
| 91 | +
|
81 | 92 | ### Unary RPC using Stream API |
82 | 93 |
|
83 | 94 | ```elixir |
@@ -133,7 +144,10 @@ def say_bid_stream_hello(request, materializer) do |
133 | 144 | |> GRPC.Stream.run_with(materializer) |
134 | 145 | end |
135 | 146 | ``` |
136 | | -__💡__ The Stream API supports composable stream transformations via `ask`, `map`, `run` and others functions, enabling clean and declarative stream pipelines. For a complete list of available operators see [here](lib/grpc/stream.ex). |
| 147 | + |
| 148 | +The Stream API supports composable stream transformations via `ask`, `map`, `run` and other functions, enabling clean and declarative stream pipelines. For a complete list of available operators and detailed documentation, see [`GRPC.Stream`](lib/grpc/stream.ex). |
| 149 | + |
| 150 | +--- |
137 | 151 |
|
138 | 152 | ## Application Startup |
139 | 153 |
|
@@ -166,38 +180,106 @@ end |
166 | 180 |
|
167 | 181 | # Client Usage |
168 | 182 |
|
| 183 | +This section demonstrates how to establish client connections and perform RPC calls using the Elixir gRPC client. |
| 184 | + |
| 185 | +--- |
| 186 | + |
| 187 | +## Basic Connection and RPC |
| 188 | + |
169 | 189 | ```elixir |
170 | 190 | iex> {:ok, channel} = GRPC.Stub.connect("localhost:50051") |
171 | 191 | iex> request = Helloworld.HelloRequest.new(name: "grpc-elixir") |
172 | 192 | iex> {:ok, reply} = channel |> Helloworld.GreetingServer.Stub.say_unary_hello(request) |
| 193 | +``` |
| 194 | + |
| 195 | +--- |
| 196 | + |
| 197 | +## Using Interceptors |
| 198 | + |
| 199 | +Client interceptors allow you to add logic to the request/response lifecycle, such as logging, tracing, or authentication. |
| 200 | + |
| 201 | +```elixir |
| 202 | +iex> {:ok, channel} = |
| 203 | +...> GRPC.Stub.connect("localhost:50051", |
| 204 | +...> interceptors: [GRPC.Client.Interceptors.Logger] |
| 205 | +...> ) |
| 206 | +iex> request = Helloworld.HelloRequest.new(name: "Alice") |
| 207 | +iex> {:ok, reply} = channel |> Helloworld.GreetingServer.Stub.say_unary_hello(request) |
| 208 | +``` |
| 209 | + |
| 210 | +--- |
| 211 | + |
| 212 | +## Target Schemes and Resolvers |
173 | 213 |
|
174 | | -# With interceptors |
175 | | -iex> {:ok, channel} = GRPC.Stub.connect("localhost:50051", interceptors: [GRPC.Client.Interceptors.Logger]) |
176 | | -... |
| 214 | +The `connect/2` function supports URI-like targets that are resolved via the internal **gRPC** [Resolver](lib/grpc/client/resolver.ex). |
| 215 | +You can connect using `DNS`, `Unix Domain sockets`, `IPv4/IPv6`, or even `xDS-based endpoints`. |
| 216 | + |
| 217 | +### Supported formats: |
| 218 | + |
| 219 | +| Scheme | Example | Description | |
| 220 | +|:----------|:----------------------------|:---------------------------------------------| |
| 221 | +| `dns://` | `"dns://example.com:50051"` | Resolves via DNS `A/AAAA` records | |
| 222 | +| `ipv4:` | `"ipv4:10.0.0.5:50051"` | Connects directly to an IPv4 address | |
| 223 | +| `unix:` | `"unix:/tmp/service.sock"` | Connects via a Unix domain socket | |
| 224 | +| `xds:///` | `"xds:///my-service"` | Resolves via xDS control plane (Envoy/Istio) | |
| 225 | +| none | `"127.0.0.1:50051"` | Implicit DNS (default port `50051`) | |
| 226 | + |
| 227 | +### Example (DNS): |
| 228 | + |
| 229 | +```elixir |
| 230 | +iex> {:ok, channel} = GRPC.Stub.connect("dns://orders.prod.svc.cluster.local:50051") |
| 231 | +iex> request = Orders.GetOrderRequest.new(id: "123") |
| 232 | +iex> {:ok, reply} = channel |> Orders.OrderService.Stub.get_order(request) |
| 233 | +``` |
| 234 | + |
| 235 | +### Example (Unix socket): |
| 236 | + |
| 237 | +```elixir |
| 238 | +iex> {:ok, channel} = GRPC.Stub.connect("unix:/tmp/my.sock") |
| 239 | +``` |
| 240 | + |
| 241 | +>__NOTE__: When using `DNS` or `xDS` targets, the connection layer periodically refreshes endpoints. |
| 242 | +--- |
| 243 | + |
| 244 | +## Compression and Metadata |
| 245 | + |
| 246 | +You can specify message compression and attach default headers to all requests. |
| 247 | + |
| 248 | +```elixir |
| 249 | +iex> {:ok, channel} = |
| 250 | +...> GRPC.Stub.connect("localhost:50051", |
| 251 | +...> compressor: GRPC.Compressor.Gzip, |
| 252 | +...> headers: [{"authorization", "Bearer my-token"}] |
| 253 | +...> ) |
177 | 254 | ``` |
178 | 255 |
|
179 | | -Check the [examples](examples) and [interop](interop) directories in the project's source code for some examples. |
| 256 | +--- |
| 257 | + |
| 258 | +## Client Adapters |
180 | 259 |
|
181 | | -## Client Adapter and Configuration |
| 260 | +By default, `GRPC.Stub.connect/2` uses the **Gun** adapter. |
| 261 | +You can switch to **Mint** (pure Elixir HTTP/2) or other adapters as needed. |
182 | 262 |
|
183 | | -The 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: |
| 263 | +### Using Mint Adapter |
184 | 264 |
|
185 | 265 | ```elixir |
186 | | -GRPC.Stub.connect("localhost:50051", |
187 | | - # Use Mint adapter instead of default Gun |
188 | | - adapter: GRPC.Client.Adapters.Mint |
189 | | -) |
| 266 | +iex> GRPC.Stub.connect("localhost:50051", |
| 267 | +...> adapter: GRPC.Client.Adapters.Mint |
| 268 | +...> ) |
190 | 269 | ``` |
191 | 270 |
|
192 | | -The `GRPC.Client.Adapters.Mint` adapter accepts custom configuration. To do so, you can configure it from your mix application via: |
| 271 | +You can configure adapter options globally via your application’s config: |
193 | 272 |
|
194 | 273 | ```elixir |
195 | | -# File: your application's config file. |
196 | | -config :grpc, GRPC.Client.Adapters.Mint, custom_opts |
| 274 | +# File: config/config.exs |
| 275 | +config :grpc, GRPC.Client.Adapters.Mint, |
| 276 | + timeout: 10_000, |
| 277 | + transport_opts: [cacertfile: "/etc/ssl/certs/ca-certificates.crt"] |
197 | 278 | ``` |
198 | 279 |
|
199 | | -The accepted options for configuration are the ones listed on [Mint.HTTP.connect/4](https://hexdocs.pm/mint/Mint.HTTP.html#connect/4-options) |
| 280 | +The accepted options are the same as [`Mint.HTTP.connect/4`](https://hexdocs.pm/mint/Mint.HTTP.html#connect/4-options). |
200 | 281 |
|
| 282 | +--- |
201 | 283 |
|
202 | 284 | ### **HTTP Transcoding** |
203 | 285 |
|
@@ -264,7 +346,7 @@ defmodule Helloworld.Greeter.Server do |
264 | 346 | end |
265 | 347 | ``` |
266 | 348 |
|
267 | | -See full application code in [helloworld_transcoding](examples/helloworld_transcoding) example. |
| 349 | +See full application code in [helloworld_transcoding](https://github.com/elixir-grpc/tree/master/examples/helloworld_transcoding) example. |
268 | 350 |
|
269 | 351 | ### **CORS** |
270 | 352 |
|
|
300 | 382 |
|
301 | 383 | ## Benchmark |
302 | 384 |
|
303 | | -1. [Simple benchmark](examples/helloworld/README.md#Benchmark) by using [ghz](https://ghz.sh/) |
| 385 | +1. [Simple benchmark](https://github.com/elixir-grpc/tree/master/examples/helloworld/README.md#Benchmark) by using [ghz](https://ghz.sh/) |
304 | 386 |
|
305 | | -2. [Benchmark](benchmark) followed by official spec |
| 387 | +2. [Benchmark](https://github.com/elixir-grpc/tree/master/benchmark) followed by official spec |
306 | 388 |
|
307 | 389 | ## Contributing |
308 | 390 |
|
|
0 commit comments