From aec00f970f4ebfb8b185b6394b7950001207527b Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Wed, 22 May 2019 15:19:41 -0700 Subject: [PATCH 1/6] 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. --- .../CommonGoogleClientRequestInitializer.java | 166 +++++++++++++++++- ...monGoogleJsonClientRequestInitializer.java | 27 ++- 2 files changed, 186 insertions(+), 7 deletions(-) diff --git a/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java b/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java index e14fa4e89..36f7356bf 100644 --- a/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java +++ b/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java @@ -25,7 +25,9 @@ * *
   public static final GoogleClientRequestInitializer KEY_INITIALIZER =
-      new CommonGoogleClientRequestInitializer(KEY);
+      CommonGoogleClientRequestInitializer.newBuilder()
+          .setKey(KEY)
+          .build();
  * 
* *

@@ -34,7 +36,10 @@ * *

   public static final GoogleClientRequestInitializer INITIALIZER =
-      new CommonGoogleClientRequestInitializer(KEY, USER_IP);
+      CommonGoogleClientRequestInitializer.newBuilder()
+          .setKey(KEY)
+          .setUserIp(USER_IP)
+          .build();
  * 
* *

@@ -87,13 +92,25 @@ public class CommonGoogleClientRequestInitializer implements GoogleClientRequest /** User IP or {@code null} to leave it unchanged. */ private final String userIp; + /** User Agent or {@code null} to leave it unchanged. */ + private final String userAgent; + + /** Reason for request or {@code null} to leave it unchanged. */ + private final String requestReason; + + /** + * @deprecated Please use the builder interface + */ + @Deprecated public CommonGoogleClientRequestInitializer() { - this(null); + this(newBuilder()); } /** * @param key API key or {@code null} to leave it unchanged + * @deprecated Please use the builder interface */ + @Deprecated public CommonGoogleClientRequestInitializer(String key) { this(key, null); } @@ -101,10 +118,25 @@ public CommonGoogleClientRequestInitializer(String key) { /** * @param key API key or {@code null} to leave it unchanged * @param userIp user IP or {@code null} to leave it unchanged + * @deprecated Please use the builder interface */ + @Deprecated public CommonGoogleClientRequestInitializer(String key, String userIp) { - this.key = key; - this.userIp = userIp; + this(newBuilder().setKey(key).setUserIp(userIp)); + } + + protected CommonGoogleClientRequestInitializer(Builder builder) { + this.key = builder.getKey(); + this.userIp = builder.getUserIp(); + this.userAgent = builder.getUserAgent(); + this.requestReason = builder.getRequestReason(); + } + + /** + * Returns new builder + */ + public static Builder newBuilder() { + return new Builder(); } /** @@ -119,6 +151,14 @@ public void initialize(AbstractGoogleClientRequest request) throws IOExceptio if (userIp != null) { request.put("userIp", userIp); } + if (userAgent != null) { + // FIXME(chingor): set the correct header + request.put("userAgent", userAgent); + } + if (requestReason != null) { + // FIXME(chingor): set the correct header + request.put("requestReason", requestReason); + } } /** Returns the API key or {@code null} to leave it unchanged. */ @@ -130,4 +170,120 @@ public final String getKey() { public final String getUserIp() { return userIp; } + + /** Returns the user agent or {@code null} to leave it unchanged. */ + public final String getUserAgent() { + return userAgent; + } + + /** Returns the request reason or {@code null} to leave it unchanged. */ + public final String getRequestReason() { + return requestReason; + } + + /** + * Builder for {@code CommonGoogleClientRequestInitializer}. + */ + public static class Builder { + private String key; + private String userIp; + private String userAgent; + private String requestReason; + + /** + * Set the API Key for outgoing requests + * + * @param key the API key + * @return the builder + */ + public Builder setKey(String key) { + this.key = key; + return self(); + } + + /** + * Returns the API Key + * + * @return the API key + */ + public String getKey() { + return key; + } + + /** + * Set the IP address of the end user for whom the API call is being made + * + * @param userIp the user's IP + * @return the builder + */ + public Builder setUserIp(String userIp) { + this.userIp = userIp; + return self(); + } + + /** + * Returns the configured userIp + * + * @return the userIp + */ + public String getUserIp() { + return userIp; + } + + /** + * Set the user agent + * + * @param userAgent the user agent + * @return the builder + */ + public Builder setUserAgent(String userAgent) { + this.userAgent = userAgent; + return self(); + } + + /** + * Returns the configured user agent + * + * @return the user agent + */ + public String getUserAgent() { + return userAgent; + } + + /** + * Set the reason for making the request, which is intended to be recorded in audit logging. An example reason would + * be a support-case ticket number + * + * @param requestReason the reason for making the request + * @return the builder + */ + public Builder setRequestReason(String requestReason) { + this.requestReason = requestReason; + return self(); + } + + /** + * Get the configured request reason + * + * @return the request reason + */ + public String getRequestReason() { + return requestReason; + } + + /** + * Returns the constructed CommonGoogleClientRequestInitializer instance + * + * @return the constructed CommonGoogleClientRequestInitializer instance + */ + public CommonGoogleClientRequestInitializer build() { + return new CommonGoogleClientRequestInitializer(this); + } + + protected Builder self() { + return this; + } + + protected Builder() {} + } } diff --git a/google-api-client/src/main/java/com/google/api/client/googleapis/services/json/CommonGoogleJsonClientRequestInitializer.java b/google-api-client/src/main/java/com/google/api/client/googleapis/services/json/CommonGoogleJsonClientRequestInitializer.java index 162947b8a..4518c471f 100644 --- a/google-api-client/src/main/java/com/google/api/client/googleapis/services/json/CommonGoogleJsonClientRequestInitializer.java +++ b/google-api-client/src/main/java/com/google/api/client/googleapis/services/json/CommonGoogleJsonClientRequestInitializer.java @@ -28,7 +28,9 @@ * *

   public static final GoogleClientRequestInitializer KEY_INITIALIZER =
-      new CommonGoogleJsonClientRequestInitializer(KEY);
+      CommonGoogleJsonClientRequestInitializer.newBuilder()
+          .setKey(KEY)
+          .build();
  * 
* *

@@ -37,7 +39,10 @@ * *

   public static final GoogleClientRequestInitializer INITIALIZER =
-      new CommonGoogleJsonClientRequestInitializer(KEY, USER_IP);
+      CommonGoogleJsonClientRequestInitializer.newBuilder()
+          .setKey(KEY)
+          .setUserIp(USER_IP)
+          .build();
  * 
* *

@@ -83,13 +88,19 @@ public void initializeJsonRequest( */ public class CommonGoogleJsonClientRequestInitializer extends CommonGoogleClientRequestInitializer { + /** + * @deprecated Please use the builder interface + */ + @Deprecated public CommonGoogleJsonClientRequestInitializer() { super(); } /** * @param key API key or {@code null} to leave it unchanged + * @deprecated Please use the builder interface */ + @Deprecated public CommonGoogleJsonClientRequestInitializer(String key) { super(key); } @@ -97,7 +108,9 @@ public CommonGoogleJsonClientRequestInitializer(String key) { /** * @param key API key or {@code null} to leave it unchanged * @param userIp user IP or {@code null} to leave it unchanged + * @deprecated Please use the builder interface */ + @Deprecated public CommonGoogleJsonClientRequestInitializer(String key, String userIp) { super(key, userIp); } @@ -121,4 +134,14 @@ public final void initialize(AbstractGoogleClientRequest request) throws IOEx protected void initializeJsonRequest(AbstractGoogleJsonClientRequest request) throws IOException { } + + /** + * Builder for {@code CommonGoogleJsonClientRequestInitializer} + */ + public static class Builder extends CommonGoogleClientRequestInitializer.Builder { + @Override + protected Builder self() { + return this; + } + } } From 138ffa619ce27b24397b0ab7ab892206b213d797 Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Wed, 22 May 2019 15:48:20 -0700 Subject: [PATCH 2/6] Fix lint --- .../services/CommonGoogleClientRequestInitializer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java b/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java index 36f7356bf..08533dd70 100644 --- a/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java +++ b/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java @@ -251,8 +251,8 @@ public String getUserAgent() { } /** - * Set the reason for making the request, which is intended to be recorded in audit logging. An example reason would - * be a support-case ticket number + * Set the reason for making the request, which is intended to be recorded in audit logging. An + * example reason would be a support-case ticket number * * @param requestReason the reason for making the request * @return the builder From cc6eb5449eaaae232690ace283379847dc40f50d Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Wed, 22 May 2019 15:53:33 -0700 Subject: [PATCH 3/6] Fix lint --- .../services/CommonGoogleClientRequestInitializer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java b/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java index 08533dd70..3f6dcff7b 100644 --- a/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java +++ b/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java @@ -152,11 +152,11 @@ public void initialize(AbstractGoogleClientRequest request) throws IOExceptio request.put("userIp", userIp); } if (userAgent != null) { - // FIXME(chingor): set the correct header + // TODO(chingor): set the correct header request.put("userAgent", userAgent); } if (requestReason != null) { - // FIXME(chingor): set the correct header + // TODO(chingor): set the correct header request.put("requestReason", requestReason); } } From 1678fefd4105a6bf40f6ba0720602962a1f76f7a Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Wed, 22 May 2019 16:16:01 -0700 Subject: [PATCH 4/6] javadoc linting --- .../CommonGoogleClientRequestInitializer.java | 22 +++++++++---------- ...monGoogleJsonClientRequestInitializer.java | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java b/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java index 3f6dcff7b..4cfa7bb83 100644 --- a/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java +++ b/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java @@ -133,7 +133,7 @@ protected CommonGoogleClientRequestInitializer(Builder builder) { } /** - * Returns new builder + * Returns new builder. */ public static Builder newBuilder() { return new Builder(); @@ -191,7 +191,7 @@ public static class Builder { private String requestReason; /** - * Set the API Key for outgoing requests + * Set the API Key for outgoing requests. * * @param key the API key * @return the builder @@ -202,7 +202,7 @@ public Builder setKey(String key) { } /** - * Returns the API Key + * Returns the API key. * * @return the API key */ @@ -211,9 +211,9 @@ public String getKey() { } /** - * Set the IP address of the end user for whom the API call is being made + * Set the IP address of the end user for whom the API call is being made. * - * @param userIp the user's IP + * @param userIp the user's IP address * @return the builder */ public Builder setUserIp(String userIp) { @@ -222,7 +222,7 @@ public Builder setUserIp(String userIp) { } /** - * Returns the configured userIp + * Returns the configured userIp. * * @return the userIp */ @@ -231,7 +231,7 @@ public String getUserIp() { } /** - * Set the user agent + * Set the user agent. * * @param userAgent the user agent * @return the builder @@ -242,7 +242,7 @@ public Builder setUserAgent(String userAgent) { } /** - * Returns the configured user agent + * Returns the configured user agent. * * @return the user agent */ @@ -252,7 +252,7 @@ public String getUserAgent() { /** * Set the reason for making the request, which is intended to be recorded in audit logging. An - * example reason would be a support-case ticket number + * example reason would be a support-case ticket number. * * @param requestReason the reason for making the request * @return the builder @@ -263,7 +263,7 @@ public Builder setRequestReason(String requestReason) { } /** - * Get the configured request reason + * Get the configured request reason. * * @return the request reason */ @@ -272,7 +272,7 @@ public String getRequestReason() { } /** - * Returns the constructed CommonGoogleClientRequestInitializer instance + * Returns the constructed CommonGoogleClientRequestInitializer instance. * * @return the constructed CommonGoogleClientRequestInitializer instance */ diff --git a/google-api-client/src/main/java/com/google/api/client/googleapis/services/json/CommonGoogleJsonClientRequestInitializer.java b/google-api-client/src/main/java/com/google/api/client/googleapis/services/json/CommonGoogleJsonClientRequestInitializer.java index 4518c471f..eeabf184e 100644 --- a/google-api-client/src/main/java/com/google/api/client/googleapis/services/json/CommonGoogleJsonClientRequestInitializer.java +++ b/google-api-client/src/main/java/com/google/api/client/googleapis/services/json/CommonGoogleJsonClientRequestInitializer.java @@ -136,7 +136,7 @@ protected void initializeJsonRequest(AbstractGoogleJsonClientRequest request) } /** - * Builder for {@code CommonGoogleJsonClientRequestInitializer} + * Builder for {@code CommonGoogleJsonClientRequestInitializer}. */ public static class Builder extends CommonGoogleClientRequestInitializer.Builder { @Override From 3a497f2d705bc6ff8f1e3fa25687604bea1f175c Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Thu, 6 Jun 2019 11:53:38 -0700 Subject: [PATCH 5/6] Add userProject configuration --- .../CommonGoogleClientRequestInitializer.java | 52 +++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java b/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java index 4cfa7bb83..4bb5cfc99 100644 --- a/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java +++ b/google-api-client/src/main/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializer.java @@ -86,6 +86,18 @@ public void initialize(AbstractGoogleClientRequest{@literal <}?{@literal >} requ */ public class CommonGoogleClientRequestInitializer implements GoogleClientRequestInitializer { + /** + * Contains a reason for making the request, which is intended to be recorded in audit logging. + * An example reason would be a support-case ticket number. + */ + private static final String REQUEST_REASON_HEADER_NAME = "X-Goog-Request-Reason"; + + /** + * A caller-specified project for quota and billing purposes. The caller must have + * serviceusage.services.use permission on the project. + */ + private static final String USER_PROJECT_HEADER_NAME = "X-Goog-User-Project"; + /** API key or {@code null} to leave it unchanged. */ private final String key; @@ -98,6 +110,9 @@ public class CommonGoogleClientRequestInitializer implements GoogleClientRequest /** Reason for request or {@code null} to leave it unchanged. */ private final String requestReason; + /** Project for quota and billing purposes of {@code null} to leave it unchanged. */ + private final String userProject; + /** * @deprecated Please use the builder interface */ @@ -130,6 +145,7 @@ protected CommonGoogleClientRequestInitializer(Builder builder) { this.userIp = builder.getUserIp(); this.userAgent = builder.getUserAgent(); this.requestReason = builder.getRequestReason(); + this.userProject = builder.getUserProject(); } /** @@ -152,12 +168,13 @@ public void initialize(AbstractGoogleClientRequest request) throws IOExceptio request.put("userIp", userIp); } if (userAgent != null) { - // TODO(chingor): set the correct header - request.put("userAgent", userAgent); + request.getRequestHeaders().setUserAgent(userAgent); } if (requestReason != null) { - // TODO(chingor): set the correct header - request.put("requestReason", requestReason); + request.getRequestHeaders().set(REQUEST_REASON_HEADER_NAME, requestReason); + } + if (userProject != null) { + request.getRequestHeaders().set(USER_PROJECT_HEADER_NAME, userProject); } } @@ -181,6 +198,11 @@ public final String getRequestReason() { return requestReason; } + /** Returns the user project of {@code null} */ + public final String getUserProject() { + return userProject; + } + /** * Builder for {@code CommonGoogleClientRequestInitializer}. */ @@ -189,6 +211,7 @@ public static class Builder { private String userIp; private String userAgent; private String requestReason; + private String userProject; /** * Set the API Key for outgoing requests. @@ -271,6 +294,27 @@ public String getRequestReason() { return requestReason; } + /** + * Set the user project for the request. This is a caller-specified project for quota and + * billing purposes. The caller must have serviceusage.services.use permission on the project. + * + * @param userProject the user project + * @return the builder + */ + public Builder setUserProject(String userProject) { + this.userProject = userProject; + return self(); + } + + /** + * Get the configured user project. + * + * @return the user project + */ + public String getUserProject() { + return userProject; + } + /** * Returns the constructed CommonGoogleClientRequestInitializer instance. * From 170744068ed7d088c038ae4945b3d773dbbff414 Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Fri, 7 Jun 2019 11:33:49 -0700 Subject: [PATCH 6/6] Add test for setting user project, request reason, user agent --- ...monGoogleClientRequestInitializerTest.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/google-api-client/src/test/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializerTest.java b/google-api-client/src/test/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializerTest.java index 8c73a0e3a..1973ede1a 100644 --- a/google-api-client/src/test/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializerTest.java +++ b/google-api-client/src/test/java/com/google/api/client/googleapis/services/CommonGoogleClientRequestInitializerTest.java @@ -14,10 +14,12 @@ import com.google.api.client.googleapis.testing.services.MockGoogleClient; import com.google.api.client.http.HttpContent; +import com.google.api.client.http.HttpHeaders; import com.google.api.client.testing.http.HttpTesting; import com.google.api.client.testing.http.MockHttpTransport; import com.google.api.client.util.Key; +import java.io.IOException; import junit.framework.TestCase; /** @@ -46,4 +48,46 @@ public void testInitialize() throws Exception { key.initialize(request); assertEquals("foo", request.key); } + + public void testInitializeSetsUserAgent() throws IOException { + GoogleClientRequestInitializer requestInitializer = CommonGoogleClientRequestInitializer.newBuilder() + .setUserAgent("test user agent") + .build(); + MockGoogleClient client = new MockGoogleClient.Builder(new MockHttpTransport(), HttpTesting.SIMPLE_URL, "test/", null, null) + .setGoogleClientRequestInitializer(requestInitializer) + .setApplicationName("My Application") + .build(); + MyRequest request = new MyRequest(client, "GET", "", null, String.class); + requestInitializer.initialize(request); + HttpHeaders headers = request.getRequestHeaders(); + assertEquals("test user agent", headers.getUserAgent()); + } + + public void testInitializeSetsUserProject() throws IOException { + GoogleClientRequestInitializer requestInitializer = CommonGoogleClientRequestInitializer.newBuilder() + .setUserProject("my quota project") + .build(); + MockGoogleClient client = new MockGoogleClient.Builder(new MockHttpTransport(), HttpTesting.SIMPLE_URL, "test/", null, null) + .setGoogleClientRequestInitializer(requestInitializer) + .setApplicationName("My Application") + .build(); + MyRequest request = new MyRequest(client, "GET", "", null, String.class); + requestInitializer.initialize(request); + HttpHeaders headers = request.getRequestHeaders(); + assertEquals("my quota project", headers.get("X-Goog-User-Project")); + } + + public void testInitializeSetsRequestReason() throws IOException { + GoogleClientRequestInitializer requestInitializer = CommonGoogleClientRequestInitializer.newBuilder() + .setRequestReason("some request reason") + .build(); + MockGoogleClient client = new MockGoogleClient.Builder(new MockHttpTransport(), HttpTesting.SIMPLE_URL, "test/", null, null) + .setGoogleClientRequestInitializer(requestInitializer) + .setApplicationName("My Application") + .build(); + MyRequest request = new MyRequest(client, "GET", "", null, String.class); + requestInitializer.initialize(request); + HttpHeaders headers = request.getRequestHeaders(); + assertEquals("some request reason", headers.get("X-Goog-Request-Reason")); + } }