Skip to content

Commit

Permalink
chore: Add X-Goog-Api-Client metric header to outgoing requests (#430)
Browse files Browse the repository at this point in the history
* chore: Add `X-Goog-Api-Client` metric header to outgoing requests

* fix styling

* fix typo

* fix typo

* trigger integration tests
  • Loading branch information
jonathanedey authored Nov 7, 2024
1 parent 379e391 commit b6cf20a
Show file tree
Hide file tree
Showing 18 changed files with 48 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public async Task GetPublicKeysWithoutCaching()
Assert.Equal(2, keys.Count);
Assert.Equal(2, handler.Calls);
Assert.NotSame(keys, keys2);
JwtTestUtils.AssertRequest(handler.Requests[0]);
JwtTestUtils.AssertRequest(handler.Requests[1]);
}

[Fact]
Expand Down Expand Up @@ -77,6 +79,8 @@ public async Task GetPublicKeysWithCaching()
Assert.Equal(2, keys.Count);
Assert.Equal(2, handler.Calls);
Assert.NotSame(keys, keys3);
JwtTestUtils.AssertRequest(handler.Requests[0]);
JwtTestUtils.AssertRequest(handler.Requests[1]);
}

[Fact]
Expand Down
2 changes: 2 additions & 0 deletions FirebaseAdmin/FirebaseAdmin.Tests/Auth/Jwt/IAMSignerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public async Task Signer()
Assert.Equal(Convert.ToBase64String(data), req.BytesToSign);
Assert.Equal(2, handler.Calls);
Assert.Equal("Bearer token", handler.LastRequestHeaders.Authorization?.ToString());
JwtTestUtils.AssertRequest(handler.Requests[1]);
}

[Fact]
Expand Down Expand Up @@ -112,6 +113,7 @@ public async Task Signer()
handler.LastRequestBody);
Assert.Equal(Convert.ToBase64String(data), req.BytesToSign);
Assert.Equal(1, handler.Calls);
JwtTestUtils.AssertRequest(Assert.Single(handler.Requests));
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ public async Task RevokedToken(TestConfig config)
this.CheckException(exception, expectedMessage, AuthErrorCode.RevokedIdToken);
Assert.Equal(1, handler.Calls);
config.AssertRevocationCheckRequest(handler.Requests[0].Url);
JwtTestUtils.AssertRequest(Assert.Single(handler.Requests));
}

[Theory]
Expand All @@ -458,6 +459,7 @@ public async Task ValidUnrevokedToken(TestConfig config)
Assert.Equal("testuser", decoded.Uid);
Assert.Equal(1, handler.Calls);
config.AssertRevocationCheckRequest(handler.Requests[0].Url);
JwtTestUtils.AssertRequest(Assert.Single(handler.Requests));
}

[Theory]
Expand All @@ -484,6 +486,7 @@ public async Task CheckRevokedError(TestConfig config)
Assert.NotNull(exception.HttpResponse);
Assert.Equal(1, handler.Calls);
config.AssertRevocationCheckRequest(handler.Requests[0].Url);
JwtTestUtils.AssertRequest(Assert.Single(handler.Requests));
}

[Theory]
Expand Down
5 changes: 5 additions & 0 deletions FirebaseAdmin/FirebaseAdmin.Tests/Auth/Jwt/JwtTestUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ public static void AssertRevocationCheckRequest(string tenantId, string emulator
Assert.Equal(expectedUrl, uri.ToString());
}

internal static void AssertRequest(MockMessageHandler.IncomingRequest request)
{
Assert.Contains(HttpUtils.GetMetricsHeader(), request.Headers.GetValues("X-Goog-Api-Client"));
}

private static ISigner CreateTestSigner(string filePath)
{
var credential = GoogleCredential.FromFile(filePath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ public async Task RevokedToken(TestConfig config)
this.CheckException(exception, expectedMessage, AuthErrorCode.RevokedSessionCookie);
Assert.Equal(1, handler.Calls);
JwtTestUtils.AssertRevocationCheckRequest(null, handler.Requests[0].Url);
JwtTestUtils.AssertRequest(Assert.Single(handler.Requests));
}

[Theory]
Expand All @@ -355,6 +356,7 @@ public async Task ValidUnrevokedToken(TestConfig config)
Assert.Equal("testuser", decoded.Uid);
Assert.Equal(1, handler.Calls);
JwtTestUtils.AssertRevocationCheckRequest(null, handler.Requests[0].Url);
JwtTestUtils.AssertRequest(Assert.Single(handler.Requests));
}

