Skip to content

Commit 6000d9f

Browse files
authored
Extensible client options (#1263)
* Add ability to set requestReason and userAgent when configuring the client. Introduces the builder pattern for these common configuration options so that it is extensible in the future. * Fix lint * Fix lint * javadoc linting * Add userProject configuration * Add test for setting user project, request reason, user agent
1 parent 7239425 commit 6000d9f

File tree

3 files changed

+274
-7
lines changed

3 files changed

+274
-7
lines changed

google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java

Lines changed: 205 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
*
2626
* <pre>
2727
public static final GoogleClientRequestInitializer KEY_INITIALIZER =
28-
new CommonGoogleClientRequestInitializer(KEY);
28+
CommonGoogleClientRequestInitializer.newBuilder()
29+
.setKey(KEY)
30+
.build();
2931
* </pre>
3032
*
3133
* <p>
@@ -34,7 +36,10 @@
3436
*
3537
* <pre>
3638
public static final GoogleClientRequestInitializer INITIALIZER =
37-
new CommonGoogleClientRequestInitializer(KEY, USER_IP);
39+
CommonGoogleClientRequestInitializer.newBuilder()
40+
.setKey(KEY)
41+
.setUserIp(USER_IP)
42+
.build();
3843
* </pre>
3944
*
4045
* <p>
@@ -81,30 +86,73 @@ public void initialize(AbstractGoogleClientRequest{@literal <}?{@literal >} requ
8186
*/
8287
public class CommonGoogleClientRequestInitializer implements GoogleClientRequestInitializer {
8388

89+
/**
90+
* Contains a reason for making the request, which is intended to be recorded in audit logging.
91+
* An example reason would be a support-case ticket number.
92+
*/
93+
private static final String REQUEST_REASON_HEADER_NAME = "X-Goog-Request-Reason";
94+
95+
/**
96+
* A caller-specified project for quota and billing purposes. The caller must have
97+
* serviceusage.services.use permission on the project.
98+
*/
99+
private static final String USER_PROJECT_HEADER_NAME = "X-Goog-User-Project";
100+
84101
/** API key or {@code null} to leave it unchanged. */
85102
private final String key;
86103

87104
/** User IP or {@code null} to leave it unchanged. */
88105
private final String userIp;
89106

107+
/** User Agent or {@code null} to leave it unchanged. */
108+
private final String userAgent;
109+
110+
/** Reason for request or {@code null} to leave it unchanged. */
111+
private final String requestReason;
112+
113+
/** Project for quota and billing purposes of {@code null} to leave it unchanged. */
114+
private final String userProject;
115+
116+
/**
117+
* @deprecated Please use the builder interface
118+
*/
119+
@Deprecated
90120
public CommonGoogleClientRequestInitializer() {
91-
this(null);
121+
this(newBuilder());
92122
}
93123

94124
/**
95125
* @param key API key or {@code null} to leave it unchanged
126+
* @deprecated Please use the builder interface
96127
*/
128+
@Deprecated
97129
public CommonGoogleClientRequestInitializer(String key) {
98130
this(key, null);
99131
}
100132

101133
/**
102134
* @param key API key or {@code null} to leave it unchanged
103135
* @param userIp user IP or {@code null} to leave it unchanged
136+
* @deprecated Please use the builder interface
104137
*/
138+
@Deprecated
105139
public CommonGoogleClientRequestInitializer(String key, String userIp) {
106-
this.key = key;
107-
this.userIp = userIp;
140+
this(newBuilder().setKey(key).setUserIp(userIp));
141+
}
142+
143+
protected CommonGoogleClientRequestInitializer(Builder builder) {
144+
this.key = builder.getKey();
145+
this.userIp = builder.getUserIp();
146+
this.userAgent = builder.getUserAgent();
147+
this.requestReason = builder.getRequestReason();
148+
this.userProject = builder.getUserProject();
149+
}
150+
151+
/**
152+
* Returns new builder.
153+
*/
154+
public static Builder newBuilder() {
155+
return new Builder();
108156
}
109157

110158
/**
@@ -119,6 +167,15 @@ public void initialize(AbstractGoogleClientRequest<?> request) throws IOExceptio
119167
if (userIp != null) {
120168
request.put("userIp", userIp);
121169
}
170+
if (userAgent != null) {
171+
request.getRequestHeaders().setUserAgent(userAgent);
172+
}
173+
if (requestReason != null) {
174+
request.getRequestHeaders().set(REQUEST_REASON_HEADER_NAME, requestReason);
175+
}
176+
if (userProject != null) {
177+
request.getRequestHeaders().set(USER_PROJECT_HEADER_NAME, userProject);
178+
}
122179
}
123180

124181
/** Returns the API key or {@code null} to leave it unchanged. */
@@ -130,4 +187,147 @@ public final String getKey() {
130187
public final String getUserIp() {
131188
return userIp;
132189
}
190+
191+
/** Returns the user agent or {@code null} to leave it unchanged. */
192+
public final String getUserAgent() {
193+
return userAgent;
194+
}
195+
196+
/** Returns the request reason or {@code null} to leave it unchanged. */
197+
public final String getRequestReason() {
198+
return requestReason;
199+
}
200+
201+
/** Returns the user project of {@code null} */
202+
public final String getUserProject() {
203+
return userProject;
204+
}
205+
206+
/**
207+
* Builder for {@code CommonGoogleClientRequestInitializer}.
208+
*/
209+
public static class Builder {
210+
private String key;
211+
private String userIp;
212+
private String userAgent;
213+
private String requestReason;
214+
private String userProject;
215+
216+
/**
217+
* Set the API Key for outgoing requests.
218+
*
219+
* @param key the API key
220+
* @return the builder
221+
*/
222+
public Builder setKey(String key) {
223+
this.key = key;
224+
return self();
225+
}
226+
227+
/**
228+
* Returns the API key.
229+
*
230+
* @return the API key
231+
*/
232+
public String getKey() {
233+
return key;
234+
}
235+
236+
/**
237+
* Set the IP address of the end user for whom the API call is being made.
238+
*
239+
* @param userIp the user's IP address
240+
* @return the builder
241+
*/
242+
public Builder setUserIp(String userIp) {
243+
this.userIp = userIp;
244+
return self();
245+
}
246+
247+
/**
248+
* Returns the configured userIp.
249+
*
250+
* @return the userIp
251+
*/
252+
public String getUserIp() {
253+
return userIp;
254+
}
255+
256+
/**
257+
* Set the user agent.
258+
*
259+
* @param userAgent the user agent
260+
* @return the builder
261+
*/
262+
public Builder setUserAgent(String userAgent) {
263+
this.userAgent = userAgent;
264+
return self();
265+
}
266+
267+
/**
268+
* Returns the configured user agent.
269+
*
270+
* @return the user agent
271+
*/
272+
public String getUserAgent() {
273+
return userAgent;
274+
}
275+
276+
/**
277+
* Set the reason for making the request, which is intended to be recorded in audit logging. An
278+
* example reason would be a support-case ticket number.
279+
*
280+
* @param requestReason the reason for making the request
281+
* @return the builder
282+
*/
283+
public Builder setRequestReason(String requestReason) {
284+
this.requestReason = requestReason;
285+
return self();
286+
}
287+
288+
/**
289+
* Get the configured request reason.
290+
*
291+
* @return the request reason
292+
*/
293+
public String getRequestReason() {
294+
return requestReason;
295+
}
296+
297+
/**
298+
* Set the user project for the request. This is a caller-specified project for quota and
299+
* billing purposes. The caller must have serviceusage.services.use permission on the project.
300+
*
301+
* @param userProject the user project
302+
* @return the builder
303+
*/
304+
public Builder setUserProject(String userProject) {
305+
this.userProject = userProject;
306+
return self();
307+
}
308+
309+
/**
310+
* Get the configured user project.
311+
*
312+
* @return the user project
313+
*/
314+
public String getUserProject() {
315+
return userProject;
316+
}
317+
318+
/**
319+
* Returns the constructed CommonGoogleClientRequestInitializer instance.
320+
*
321+
* @return the constructed CommonGoogleClientRequestInitializer instance
322+
*/
323+
public CommonGoogleClientRequestInitializer build() {
324+
return new CommonGoogleClientRequestInitializer(this);
325+
}
326+
327+
protected Builder self() {
328+
return this;
329+
}
330+
331+
protected Builder() {}
332+
}
133333
}

google-api-client/src/main/java/com/google/api/client/googleapis/services/json/CommonGoogleJsonClientRequestInitializer.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
*
2929
* <pre>
3030
public static final GoogleClientRequestInitializer KEY_INITIALIZER =
31-
new CommonGoogleJsonClientRequestInitializer(KEY);
31+
CommonGoogleJsonClientRequestInitializer.newBuilder()
32+
.setKey(KEY)
33+
.build();
3234
* </pre>
3335
*
3436
* <p>
@@ -37,7 +39,10 @@
3739
*
3840
* <pre>
3941
public static final GoogleClientRequestInitializer INITIALIZER =
40-
new CommonGoogleJsonClientRequestInitializer(KEY, USER_IP);
42+
CommonGoogleJsonClientRequestInitializer.newBuilder()
43+
.setKey(KEY)
44+
.setUserIp(USER_IP)
45+
.build();
4146
* </pre>
4247
*
4348
* <p>
@@ -83,21 +88,29 @@ public void initializeJsonRequest(
8388
*/
8489
public class CommonGoogleJsonClientRequestInitializer extends CommonGoogleClientRequestInitializer {
8590

91+
/**
92+
* @deprecated Please use the builder interface
93+
*/
94+
@Deprecated
8695
public CommonGoogleJsonClientRequestInitializer() {
8796
super();
8897
}
8998

9099
/**
91100
* @param key API key or {@code null} to leave it unchanged
101+
* @deprecated Please use the builder interface
92102
*/
103+
@Deprecated
93104
public CommonGoogleJsonClientRequestInitializer(String key) {
94105
super(key);
95106
}
96107

97108
/**
98109
* @param key API key or {@code null} to leave it unchanged
99110
* @param userIp user IP or {@code null} to leave it unchanged
111+
* @deprecated Please use the builder interface
100112
*/
113+
@Deprecated
101114
public CommonGoogleJsonClientRequestInitializer(String key, String userIp) {
102115
super(key, userIp);
103116
}
@@ -121,4 +134,14 @@ public final void initialize(AbstractGoogleClientRequest<?> request) throws IOEx
121134
protected void initializeJsonRequest(AbstractGoogleJsonClientRequest<?> request)
122135
throws IOException {
123136
}
137+
138+
/**
139+
* Builder for {@code CommonGoogleJsonClientRequestInitializer}.
140+
*/
141+
public static class Builder extends CommonGoogleClientRequestInitializer.Builder {
142+
@Override
143+
protected Builder self() {
144+
return this;
145+
}
146+
}
124147
}

google-api-client/src/test/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializerTest.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414

1515
import com.google.api.client.googleapis.testing.services.MockGoogleClient;
1616
import com.google.api.client.http.HttpContent;
17+
import com.google.api.client.http.HttpHeaders;
1718
import com.google.api.client.testing.http.HttpTesting;
1819
import com.google.api.client.testing.http.MockHttpTransport;
1920
import com.google.api.client.util.Key;
2021

22+
import java.io.IOException;
2123
import junit.framework.TestCase;
2224

2325
/**
@@ -46,4 +48,46 @@ public void testInitialize() throws Exception {
4648
key.initialize(request);
4749
assertEquals("foo", request.key);
4850
}
51+
52+
public void testInitializeSetsUserAgent() throws IOException {
53+
GoogleClientRequestInitializer requestInitializer = CommonGoogleClientRequestInitializer.newBuilder()
54+
.setUserAgent("test user agent")
55+
.build();
56+
MockGoogleClient client = new MockGoogleClient.Builder(new MockHttpTransport(), HttpTesting.SIMPLE_URL, "test/", null, null)
57+
.setGoogleClientRequestInitializer(requestInitializer)
58+
.setApplicationName("My Application")
59+
.build();
60+
MyRequest request = new MyRequest(client, "GET", "", null, String.class);
61+
requestInitializer.initialize(request);
62+
HttpHeaders headers = request.getRequestHeaders();
63+
assertEquals("test user agent", headers.getUserAgent());
64+
}
65+
66+
public void testInitializeSetsUserProject() throws IOException {
67+
GoogleClientRequestInitializer requestInitializer = CommonGoogleClientRequestInitializer.newBuilder()
68+
.setUserProject("my quota project")
69+
.build();
70+
MockGoogleClient client = new MockGoogleClient.Builder(new MockHttpTransport(), HttpTesting.SIMPLE_URL, "test/", null, null)
71+
.setGoogleClientRequestInitializer(requestInitializer)
72+
.setApplicationName("My Application")
73+
.build();
74+
MyRequest request = new MyRequest(client, "GET", "", null, String.class);
75+
requestInitializer.initialize(request);
76+
HttpHeaders headers = request.getRequestHeaders();
77+
assertEquals("my quota project", headers.get("X-Goog-User-Project"));
78+
}
79+
80+
public void testInitializeSetsRequestReason() throws IOException {
81+
GoogleClientRequestInitializer requestInitializer = CommonGoogleClientRequestInitializer.newBuilder()
82+
.setRequestReason("some request reason")
83+
.build();
84+
MockGoogleClient client = new MockGoogleClient.Builder(new MockHttpTransport(), HttpTesting.SIMPLE_URL, "test/", null, null)
85+
.setGoogleClientRequestInitializer(requestInitializer)
86+
.setApplicationName("My Application")
87+
.build();
88+
MyRequest request = new MyRequest(client, "GET", "", null, String.class);
89+
requestInitializer.initialize(request);
90+
HttpHeaders headers = request.getRequestHeaders();
91+
assertEquals("some request reason", headers.get("X-Goog-Request-Reason"));
92+
}
4993
}

0 commit comments

Comments
 (0)