Skip to content
This repository was archived by the owner on Sep 26, 2023. It is now read-only.

Commit 59b3699

Browse files
authored
feat: [REGAPIC] Add support for additional bindings (#1680)
Additional bindings are currently relevant only for generated unit tests **[edit]** Also update IAM dependency in dependencies.properties (it is used in generated build gralde files for self-service)
1 parent faafafb commit 59b3699

File tree

6 files changed

+113
-35
lines changed

6 files changed

+113
-35
lines changed

‎dependencies.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ maven.com_google_auto_value_auto_value=com.google.auto.value:auto-value:1.9
6464
maven.com_google_auto_value_auto_value_annotations=com.google.auto.value:auto-value-annotations:1.9
6565
maven.com_google_api_api_common=com.google.api:api-common:2.1.5
6666
maven.org_threeten_threetenbp=org.threeten:threetenbp:1.5.0
67-
maven.com_google_api_grpc_grpc_google_iam_v1=com.google.api.grpc:grpc-google-iam-v1:1.0.9
68-
maven.com_google_api_grpc_proto_google_iam_v1=com.google.api.grpc:proto-google-iam-v1:1.0.9
67+
maven.com_google_api_grpc_grpc_google_iam_v1=com.google.api.grpc:grpc-google-iam-v1:1.3.4
68+
maven.com_google_api_grpc_proto_google_iam_v1=com.google.api.grpc:proto-google-iam-v1:1.3.4
6969
maven.com_google_http_client_google_http_client=com.google.http-client:google-http-client:1.41.5
7070
maven.com_google_http_client_google_http_client_gson=com.google.http-client:google-http-client-gson:1.41.5
7171
maven.org_codehaus_mojo_animal_sniffer_annotations=org.codehaus.mojo:animal-sniffer-annotations:1.18

‎gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpRequestFormatter.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929
*/
3030
package com.google.api.gax.httpjson;
3131

32+
import com.google.api.core.BetaApi;
3233
import com.google.api.pathtemplate.PathTemplate;
34+
import java.util.Collections;
3335
import java.util.List;
3436
import java.util.Map;
3537

@@ -48,4 +50,10 @@ public interface HttpRequestFormatter<MessageFormatT> {
4850

4951
/** Path template for endpoint URL path. */
5052
PathTemplate getPathTemplate();
53+
54+
/** Additional (alternative) path templates for endpoint URL path. */
55+
@BetaApi
56+
default List<PathTemplate> getAdditionalPathTemplates() {
57+
return Collections.emptyList();
58+
}
5159
}

‎gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoMessageRequestFormatter.java

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,14 @@
2929
*/
3030
package com.google.api.gax.httpjson;
3131

32+
import com.google.api.core.BetaApi;
3233
import com.google.api.core.InternalApi;
3334
import com.google.api.pathtemplate.PathTemplate;
3435
import com.google.protobuf.Message;
36+
import java.util.Arrays;
3537
import java.util.List;
3638
import java.util.Map;
39+
import java.util.stream.Collectors;
3740

3841
/** Creates parts of a HTTP request from a protobuf message. */
3942
public class ProtoMessageRequestFormatter<RequestT extends Message>
@@ -47,28 +50,35 @@ public class ProtoMessageRequestFormatter<RequestT extends Message>
4750
private final String rawPath;
4851
private final PathTemplate pathTemplate;
4952
private final FieldsExtractor<RequestT, Map<String, String>> pathVarsExtractor;
53+
private final List<String> additionalRawPaths;
54+
private final List<PathTemplate> additionalPathTemplates;
5055

5156
private ProtoMessageRequestFormatter(
5257
FieldsExtractor<RequestT, String> requestBodyExtractor,
5358
FieldsExtractor<RequestT, Map<String, List<String>>> queryParamsExtractor,
5459
String rawPath,
5560
PathTemplate pathTemplate,
56-
FieldsExtractor<RequestT, Map<String, String>> pathVarsExtractor) {
61+
FieldsExtractor<RequestT, Map<String, String>> pathVarsExtractor,
62+
List<String> additionalRawPaths,
63+
List<PathTemplate> additionalPathTemplates) {
5764
this.requestBodyExtractor = requestBodyExtractor;
5865
this.queryParamsExtractor = queryParamsExtractor;
5966
this.rawPath = rawPath;
6067
this.pathTemplate = pathTemplate;
6168
this.pathVarsExtractor = pathVarsExtractor;
69+
this.additionalRawPaths = additionalRawPaths;
70+
this.additionalPathTemplates = additionalPathTemplates;
6271
}
6372

6473
public static <RequestT extends Message>
6574
ProtoMessageRequestFormatter.Builder<RequestT> newBuilder() {
66-
return new Builder<>();
75+
return new Builder<RequestT>().setAdditionalPaths();
6776
}
6877

6978
public Builder<RequestT> toBuilder() {
7079
return new Builder<RequestT>()
7180
.setPath(rawPath, pathVarsExtractor)
81+
.setAdditionalPaths(additionalRawPaths.toArray(new String[] {}))
7282
.setQueryParamsExtractor(queryParamsExtractor)
7383
.setRequestBodyExtractor(requestBodyExtractor);
7484
}
@@ -91,6 +101,12 @@ public String getPath(RequestT apiMessage) {
91101
return pathTemplate.instantiate(pathVarsExtractor.extract(apiMessage));
92102
}
93103

104+
@BetaApi
105+
@Override
106+
public List<PathTemplate> getAdditionalPathTemplates() {
107+
return additionalPathTemplates;
108+
}
109+
94110
/* {@inheritDoc} */
95111
@Override
96112
public PathTemplate getPathTemplate() {
@@ -104,6 +120,7 @@ public static class Builder<RequestT extends Message> {
104120
private FieldsExtractor<RequestT, Map<String, List<String>>> queryParamsExtractor;
105121
private String rawPath;
106122
private FieldsExtractor<RequestT, Map<String, String>> pathVarsExtractor;
123+
private List<String> rawAdditionalPaths;
107124

108125
public Builder<RequestT> setRequestBodyExtractor(
109126
FieldsExtractor<RequestT, String> requestBodyExtractor) {
@@ -124,6 +141,12 @@ public Builder<RequestT> setPath(
124141
return this;
125142
}
126143

144+
@BetaApi
145+
public Builder<RequestT> setAdditionalPaths(String... rawAdditionalPaths) {
146+
this.rawAdditionalPaths = Arrays.asList(rawAdditionalPaths);
147+
return this;
148+
}
149+
127150
@InternalApi
128151
public Builder<RequestT> updateRawPath(String target, String replacement) {
129152
this.rawPath = this.rawPath.replace(target, replacement);
@@ -136,7 +159,9 @@ public ProtoMessageRequestFormatter<RequestT> build() {
136159
queryParamsExtractor,
137160
rawPath,
138161
PathTemplate.create(rawPath),
139-
pathVarsExtractor);
162+
pathVarsExtractor,
163+
rawAdditionalPaths,
164+
rawAdditionalPaths.stream().map(PathTemplate::create).collect(Collectors.toList()));
140165
}
141166
}
142167
}

‎gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonDirectCallableTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,14 @@ public class HttpJsonDirectCallableTest {
6565
.setRequestFormatter(
6666
ProtoMessageRequestFormatter.<Field>newBuilder()
6767
.setPath(
68-
"/fake/v1/name/{name}",
68+
"/fake/v1/name/{name=bob/*}",
6969
request -> {
7070
Map<String, String> fields = new HashMap<>();
7171
ProtoRestSerializer<Field> serializer = ProtoRestSerializer.create();
7272
serializer.putPathParam(fields, "name", request.getName());
7373
return fields;
7474
})
75+
.setAdditionalPaths("/fake/v1/name/{name=john/*}")
7576
.setQueryParamsExtractor(
7677
request -> {
7778
Map<String, List<String>> fields = new HashMap<>();
@@ -212,7 +213,7 @@ public void testErrorNullContentFailedResponse() throws InterruptedException {
212213

213214
private Field createTestMessage() {
214215
return Field.newBuilder() // "echo" service
215-
.setName("imTheBestField")
216+
.setName("john/imTheBestField")
216217
.setNumber(2)
217218
.setCardinality(Cardinality.CARDINALITY_OPTIONAL)
218219
.setDefaultValue("blah")

‎gax-httpjson/src/test/java/com/google/api/gax/httpjson/ProtoMessageRequestFormatterTest.java

Lines changed: 67 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444

4545
public class ProtoMessageRequestFormatterTest {
4646
private Field field;
47-
private HttpRequestFormatter<Field> formatter;
47+
private ProtoMessageRequestFormatter<Field> formatter;
4848

4949
@Before
5050
public void setUp() {
@@ -60,36 +60,28 @@ public void setUp() {
6060
formatter =
6161
ProtoMessageRequestFormatter.<Field>newBuilder()
6262
.setPath(
63-
"/api/v1/names/{name}/aggregated",
64-
new FieldsExtractor<Field, Map<String, String>>() {
65-
@Override
66-
public Map<String, String> extract(Field request) {
67-
Map<String, String> fields = new HashMap<>();
68-
ProtoRestSerializer<Field> serializer = ProtoRestSerializer.create();
69-
serializer.putPathParam(fields, "name", request.getName());
70-
serializer.putPathParam(fields, "kindValue", request.getKindValue());
71-
return fields;
72-
}
63+
"/api/v1/names/{name=field_name1/**}/aggregated",
64+
request -> {
65+
Map<String, String> fields = new HashMap<>();
66+
ProtoRestSerializer<Field> serializer = ProtoRestSerializer.create();
67+
serializer.putPathParam(fields, "name", request.getName());
68+
serializer.putPathParam(fields, "kindValue", request.getKindValue());
69+
return fields;
7370
})
7471
.setQueryParamsExtractor(
75-
new FieldsExtractor<Field, Map<String, List<String>>>() {
76-
@Override
77-
public Map<String, List<String>> extract(Field request) {
78-
Map<String, List<String>> fields = new HashMap<>();
79-
ProtoRestSerializer<Field> serializer = ProtoRestSerializer.create();
80-
serializer.putQueryParam(fields, "number", request.getNumber());
81-
serializer.putQueryParam(fields, "typeUrl", request.getTypeUrl());
82-
return fields;
83-
}
72+
request -> {
73+
Map<String, List<String>> fields = new HashMap<>();
74+
ProtoRestSerializer<Field> serializer = ProtoRestSerializer.create();
75+
serializer.putQueryParam(fields, "number", request.getNumber());
76+
serializer.putQueryParam(fields, "typeUrl", request.getTypeUrl());
77+
return fields;
8478
})
8579
.setRequestBodyExtractor(
86-
new FieldsExtractor<Field, String>() {
87-
@Override
88-
public String extract(Field request) {
89-
ProtoRestSerializer<Field> serializer = ProtoRestSerializer.create();
90-
return serializer.toBody("field", request);
91-
}
80+
request -> {
81+
ProtoRestSerializer<Field> serializer = ProtoRestSerializer.create();
82+
return serializer.toBody("field", request);
9283
})
84+
.setAdditionalPaths("/api/v1/names/{name=field_name1/**}/hello")
9385
.build();
9486
}
9587

@@ -100,6 +92,12 @@ public void getQueryParamNames() {
10092
expected.put("number", Arrays.asList("2"));
10193
expected.put("typeUrl", Arrays.asList(""));
10294
Truth.assertThat(queryParamNames).isEqualTo(expected);
95+
96+
// Test toBuilder() case
97+
queryParamNames = formatter.toBuilder().build().getQueryParamNames(field);
98+
expected.put("number", Arrays.asList("2"));
99+
expected.put("typeUrl", Arrays.asList(""));
100+
Truth.assertThat(queryParamNames).isEqualTo(expected);
103101
}
104102

105103
@Test
@@ -117,18 +115,61 @@ public void getRequestBody() {
117115
+ " }]\n"
118116
+ "}";
119117
Truth.assertThat(bodyJson).isEqualTo(expectedBodyJson);
118+
119+
// Test toBuilder() case
120+
formatter.toBuilder().build().getRequestBody(field);
121+
Truth.assertThat(bodyJson).isEqualTo(expectedBodyJson);
120122
}
121123

122124
@Test
123125
public void getPath() {
124126
String path = formatter.getPath(field);
125127
Truth.assertThat(path).isEqualTo("api/v1/names/field_name1/aggregated");
128+
129+
// Test toBuilder() case
130+
path = formatter.toBuilder().build().getPath(field);
131+
Truth.assertThat(path).isEqualTo("api/v1/names/field_name1/aggregated");
126132
}
127133

128134
@Test
129135
public void getPathTemplate() {
130136
String path =
131137
formatter.getPathTemplate().instantiate(Collections.singletonMap("name", "field_name1"));
132138
Truth.assertThat(path).isEqualTo("api/v1/names/field_name1/aggregated");
139+
140+
// Test toBuilder() case
141+
path =
142+
formatter
143+
.toBuilder()
144+
.build()
145+
.getPathTemplate()
146+
.instantiate(Collections.singletonMap("name", "field_name1"));
147+
Truth.assertThat(path).isEqualTo("api/v1/names/field_name1/aggregated");
148+
}
149+
150+
@Test
151+
public void getPathTemplates() {
152+
String path =
153+
formatter
154+
.getAdditionalPathTemplates()
155+
.get(0)
156+
.instantiate(Collections.singletonMap("name", "field_name1"));
157+
Truth.assertThat(path).isEqualTo("api/v1/names/field_name1/hello");
158+
159+
// Test toBuilder() case
160+
path =
161+
formatter
162+
.toBuilder()
163+
.build()
164+
.getAdditionalPathTemplates()
165+
.get(0)
166+
.instantiate(Collections.singletonMap("name", "field_name1"));
167+
Truth.assertThat(path).isEqualTo("api/v1/names/field_name1/hello");
168+
}
169+
170+
@Test
171+
public void updateRawPath() {
172+
String path = formatter.toBuilder().updateRawPath("/v1/", "/v1beta1/").build().getPath(field);
173+
Truth.assertThat(path).isEqualTo("api/v1beta1/names/field_name1/aggregated");
133174
}
134175
}

‎gax-httpjson/src/test/java/com/google/api/gax/httpjson/testing/MockHttpService.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,11 @@ public MockLowLevelHttpResponse getHttpResponse(String httpMethod, String fullTa
208208
}
209209

210210
PathTemplate pathTemplate = methodDescriptor.getRequestFormatter().getPathTemplate();
211-
// Server figures out which RPC method is called based on the endpoint path pattern.
212-
if (!pathTemplate.matches(relativePath)) {
211+
List<PathTemplate> additionalPathTemplates =
212+
methodDescriptor.getRequestFormatter().getAdditionalPathTemplates();
213+
// Server figures out which RPC method is called based on the endpoint path pattern(s).
214+
if (!pathTemplate.matches(relativePath)
215+
&& additionalPathTemplates.stream().noneMatch(pt -> pt.matches(relativePath))) {
213216
continue;
214217
}
215218

0 commit comments

Comments
 (0)