Skip to content

Commit b7c7297

Browse files
authored
Update README.md (#63)
1 parent 75ec70c commit b7c7297

File tree

1 file changed

+115
-55
lines changed

1 file changed

+115
-55
lines changed

README.md

Lines changed: 115 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,104 @@
11
![](docs/connect-rpc-scala-logo.png)
22

3-
# Connect-RPC ↔ ScalaPB GRPC Bridge
3+
# REST API for GRPC services with Connect protocol / GRPC Transcoding for Scala
44

5-
This library provides a bridge between [Connect](https://connectrpc.com/docs/protocol) protocol and
6-
[ScalaPB](https://scalapb.github.io) GRPC compiler for Scala.
7-
It is inspired and takes ideas from [grpc-json-bridge](https://github.com/avast/grpc-json-bridge) library, which doesn't
8-
seem to be supported anymore + the library doesn't follow a Connect-RPC standard (while being very close to it),
9-
which makes using clients generated with ConnectRPC not possible.
5+
![Maven Central](https://img.shields.io/maven-central/v/io.github.igor-vovk/connect-rpc-scala-core_3?style=flat-square&color=green)
106

11-
Since integration happens on the foundational ScalaPB level, it works with all common GRPC code-generation projects for
12-
Scala:
7+
This library makes it easy to expose your GRPC services to the clients using Connect protocol (with JSON messages),
8+
without Envoy or any other proxy.
139

14-
* [ScalaPB](https://scalapb.github.io) services with `Future` monad
15-
* [fs2-grpc](https://github.com/typelevel/fs2-grpc), built on top of `cats-effect` and `fs2`
16-
* [ZIO gRPC](https://scalapb.github.io/zio-grpc/), built on top of `ZIO`
10+
In essence, a service implementing the following protobuf definition:
1711

18-
*Note*: at the moment, only unary (non-streaming) methods are supported.
12+
```protobuf
13+
syntax = "proto3";
1914
20-
## Motivation
15+
package example;
2116
22-
As a part of a GRPC adoption, there is usually a need to expose REST APIs.
23-
Since GRPC is based on HTTP2, it's not the best option to expose it directly to the clients, which aren’t
24-
natively supporting HTTP2.
25-
So the most common approach is to expose REST APIs, which will be translated to GRPC on the server side.
26-
There are two main protocols for this:
17+
service ExampleService {
18+
rpc GetExample(GetExampleRequest) returns (GetExampleResponse) {
19+
}
20+
}
2721
28-
* [GRPC-WEB](https://github.com/grpc/grpc-web)
29-
* [Connect](https://connectrpc.com/docs/introduction)
22+
message GetExampleRequest {
23+
string id = 1;
24+
}
3025
31-
They are similar, but GRPC-WEB target is to be as close to GRPC as possible, while Connect is more
32-
web-friendly: it has better client libraries, better web semantics:
33-
content-type is `application/json` instead of `application/grpc-web+json`, error codes are just normal http codes
34-
instead of being sent in headers, errors are output in the body of the response JSON-encoded, it supports GET-requests,
35-
etc (you can also read
36-
this [blog post describing why Connect is better](https://buf.build/blog/connect-a-better-grpc)).
26+
message GetExampleResponse {
27+
string name = 1;
28+
}
29+
```
3730

38-
Both protocols support encoding data in Protobuf and JSON.
39-
JSON is more web-friendly, but it requires having some component in the middle, providing JSON → Protobuf
40-
conversion during the request phase and Protobuf → JSON conversion during the response phase.
31+
Will be exposed to the clients as a REST API:
4132

42-
*And this can be tricky to set up*:
33+
```http
34+
POST /example.ExampleService/GetExample HTTP/1.1
35+
Content-Type: application/json
4336
44-
The suggested approach in this case is to use a web-server ([Envoy](https://scalapb.github.io)) as a proxy,
45-
supporting translation of both protocols to GRPC.
46-
The general setup of the Envoy in this case allows proxying HTTP/1.1 requests to GRPC, while still having protobuf
47-
messages in the body of the request.
37+
{
38+
"id": "123"
39+
}
4840
49-
To support JSON, Envoy needs to be configured with Protobuf descriptors, which is not very convenient.
41+
HTTP/1.1 200 OK
5042
51-
*That's where this library comes in*:
43+
{
44+
"name": "example"
45+
}
46+
```
5247

53-
It allows exposing GRPC services, built with [ScalaPB](https://scalapb.github.io), to the clients
54-
using Connect protocol (with JSON messages), without Envoy or any other proxy, so a web service can expose
55-
both GRPC and REST APIs at the same time on two ports.
48+
It is compatible with Connect protocol clients (e.g., you can generate clients with [Connect RPC](https://connectrpc.com) `protoc` and
49+
`buf` plugins instead of writing requests manually).
5650

57-
This simplifies overall setup: simpler CI, fewer network components, faster execution speed.
51+
In addition, the library supports creating free-form REST APIs,
52+
using [GRPC Transcoding](https://cloud.google.com/endpoints/docs/grpc/transcoding) approach
53+
(full support of `google.api.http` annotations is in progress).:
5854

59-
## Features of the protocol supported by the library
55+
```protobuf
56+
syntax = "proto3";
6057
61-
```yaml
62-
versions: [ HTTP_VERSION_1, HTTP_VERSION_2 ]
63-
protocols: [ PROTOCOL_CONNECT ]
64-
codecs: [ CODEC_JSON, CODEC_PROTO ]
65-
stream_types: [ STREAM_TYPE_UNARY ]
66-
supports_tls: false
67-
supports_trailers: false
68-
supports_connect_get: true
69-
supports_message_receive_limit: false
58+
package example;
59+
60+
import "google/api/annotations.proto";
61+
62+
service ExampleService {
63+
rpc GetExample(GetExampleRequest) returns (GetExampleResponse) {
64+
option (google.api.http) = {
65+
get: "/example/{id}"
66+
};
67+
}
68+
}
69+
70+
message GetExampleRequest {
71+
string id = 1;
72+
}
73+
74+
message GetExampleResponse {
75+
string name = 1;
76+
}
77+
```
78+
79+
In addition to the previous way of calling it, this endpoint will be exposed as a REST API:
80+
81+
```http
82+
GET /example/123 HTTP/1.1
83+
84+
HTTP/1.1 200 OK
85+
86+
{
87+
"name": "example"
88+
}
7089
```
7190

91+
Since integration happens on the foundational ScalaPB level, it works with all common GRPC code-generators:
92+
93+
* [ScalaPB](https://scalapb.github.io) services with `Future` monad
94+
* [fs2-grpc](https://github.com/typelevel/fs2-grpc), built on top of `cats-effect` and `fs2`
95+
* [ZIO gRPC](https://scalapb.github.io/zio-grpc/), built on top of `ZIO`
96+
97+
*Note*: at the moment, only unary (non-streaming) methods are supported.
98+
7299
## Usage
73100

74-
Installing with SBT (you also need to install particular `http4s` server implementation):
101+
For SBT (you also need to install particular `http4s` server implementation):
75102

76103
```scala
77104
libraryDependencies ++= Seq(
@@ -138,7 +165,9 @@ You can read [this](https://zio.dev/guides/interop/with-cats-effect/).
138165

139166
## Development
140167

141-
### Running Connect-RPC conformance tests
168+
### Connect RPC
169+
170+
#### Running Connect-RPC conformance tests
142171

143172
Run the following command to run Connect-RPC conformance tests:
144173

@@ -149,7 +178,7 @@ docker build . --output "out" --progress=plain
149178
Execution results are output to STDOUT.
150179
Diagnostic data from the server itself is written to the log file `out/out.log`.
151180

152-
### Connect protocol conformance tests status
181+
#### Connect protocol conformance tests status
153182

154183
✅ JSON codec conformance status: __full conformance__.
155184

@@ -159,9 +188,40 @@ Known issues:
159188

160189
* Errors serialized incorrectly for protobuf codec.
161190

162-
## Future improvements
191+
#### Supported features of the protocol
192+
193+
```yaml
194+
versions: [ HTTP_VERSION_1, HTTP_VERSION_2 ]
195+
protocols: [ PROTOCOL_CONNECT ]
196+
codecs: [ CODEC_JSON, CODEC_PROTO ]
197+
stream_types: [ STREAM_TYPE_UNARY ]
198+
supports_tls: false
199+
supports_trailers: false
200+
supports_connect_get: true
201+
supports_message_receive_limit: false
202+
```
203+
204+
### GRPC Transcoding
205+
206+
#### Support
207+
208+
- [x] GET, POST, PUT, DELETE, PATCH methods
209+
- [x] Path parameters, e.g., `/v1/countries/{name}`
210+
- [x] Query parameters, repeating query parameters (e.g., `?a=1&a=2`) as arrays
211+
- [x] Request body (JSON)
212+
- [ ] Body field mapping, e.g. `body: "request"` (not supported yet), `body: "*"` (supported)
213+
- [ ] Path suffixes, e.g., `/v1/{name=projects/*/locations/*}/datasets` (not supported yet)
214+
215+
### Future improvements
163216

164217
- [x] Support GET-requests ([#10](https://github.com/igor-vovk/connect-rpc-scala/issues/10))
165-
- [ ] Support `google.api.http` annotations (GRPC transcoding) ([#51](https://github.com/igor-vovk/connect-rpc-scala/issues/51))
218+
- [x] Support `google.api.http` annotations (GRPC
219+
transcoding) ([#51](https://github.com/igor-vovk/connect-rpc-scala/issues/51))
166220
- [ ] Support configurable timeouts
167221
- [ ] Support non-unary (streaming) methods
222+
223+
### Thanks
224+
225+
The library is inspired and takes some ideas from the [grpc-json-bridge](https://github.com/avast/grpc-json-bridge).
226+
Which doesn't seem to be supported anymore, + also the library doesn't follow a Connect-RPC standard (while being very
227+
close to it).

0 commit comments

Comments
 (0)