[Theory]
Expand All @@ -381,6 +383,7 @@ public async Task CheckRevokedError(TestConfig config)
Assert.NotNull(exception.HttpResponse);
Assert.Equal(1, handler.Calls);
JwtTestUtils.AssertRevocationCheckRequest(null, handler.Requests[0].Url);
JwtTestUtils.AssertRequest(Assert.Single(handler.Requests));
}

private void CheckException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,7 @@ internal void AssertRequest(
}

Assert.Contains(ClientVersion, request.Headers.GetValues("X-Client-Version"));
Assert.Contains(HttpUtils.GetMetricsHeader(), request.Headers.GetValues("X-Goog-Api-Client"));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ internal void AssertRequest(
var expectedPath = $"/v2/projects/{MockProjectId}{tenantInfo}/{expectedSuffix}";
Assert.Equal(expectedPath, request.Url.PathAndQuery);
Assert.Contains(ClientVersion, request.Headers.GetValues("X-Client-Version"));
Assert.Contains(HttpUtils.GetMetricsHeader(), request.Headers.GetValues("X-Goog-Api-Client"));
}

public class InvalidListOptions : IEnumerable<object[]>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ private void AssertRequest(MockMessageHandler.IncomingRequest message)
Assert.Equal(
FirebaseUserManager.ClientVersion,
message.Headers.GetValues(FirebaseUserManager.ClientVersionHeader).First());
Assert.Equal(HttpUtils.GetMetricsHeader(), message.Headers.GetValues("X-Goog-Api-Client").First());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2222,6 +2222,8 @@ internal void AssertRequest(
var expectedUrl = $"https://{IdToolkitUrl}{tenant}/{expectedSuffix}";
Assert.Equal(expectedUrl, request.Url.ToString());
}

Assert.Equal(HttpUtils.GetMetricsHeader(), request.Headers.GetValues("X-Goog-Api-Client").First());
}

private IDictionary<string, object> GetUserResponseDictionary(string response = null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@ protected sealed override Task<HttpResponseMessage> SendAsync(
protected abstract Task<HttpResponseMessage> DoSendAsync(
HttpRequestMessage request, int count, CancellationToken cancellationToken);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<AdditionalFiles Include="../../stylecop.json" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FirebaseAdmin\FirebaseAdmin.csproj" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ public async Task SendEachAsync()
Assert.Equal("projects/fir-adminintegrationtests/messages/8580920590356323124", response.Responses[0].MessageId);
Assert.Equal("projects/fir-adminintegrationtests/messages/5903525881088369386", response.Responses[1].MessageId);
Assert.Equal(2, handler.Calls);
this.CheckHeaders(handler.LastRequestHeaders);
}

[Fact]
Expand Down Expand Up @@ -245,6 +246,7 @@ public async Task SendEachAsyncWithError()
Assert.NotNull(exception.HttpResponse);

Assert.Equal(2, handler.Calls);
this.CheckHeaders(handler.LastRequestHeaders);
}

[Fact]
Expand Down Expand Up @@ -311,6 +313,7 @@ public async Task SendEachAsyncWithErrorNoDetail()
Assert.NotNull(exception.HttpResponse);

Assert.Equal(2, handler.Calls);
this.CheckHeaders(handler.LastRequestHeaders);
}

[Fact]
Expand Down Expand Up @@ -404,6 +407,7 @@ public async Task SendAllAsync()
Assert.Equal("fire-admin-dotnet", userAgent.Product.Name);
Assert.Equal(2, this.CountLinesWithPrefix(handler.LastRequestBody, VersionHeader));
Assert.Equal(2, this.CountLinesWithPrefix(handler.LastRequestBody, ApiFormatHeader));
Assert.Equal(2, this.CountLinesWithPrefix(handler.LastRequestBody, $"X-Goog-Api-Client: {HttpUtils.GetMetricsHeader()}"));
}

[Fact]
Expand Down Expand Up @@ -486,6 +490,7 @@ public async Task SendAllAsyncWithError()
Assert.Equal(1, handler.Calls);
Assert.Equal(2, this.CountLinesWithPrefix(handler.LastRequestBody, VersionHeader));
Assert.Equal(2, this.CountLinesWithPrefix(handler.LastRequestBody, ApiFormatHeader));
Assert.Equal(2, this.CountLinesWithPrefix(handler.LastRequestBody, $"X-Goog-Api-Client: {HttpUtils.GetMetricsHeader()}"));
}

[Fact]
Expand Down Expand Up @@ -564,6 +569,7 @@ public async Task SendAllAsyncWithErrorNoDetail()
Assert.Equal(1, handler.Calls);
Assert.Equal(2, this.CountLinesWithPrefix(handler.LastRequestBody, VersionHeader));
Assert.Equal(2, this.CountLinesWithPrefix(handler.LastRequestBody, ApiFormatHeader));
Assert.Equal(2, this.CountLinesWithPrefix(handler.LastRequestBody, $"X-Goog-Api-Client: {HttpUtils.GetMetricsHeader()}"));
}

