api - 将 HTTP 转码为 gRPC:具有不同参数的相同端点
问题描述
我已经有一个正在运行的 gRPC 项目。我正在寻找构建一个能够执行一些 HTTP 请求的 API。
我有以下两种类型:
message FindRequest {
ModelType model_type = 1;
oneof by {
string id = 2;
string name = 3;
}
}
message GetAllRequest {
ModelType model_type = 1;
int32 page_size = 2;
oneof paging {
int32 page = 3;
bool skip_paging = 4;
}
}
然后,我想要这两个端点:
// Get a data set by ID or name. Returns an empty data set if there is no such
// data set in the database. If there are multiple data sets with the same
// name in the database it returns the first of these data sets.
rpc Find(FindRequest) returns (DataSet){
option (google.api.http) = { get: "/datasets" };
}
// Get (a page of) all data sets of a given type. If no page size is given
// (page <= 0) it defaults to 100. An unset page (page <= 0) defaults to the
// first page.
rpc GetAll(GetAllRequest) returns (GetAllResponse){
option (google.api.http) = { get: "/datasets" };
}
对我来说,有两个同名的不同端点是有意义的,但参数不同。例如,请求/datasets?model-type=XXX
应该映射到GetAll
函数,而请求/datasets?model-type=XXX&name=YYY
应该映射到Find
函数。但是,它不起作用,因为我猜映射失败,所以这些端点都没有返回任何东西。
我认为使映射工作的解决方案是强制参数是必需的,但是,我正在使用proto3
,这不允许该required
字段。
那么,我如何能够使用 proto3 拥有 2 个名称相同但参数不同的端点?
我知道如果我使用不同的端点名称,它可以工作,例如findRequest
,我可以有以下端点:/findDatasets
,但关于 API 命名约定的最佳实践,这是不可取的,或者是吗?
解决方案
解决这个问题的常规方法是使用不同的方法。我的直觉是,尝试使用请求字符串中的字段进行区分是一种反模式。
service YourService {
rpc FindSomething(FindSomethingRequest) returns (FindSomethingResponse){
option (google.api.http) = { get: "/something/find" };
}
rpc ListSomething(ListSomethingRequest) returns (ListSomethingResponse){
option (google.api.http) = { get: "/something/list" };
}
}
message FindSomethingRequest {
ModelType model_type = 1;
string id = 2;
string name = 3;
}
message ListSomethingRequest {
int32 page_size = 2;
int32 page_token = 3;
}
message ListSomethingResponse {
repeated ModelType model_types = 1;
int32 page_size = 2;
int32 next_page_token = 3;
}
我不确定您的底层事物结构,但是,我认为更好的做法是使用所有可能的属性对事物进行建模并允许保留一些未设置(例如,其中一个id
或name
可能两者都在FindSomethingRequest
),而不是为所有可能的查询创建不同的消息类型。你为事物建模,而不是你如何与之交互。
在您的实现(!)中FindSomething
,您将处理消息用户如何构造字段的排列。可能会报告一个错误“要么是id
要么name
是必需的”。
我认为ListSomething
's 的消息也可以更简单。您请求 (ModelTypes) 的列表并给出一个page_size
和一个page_token
(可能是""
)。它返回一个ModelType
s 列表、返回页面的大小(可能小于请求的大小)以及 anext_page_token
如果有更多数据,您可以使用它来发出下一个ListSomething
请求。
推荐阅读
- ruby-on-rails - 有没有办法在 Rails 的单个查询中进行多次插入?
- log4j - log4j 属性文件未在 Eclipse 中更新
- php - Zf3 在 OnBootrstap() Module.php 中获取自定义服务实例 - 获取 ServiceNotFoundException 致命错误
- swift - Swift - API 返回包含不同类型的数组
- python - Python:我的代码做错了什么?
- html - 如何检测水龙头?
- java - 在Java中,我可以让父类实现一个使用子类变量的方法吗?
- three.js - ThreeJS:如果我改变它的位置,网格就会消失
- javascript - 手风琴在我的 HTML 页面中没有按预期工作
- python - 为什么这个积分如此难以近似?