grpc icon indicating copy to clipboard operation
grpc copied to clipboard

Support gRPC http/json transcoding

Open drowzy opened this issue 3 years ago • 2 comments
trafficstars

Support for gRPC transcoding.

  • Closes #192
  • Closes #274

This feature is opt-in using the http_transcode option in the server definition:

defmodule Helloworld.Greeter.Server do
  use GRPC.Server,
    service: Helloworld.Greeter.Service,
    http_transcode: true

Request/response mapping can be controlled by adding grpc-gateway annotations to your proto definition:

import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto";

package helloworld;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {
    option (google.api.http) = {
      get: "/v1/greeter/{name}"
    };
  }

  rpc SayHelloFrom (HelloRequestFrom) returns (HelloReply) {
    option (google.api.http) = {
      post: "/v1/greeter"
      body: "*"
    };
  }
}

This PR does not require any changes to user code.

Changes

  • [x] Change rpc/3 to rpc/4 to accept options
  • [x] Use routes instead of finding server based on path
  • [x] HttpRule template parsing
    • [x] static segments
    • [x] variables
    • [x] * (match single URL segment)
    • [x] ** (zero or more URL paths, needs to be last part of URL)
    • [x] variable path segments
    • [x] field paths
  • [x] HttpRule spec -> server route
  • [x] JSON request body into request struct
  • [x] Merge bound path params to request struct
  • [x] Merge query string to request struct
  • [x] Use accept header instead of content-type in get requests
  • [x] Map request body using (HttpRule.body)
  • [x] Map response body using (HttpRule.response_body)
  • [x] Allow JSON requests without HttpRule options
  • [x] Change to include http request method in GRPC.Server.__call___ (to differenciate between GET /v1/messages POST /v1/messages)
  • [x] Unary
  • [x] Server streaming (Newline-delimited JSON)
  • [x] gRPC transcode integration test
  • [x] gRPC transcode example
  • [x] Docs

Routing

The path template syntax that can be described using Google.Api.HttpRule can not be expressed using the default :cowboy_router middleware. GRPC.Server.Adapters.Cowboy.Router implements the :cowboy_middleware behaviour and lifts most of its functionality from :cowboy_router with the difference being that it's using GRPC.Service.Router which can build and match Google.Api.HttpRule path templates.

The new routing should be able to match all rules described in the path template syntax:

pattern: /v1/{name=*}
match: /v1/anything
bindings: name="anything"` 

pattern: /v1/{name=messages} 
match: /v1/messages 
bindings: name="messages"

pattern: /v1/{name=messages/*} 
match: /v1/messages/anything 
bindings: name="messages/anything" 

pattern: /v1/{name=messages/**} 
match: /v1/messages/catch/all 
bindings: name="messages/catch/all" 

pattern: /v1/{name=messages/**}/suffix 
match: /v1/messages/catch/all/suffix 
bindings: name="messages/catch/all" 

pattern: /v1/{message.name=messages}/{message.id}
match: /v1/messages/1
bindings: message.name="messages" message.id=1

Of course regular gRPC request paths are also matched i.e POST helloworld.Greeter/SayHello.

drowzy avatar Sep 14 '22 07:09 drowzy

Hi @drowzy any news here ? @polvalente Can this already be merged?

sleipnir avatar Feb 04 '23 23:02 sleipnir

ping @drowzy @polvalente

sleipnir avatar Mar 07 '23 15:03 sleipnir