[Fact]
Expand Down Expand Up @@ -778,6 +784,9 @@ private void CheckHeaders(HttpRequestHeaders header)

var apiFormatHeader = header.GetValues("X-GOOG-API-FORMAT-VERSION").First();
Assert.Equal("2", apiFormatHeader);

var metricsHeader = header.GetValues("X-Goog-Api-Client").First();
Assert.Equal(HttpUtils.GetMetricsHeader(), metricsHeader);
}

private int CountLinesWithPrefix(string body, string linePrefix)
Expand Down
2 changes: 1 addition & 1 deletion FirebaseAdmin/FirebaseAdmin.Tests/MockHttpClientFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ protected override HttpMessageHandler CreateHandler(CreateHttpClientArgs args)
return this.handler;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public async Task SuccessfulRequest()
Assert.Single(response.Result);
Assert.Equal("bar", response.Result["foo"]);
Assert.Equal(1, handler.Calls);
Assert.Equal(HttpUtils.GetMetricsHeader(), handler.LastRequestHeaders.GetValues("X-Goog-Api-Client").First());
}

[Fact]
Expand All @@ -69,6 +70,7 @@ public async Task SuccessfulAuthorizedRequest()
Assert.Single(response.Result);
Assert.Equal("bar", response.Result["foo"]);
Assert.Equal(1, handler.Calls);
Assert.Equal(HttpUtils.GetMetricsHeader(), handler.LastRequestHeaders.GetValues("X-Goog-Api-Client").First());
Assert.Equal(
"Bearer test-token",
handler.LastRequestHeaders.GetValues("Authorization").First());
Expand Down Expand Up @@ -166,6 +168,7 @@ public async Task CustomDeserializer()
Assert.Equal("bar", response.Result["foo"]);
Assert.Equal(1, handler.Calls);
Assert.Equal(1, deserializer.Count);
Assert.Equal(HttpUtils.GetMetricsHeader(), handler.LastRequestHeaders.GetValues("X-Goog-Api-Client").First());
}

[Fact]
Expand Down Expand Up @@ -244,6 +247,7 @@ public async Task RetryOnErrorResponse()
Assert.Null(exception.InnerException);
Assert.NotNull(exception.HttpResponse);
Assert.Equal(5, handler.Calls);
Assert.Equal(HttpUtils.GetMetricsHeader(), handler.LastRequestHeaders.GetValues("X-Goog-Api-Client").First());
}

[Fact]
Expand All @@ -267,6 +271,7 @@ public async Task RetryOnNetworkError()
Assert.Same(handler.Exception, exception.InnerException);
Assert.Null(exception.HttpResponse);
Assert.Equal(5, handler.Calls);
Assert.Equal(HttpUtils.GetMetricsHeader(), handler.LastRequestHeaders.GetValues("X-Goog-Api-Client").First());
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ public FCMClientServiceRequest(FCMClientService clientService, string restPath,
this.ModifyRequest = (request) =>
{
AddCommonHeaders(request);
request.Headers.Add("X-Goog-Api-Client", HttpUtils.GetMetricsHeader());
};
this.InitParameters();
}
Expand Down
1 change: 1 addition & 0 deletions FirebaseAdmin/FirebaseAdmin/Messaging/InstanceIdClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ private async Task<TopicManagementResponse> SendInstanceIdRequest(
};

request.Headers.Add("access_token_auth", "true");
request.Headers.Add("X-Goog-Api-Client", HttpUtils.GetMetricsHeader());

var response = await this.httpClient
.SendAndDeserializeAsync<InstanceIdServiceResponse>(request)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public void Dispose()
internal async Task<DeserializedResponseInfo<TResult>> SendAndDeserializeAsync<TResult>(
HttpRequestMessage request, CancellationToken cancellationToken = default)
{
request.Headers.Add("X-Goog-Api-Client", HttpUtils.GetMetricsHeader());
var info = await this.SendAndReadAsync(request, cancellationToken)
.ConfigureAwait(false);
try
Expand Down
6 changes: 6 additions & 0 deletions FirebaseAdmin/FirebaseAdmin/Util/HttpUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
Expand Down Expand Up @@ -51,6 +52,11 @@ internal static IList<string> CreateUpdateMask(object request)
return mask;
}

internal static string GetMetricsHeader()
{
return $"gl-dotnet/{Environment.Version} fire-admin/{FirebaseApp.GetSdkVersion()}";
}

private static List<string> CreateUpdateMask(JObject dictionary)
{
var mask = new List<string>();
Expand Down

0 comments on commit b6cf20a

Please sign in to comment.