routing.proto 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. // Copyright 2024 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. syntax = "proto3";
  15. package google.api;
  16. import "google/protobuf/descriptor.proto";
  17. option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations";
  18. option java_multiple_files = true;
  19. option java_outer_classname = "RoutingProto";
  20. option java_package = "com.google.api";
  21. option objc_class_prefix = "GAPI";
  22. extend google.protobuf.MethodOptions {
  23. // See RoutingRule.
  24. google.api.RoutingRule routing = 72295729;
  25. }
  26. // Specifies the routing information that should be sent along with the request
  27. // in the form of routing header.
  28. // **NOTE:** All service configuration rules follow the "last one wins" order.
  29. //
  30. // The examples below will apply to an RPC which has the following request type:
  31. //
  32. // Message Definition:
  33. //
  34. // message Request {
  35. // // The name of the Table
  36. // // Values can be of the following formats:
  37. // // - `projects/<project>/tables/<table>`
  38. // // - `projects/<project>/instances/<instance>/tables/<table>`
  39. // // - `region/<region>/zones/<zone>/tables/<table>`
  40. // string table_name = 1;
  41. //
  42. // // This value specifies routing for replication.
  43. // // It can be in the following formats:
  44. // // - `profiles/<profile_id>`
  45. // // - a legacy `profile_id` that can be any string
  46. // string app_profile_id = 2;
  47. // }
  48. //
  49. // Example message:
  50. //
  51. // {
  52. // table_name: projects/proj_foo/instances/instance_bar/table/table_baz,
  53. // app_profile_id: profiles/prof_qux
  54. // }
  55. //
  56. // The routing header consists of one or multiple key-value pairs. Every key
  57. // and value must be percent-encoded, and joined together in the format of
  58. // `key1=value1&key2=value2`.
  59. // In the examples below I am skipping the percent-encoding for readablity.
  60. //
  61. // Example 1
  62. //
  63. // Extracting a field from the request to put into the routing header
  64. // unchanged, with the key equal to the field name.
  65. //
  66. // annotation:
  67. //
  68. // option (google.api.routing) = {
  69. // // Take the `app_profile_id`.
  70. // routing_parameters {
  71. // field: "app_profile_id"
  72. // }
  73. // };
  74. //
  75. // result:
  76. //
  77. // x-goog-request-params: app_profile_id=profiles/prof_qux
  78. //
  79. // Example 2
  80. //
  81. // Extracting a field from the request to put into the routing header
  82. // unchanged, with the key different from the field name.
  83. //
  84. // annotation:
  85. //
  86. // option (google.api.routing) = {
  87. // // Take the `app_profile_id`, but name it `routing_id` in the header.
  88. // routing_parameters {
  89. // field: "app_profile_id"
  90. // path_template: "{routing_id=**}"
  91. // }
  92. // };
  93. //
  94. // result:
  95. //
  96. // x-goog-request-params: routing_id=profiles/prof_qux
  97. //
  98. // Example 3
  99. //
  100. // Extracting a field from the request to put into the routing
  101. // header, while matching a path template syntax on the field's value.
  102. //
  103. // NB: it is more useful to send nothing than to send garbage for the purpose
  104. // of dynamic routing, since garbage pollutes cache. Thus the matching.
  105. //
  106. // Sub-example 3a
  107. //
  108. // The field matches the template.
  109. //
  110. // annotation:
  111. //
  112. // option (google.api.routing) = {
  113. // // Take the `table_name`, if it's well-formed (with project-based
  114. // // syntax).
  115. // routing_parameters {
  116. // field: "table_name"
  117. // path_template: "{table_name=projects/*/instances/*/**}"
  118. // }
  119. // };
  120. //
  121. // result:
  122. //
  123. // x-goog-request-params:
  124. // table_name=projects/proj_foo/instances/instance_bar/table/table_baz
  125. //
  126. // Sub-example 3b
  127. //
  128. // The field does not match the template.
  129. //
  130. // annotation:
  131. //
  132. // option (google.api.routing) = {
  133. // // Take the `table_name`, if it's well-formed (with region-based
  134. // // syntax).
  135. // routing_parameters {
  136. // field: "table_name"
  137. // path_template: "{table_name=regions/*/zones/*/**}"
  138. // }
  139. // };
  140. //
  141. // result:
  142. //
  143. // <no routing header will be sent>
  144. //
  145. // Sub-example 3c
  146. //
  147. // Multiple alternative conflictingly named path templates are
  148. // specified. The one that matches is used to construct the header.
  149. //
  150. // annotation:
  151. //
  152. // option (google.api.routing) = {
  153. // // Take the `table_name`, if it's well-formed, whether
  154. // // using the region- or projects-based syntax.
  155. //
  156. // routing_parameters {
  157. // field: "table_name"
  158. // path_template: "{table_name=regions/*/zones/*/**}"
  159. // }
  160. // routing_parameters {
  161. // field: "table_name"
  162. // path_template: "{table_name=projects/*/instances/*/**}"
  163. // }
  164. // };
  165. //
  166. // result:
  167. //
  168. // x-goog-request-params:
  169. // table_name=projects/proj_foo/instances/instance_bar/table/table_baz
  170. //
  171. // Example 4
  172. //
  173. // Extracting a single routing header key-value pair by matching a
  174. // template syntax on (a part of) a single request field.
  175. //
  176. // annotation:
  177. //
  178. // option (google.api.routing) = {
  179. // // Take just the project id from the `table_name` field.
  180. // routing_parameters {
  181. // field: "table_name"
  182. // path_template: "{routing_id=projects/*}/**"
  183. // }
  184. // };
  185. //
  186. // result:
  187. //
  188. // x-goog-request-params: routing_id=projects/proj_foo
  189. //
  190. // Example 5
  191. //
  192. // Extracting a single routing header key-value pair by matching
  193. // several conflictingly named path templates on (parts of) a single request
  194. // field. The last template to match "wins" the conflict.
  195. //
  196. // annotation:
  197. //
  198. // option (google.api.routing) = {
  199. // // If the `table_name` does not have instances information,
  200. // // take just the project id for routing.
  201. // // Otherwise take project + instance.
  202. //
  203. // routing_parameters {
  204. // field: "table_name"
  205. // path_template: "{routing_id=projects/*}/**"
  206. // }
  207. // routing_parameters {
  208. // field: "table_name"
  209. // path_template: "{routing_id=projects/*/instances/*}/**"
  210. // }
  211. // };
  212. //
  213. // result:
  214. //
  215. // x-goog-request-params:
  216. // routing_id=projects/proj_foo/instances/instance_bar
  217. //
  218. // Example 6
  219. //
  220. // Extracting multiple routing header key-value pairs by matching
  221. // several non-conflicting path templates on (parts of) a single request field.
  222. //
  223. // Sub-example 6a
  224. //
  225. // Make the templates strict, so that if the `table_name` does not
  226. // have an instance information, nothing is sent.
  227. //
  228. // annotation:
  229. //
  230. // option (google.api.routing) = {
  231. // // The routing code needs two keys instead of one composite
  232. // // but works only for the tables with the "project-instance" name
  233. // // syntax.
  234. //
  235. // routing_parameters {
  236. // field: "table_name"
  237. // path_template: "{project_id=projects/*}/instances/*/**"
  238. // }
  239. // routing_parameters {
  240. // field: "table_name"
  241. // path_template: "projects/*/{instance_id=instances/*}/**"
  242. // }
  243. // };
  244. //
  245. // result:
  246. //
  247. // x-goog-request-params:
  248. // project_id=projects/proj_foo&instance_id=instances/instance_bar
  249. //
  250. // Sub-example 6b
  251. //
  252. // Make the templates loose, so that if the `table_name` does not
  253. // have an instance information, just the project id part is sent.
  254. //
  255. // annotation:
  256. //
  257. // option (google.api.routing) = {
  258. // // The routing code wants two keys instead of one composite
  259. // // but will work with just the `project_id` for tables without
  260. // // an instance in the `table_name`.
  261. //
  262. // routing_parameters {
  263. // field: "table_name"
  264. // path_template: "{project_id=projects/*}/**"
  265. // }
  266. // routing_parameters {
  267. // field: "table_name"
  268. // path_template: "projects/*/{instance_id=instances/*}/**"
  269. // }
  270. // };
  271. //
  272. // result (is the same as 6a for our example message because it has the instance
  273. // information):
  274. //
  275. // x-goog-request-params:
  276. // project_id=projects/proj_foo&instance_id=instances/instance_bar
  277. //
  278. // Example 7
  279. //
  280. // Extracting multiple routing header key-value pairs by matching
  281. // several path templates on multiple request fields.
  282. //
  283. // NB: note that here there is no way to specify sending nothing if one of the
  284. // fields does not match its template. E.g. if the `table_name` is in the wrong
  285. // format, the `project_id` will not be sent, but the `routing_id` will be.
  286. // The backend routing code has to be aware of that and be prepared to not
  287. // receive a full complement of keys if it expects multiple.
  288. //
  289. // annotation:
  290. //
  291. // option (google.api.routing) = {
  292. // // The routing needs both `project_id` and `routing_id`
  293. // // (from the `app_profile_id` field) for routing.
  294. //
  295. // routing_parameters {
  296. // field: "table_name"
  297. // path_template: "{project_id=projects/*}/**"
  298. // }
  299. // routing_parameters {
  300. // field: "app_profile_id"
  301. // path_template: "{routing_id=**}"
  302. // }
  303. // };
  304. //
  305. // result:
  306. //
  307. // x-goog-request-params:
  308. // project_id=projects/proj_foo&routing_id=profiles/prof_qux
  309. //
  310. // Example 8
  311. //
  312. // Extracting a single routing header key-value pair by matching
  313. // several conflictingly named path templates on several request fields. The
  314. // last template to match "wins" the conflict.
  315. //
  316. // annotation:
  317. //
  318. // option (google.api.routing) = {
  319. // // The `routing_id` can be a project id or a region id depending on
  320. // // the table name format, but only if the `app_profile_id` is not set.
  321. // // If `app_profile_id` is set it should be used instead.
  322. //
  323. // routing_parameters {
  324. // field: "table_name"
  325. // path_template: "{routing_id=projects/*}/**"
  326. // }
  327. // routing_parameters {
  328. // field: "table_name"
  329. // path_template: "{routing_id=regions/*}/**"
  330. // }
  331. // routing_parameters {
  332. // field: "app_profile_id"
  333. // path_template: "{routing_id=**}"
  334. // }
  335. // };
  336. //
  337. // result:
  338. //
  339. // x-goog-request-params: routing_id=profiles/prof_qux
  340. //
  341. // Example 9
  342. //
  343. // Bringing it all together.
  344. //
  345. // annotation:
  346. //
  347. // option (google.api.routing) = {
  348. // // For routing both `table_location` and a `routing_id` are needed.
  349. // //
  350. // // table_location can be either an instance id or a region+zone id.
  351. // //
  352. // // For `routing_id`, take the value of `app_profile_id`
  353. // // - If it's in the format `profiles/<profile_id>`, send
  354. // // just the `<profile_id>` part.
  355. // // - If it's any other literal, send it as is.
  356. // // If the `app_profile_id` is empty, and the `table_name` starts with
  357. // // the project_id, send that instead.
  358. //
  359. // routing_parameters {
  360. // field: "table_name"
  361. // path_template: "projects/*/{table_location=instances/*}/tables/*"
  362. // }
  363. // routing_parameters {
  364. // field: "table_name"
  365. // path_template: "{table_location=regions/*/zones/*}/tables/*"
  366. // }
  367. // routing_parameters {
  368. // field: "table_name"
  369. // path_template: "{routing_id=projects/*}/**"
  370. // }
  371. // routing_parameters {
  372. // field: "app_profile_id"
  373. // path_template: "{routing_id=**}"
  374. // }
  375. // routing_parameters {
  376. // field: "app_profile_id"
  377. // path_template: "profiles/{routing_id=*}"
  378. // }
  379. // };
  380. //
  381. // result:
  382. //
  383. // x-goog-request-params:
  384. // table_location=instances/instance_bar&routing_id=prof_qux
  385. message RoutingRule {
  386. // A collection of Routing Parameter specifications.
  387. // **NOTE:** If multiple Routing Parameters describe the same key
  388. // (via the `path_template` field or via the `field` field when
  389. // `path_template` is not provided), "last one wins" rule
  390. // determines which Parameter gets used.
  391. // See the examples for more details.
  392. repeated RoutingParameter routing_parameters = 2;
  393. }
  394. // A projection from an input message to the GRPC or REST header.
  395. message RoutingParameter {
  396. // A request field to extract the header key-value pair from.
  397. string field = 1;
  398. // A pattern matching the key-value field. Optional.
  399. // If not specified, the whole field specified in the `field` field will be
  400. // taken as value, and its name used as key. If specified, it MUST contain
  401. // exactly one named segment (along with any number of unnamed segments) The
  402. // pattern will be matched over the field specified in the `field` field, then
  403. // if the match is successful:
  404. // - the name of the single named segment will be used as a header name,
  405. // - the match value of the segment will be used as a header value;
  406. // if the match is NOT successful, nothing will be sent.
  407. //
  408. // Example:
  409. //
  410. // -- This is a field in the request message
  411. // | that the header value will be extracted from.
  412. // |
  413. // | -- This is the key name in the
  414. // | | routing header.
  415. // V |
  416. // field: "table_name" v
  417. // path_template: "projects/*/{table_location=instances/*}/tables/*"
  418. // ^ ^
  419. // | |
  420. // In the {} brackets is the pattern that -- |
  421. // specifies what to extract from the |
  422. // field as a value to be sent. |
  423. // |
  424. // The string in the field must match the whole pattern --
  425. // before brackets, inside brackets, after brackets.
  426. //
  427. // When looking at this specific example, we can see that:
  428. // - A key-value pair with the key `table_location`
  429. // and the value matching `instances/*` should be added
  430. // to the x-goog-request-params routing header.
  431. // - The value is extracted from the request message's `table_name` field
  432. // if it matches the full pattern specified:
  433. // `projects/*/instances/*/tables/*`.
  434. //
  435. // **NB:** If the `path_template` field is not provided, the key name is
  436. // equal to the field name, and the whole field should be sent as a value.
  437. // This makes the pattern for the field and the value functionally equivalent
  438. // to `**`, and the configuration
  439. //
  440. // {
  441. // field: "table_name"
  442. // }
  443. //
  444. // is a functionally equivalent shorthand to:
  445. //
  446. // {
  447. // field: "table_name"
  448. // path_template: "{table_name=**}"
  449. // }
  450. //
  451. // See Example 1 for more details.
  452. string path_template = 2;
  453. }