Http
定义api服务的http配置。它包含一个httprule列表,每个列表指定一个rpc方法到一个或多个http rest api方法的映射。
字段 | 描述 |
---|---|
rules[] | HttpRule, 一个适用于各个API方法的http配置规则列表。注意:所有服务配置规则都遵循“最后一个配置赢”规则。 |
fully_decode_reserved_expansion | bool, 当设置为true时,除了保留扩展中的单个段匹配的情况下,url路径参数将完全进行url解码,其中“%2f”将保留编码。默认行为是不解码多段匹配中的rfc 6570保留字符。 |
URL特殊符号编码
有些符号在URL中是不能直接传递的,如果要在URL中传递这些特殊符号,那么就要使用他们的编码。
编码的格式为:%加字符的ASCII码,即一个百分号%,后面跟对应字符的ASCII(16进制)码值。例如: 空格的编码值是”%20”。
如果不使用转义字符,这些编码就会当URL中定义的特殊字符处理。
URL特殊符号 | 含义 | 编码十六进制值 |
---|---|---|
+ | 空格 | %2B |
空格 | 空格可以用+号或者编码%20 | %20 |
/ | 分隔目录和子目录 | %2F |
? | 分隔实际的 URL 和参数 | %3F |
% | 指定特殊字符 | %25 |
# | 表示书签 | %23 |
& | 指定的参数间的分隔符 | %26 |
= | 指定参数的值 | %3D |
HttpRule
httprule定义了一个rpc方法到一个或多个http rest API方法的映射。映射指定rpc请求消息的不同部分如何映射到url路径,url查询参数和http请求主体。通常可在rpc方法中指定google.api.http
注释来表示该映射,有关详细信息,请参阅“google/api/annotations.proto”。
该映射由指定路径模板和方法类型的字段组成。路径模板可以引用请求消息中的字段,如下面的示例中描述对消息资源集合的REST GET
操作:
service Messaging {
rpc GetMessage(GetMessageRequest) returns (Message) {
option (google.api.http).get = "/v1/messages/{message_id}/{sub.subfield}";
}
}
message GetMessageRequest {
message SubMessage {
string subfield = 1;
}
string message_id = 1; // mapped to the URL
SubMessage sub = 2; // `sub.subfield` is url-mapped
}
message Message {
string text = 1; // content of the resource
}
也可以在GRPC API Configuration yaml文件中表达相同的http注释。
http:
rules:
- selector: <proto_package_name>.Messaging.GetMessage
get: /v1/messages/{message_id}/{sub.subfield}
这个定义启用了http json到rpc的自动,双向映射。例:
HTTP | RPC |
---|---|
GET /v1/messages/123456/foo | GetMessage(message_id: “123456” sub: SubMessage(subfield: “foo”)) |
通常,不仅可以从路径模式中引用字段,还可以引用字段路径。映射到路径模式的字段不能重复,并且必须具有原始(非消息)类型。
请求消息中未被路径模式绑定的任何字段自动成为(可选)http查询参数。
假定请求消息的以下定义:
service Messaging {
rpc GetMessage(GetMessageRequest) returns (Message) {
option (google.api.http).get = "/v1/messages/{message_id}";
}
}
message GetMessageRequest {
message SubMessage {
string subfield = 1;
}
string message_id = 1; // mapped to the URL
int64 revision = 2; // becomes a parameter
SubMessage sub = 3; // `sub.subfield` becomes a parameter
}
这使得http json到rpc的映射如下:
HTTP | RPC |
---|---|
GET /v1/messages/123456?revision=2&sub.subfield=foo | GetMessage(message_id: “123456” revision: 2 sub: SubMessage(subfield: “foo”)) |
请注意,映射到http参数的字段必须具有基元类型或重复基元类型。消息类型是不允许的。在重复类型的情况下,该参数可以在url中重复,如...?param=a&param=b
。
对于允许请求主体的http方法种类,body
字段可以在映射中指定。考虑在消息资源集合上的REST Update
方法:
service Messaging {
rpc UpdateMessage(UpdateMessageRequest) returns (Message) {
option (google.api.http) = {
put: "/v1/messages/{message_id}"
body: "message"
};
}
}
message UpdateMessageRequest {
string message_id = 1; // mapped to the URL
Message message = 2; // mapped to the body
}
下面的http json到rpc映射被启用,其中请求主体中json的表示由protos json编码确定:
HTTP | RPC |
---|---|
PUT /v1/messages/123456 { “text”: “Hi!” } | UpdateMessage(message_id: “123456” message { text: “Hi!” }) |
可以在主体映射中使用特殊名称*
来定义未被路径模板限制的每个字段都应映射到请求主体。这使更新方法的以下备选定义成为可能:
service Messaging {
rpc UpdateMessage(Message) returns (Message) {
option (google.api.http) = {
put: "/v1/messages/{message_id}"
body: "*"
};
}
}
message Message {
string message_id = 1;
string text = 2;
}
下面的http json到rpc映射被启用:
HTTP | RPC |
---|---|
PUT /v1/messages/123456 { “text”: “Hi!” } | UpdateMessage(message_id: “123456” text: “Hi!”) |
请注意,在正文映射中使用*
时,不可能使用http参数,因为所有未在路径上绑定的字段都在body中。这使得这个选项很少被用于定义REST apis的实践。*
的常见用法是在自定义方法中根本不会使用url参数来传输数据。
可以使用additional_bindings
选项为一个rpc定义多个http方法。例:
service Messaging {
rpc GetMessage(GetMessageRequest) returns (Message) {
option (google.api.http) = {
get: "/v1/messages/{message_id}"
additional_bindings {
get: "/v1/users/{user_id}/messages/{message_id}"
}
};
}
}
message GetMessageRequest {
string message_id = 1;
string user_id = 2;
}
这使得以下两种替代http json到rpc映射成为可能:
HTTP | RPC |
---|---|
GET /v1/messages/123456 | GetMessage(message_id: “123456”) |
GET /v1/users/me/messages/123456 | GetMessage(user_id: “me” message_id: “123456”) |
http映射规则
将http路径,查询参数和主体字段映射到请求消息的规则如下:
body
字段指定*
或字段路径,或省略。如果省略,则表示没有http请求体。- 叶子字段(请求中嵌套消息的递归扩展)可以分为三种类型:
a. 在url模板中匹配。
b. 由body
覆盖(如果body
是*
,除(a)字段外的所有字段; 否则一切由body
标明的字段)
c. 所有其他字段。 - 在http请求中找到的url查询参数被映射到(c)字段(未在url模板中匹配,不包含
body
之外的所有其他字段)。 - 任何使用http请求发送的
body
只能包含(b)字段。
路径模板的语法如下所示:
Template = "/" Segments [ Verb ] ;
Segments = Segment { "/" Segment } ;
Segment = "*" | "**" | LITERAL | Variable ;
Variable = "{" FieldPath [ "=" Segments ] "}" ;
FieldPath = IDENT { "." IDENT } ;
Verb = ":" LITERAL ;
语法*
匹配单个路径段。语法**
匹配零个或多个路径段,它必须是除Verb
之外的路径的最后部分。语法LITERAL
与路径中的文本文字相匹配。
语法Variable
匹配由其模板指定的url路径的一部分。一个变量模板不能包含其他变量。如果变量与单个路径段匹配,则其模板可以省略,例如: {var}
相当于{var = *}
。
如果一个变量恰好包含一个路径段,如“{var}”
或“{var = *}”
,当这样一个变量扩展为一个url路径时,除了[-_.〜0-9a-za-z]
之外的所有字符都是百分比编码的。这些变量在发现文档中显示为{var}
。
如果变量包含一个或多个路径段,如“{var = foo / *}”
或“{var = **}”
, 当这样一个变量扩展为一个url路径时,除了[-_.〜/0-9a-za-z]
之外的所有字符都是百分比编码的。这些变量在发现文档中显示为{+var}
。
注意:虽然单段变量匹配RFC 6570第3.2.2节简单字符串扩展的语义,但多段变量不匹配RFC 6570保留扩展。原因是保留扩展不会扩展特殊字符?
和#
,这将导致无效的网址。
注意:变量和正文中的字段路径不得引用重复的字段或映射字段。
原文链接: google.api.http