Skip to content

Commit 264b808

Browse files
Default User-Agent on HttpClient: net10.0, CreateApplicationBuilder, ConfigureHttpClientDefaults, on-the-wire tests
1 parent 5f9e917 commit 264b808

5 files changed

Lines changed: 144 additions & 22 deletions

File tree

‎aspnetcore-features/HowToSetDefaultUserAgentOnHttpClient/HowToSetDefaultUserAgentOnHttpClient/HowToSetDefaultUserAgentOnHttpClient.csproj‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFramework>net8.0</TargetFramework>
5+
<TargetFramework>net10.0</TargetFramework>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<Nullable>enable</Nullable>
88
</PropertyGroup>
99

1010
<ItemGroup>
11-
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
12-
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
11+
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.13" />
12+
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.13" />
1313
</ItemGroup>
1414

1515
</Project>

‎aspnetcore-features/HowToSetDefaultUserAgentOnHttpClient/HowToSetDefaultUserAgentOnHttpClient/Program.cs‎

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,37 +9,60 @@ public static void Main(string[] args)
99
{
1010
var host = BuildHost();
1111

12-
var httpClientFactory = host.Services.GetService<IHttpClientFactory>();
12+
var httpClientFactory = host.Services.GetRequiredService<IHttpClientFactory>();
1313

1414
GetDefaultAgentOnHttpClient(httpClientFactory);
1515

16+
SetUserAgentOnHttpRequestMessage("CodeMazeDesktopApp/1.1");
17+
1618
SetUserAgentOnHttpRequestMessage("CodeMazeDesktopApp", "1.1");
1719
}
1820

1921
public static IHost BuildHost()
2022
{
21-
var builder = new HostBuilder()
22-
.ConfigureServices(services =>
23-
{
24-
services.AddHttpClient("CodeMazeHttpClient", client =>
25-
{
26-
var productHeaderValue = new ProductHeaderValue(name: "CodeMazeDesktopApp", version: "1.1");
27-
var productInfoHeaderValue = new ProductInfoHeaderValue(productHeaderValue);
23+
var builder = Host.CreateApplicationBuilder();
24+
25+
builder.Services.AddHttpClient("CodeMazeHttpClient", client =>
26+
{
27+
var productHeaderValue = new ProductHeaderValue(name: "CodeMazeDesktopApp", version: "1.1");
28+
var productInfoHeaderValue = new ProductInfoHeaderValue(productHeaderValue);
29+
30+
client.DefaultRequestHeaders.UserAgent.Add(productInfoHeaderValue);
31+
});
32+
33+
return builder.Build();
34+
}
35+
36+
public static IHost BuildHostWithUserAgentForAllClients()
37+
{
38+
var builder = Host.CreateApplicationBuilder();
2839

29-
client.DefaultRequestHeaders.UserAgent.Add(productInfoHeaderValue);
30-
});
40+
builder.Services.ConfigureHttpClientDefaults(httpClientBuilder =>
41+
{
42+
httpClientBuilder.ConfigureHttpClient(client =>
43+
{
44+
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("CodeMazeDesktopApp", "1.1"));
3145
});
46+
});
3247

3348
return builder.Build();
3449
}
3550

3651
public static string GetDefaultAgentOnHttpClient(IHttpClientFactory httpClientFactory)
37-
{
52+
{
3853
var httpClient = httpClientFactory.CreateClient("CodeMazeHttpClient");
3954

4055
return httpClient.DefaultRequestHeaders.UserAgent.ToString();
4156
}
4257

58+
public static string SetUserAgentOnHttpRequestMessage(string userAgentValue)
59+
{
60+
var httpRequestMessage = new HttpRequestMessage();
61+
httpRequestMessage.Headers.Add("User-Agent", userAgentValue);
62+
63+
return httpRequestMessage.Headers.UserAgent.ToString();
64+
}
65+
4366
public static string SetUserAgentOnHttpRequestMessage(string productName, string productVersion)
4467
{
4568
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "/users/1234");
@@ -51,4 +74,4 @@ public static string SetUserAgentOnHttpRequestMessage(string productName, string
5174

5275
return httpRequestMessage.Headers.UserAgent.ToString();
5376
}
54-
}
77+
}

‎aspnetcore-features/HowToSetDefaultUserAgentOnHttpClient/Tests/ProgramUnitTests.cs‎

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ namespace Tests;
55

66
public class ProgramUnitTests
77
{
8+
[Fact]
9+
public void WhenUserAgentStringIsProvided_ThenSetUserAgentOnHttpRequestMessageSetsTheHeader()
10+
{
11+
//Arrange
12+
var userAgentValue = "CodeMazeDesktopApp/1.1";
13+
14+
//Act
15+
var actualOutput = Program.SetUserAgentOnHttpRequestMessage(userAgentValue);
16+
17+
//Assert
18+
Assert.Equal(userAgentValue, actualOutput);
19+
}
20+
821
[Fact]
922
public void WhenUserAgentPropertyIsProvided_ThenSetUserAgentOnHttpRequestMessageSetsTheHeader()
1023
{
@@ -30,11 +43,29 @@ public void WhenHttpClientIsRegisteredWithHostBuilder_ThenHttpClientGetsDefaultU
3043

3144
//Act
3245
var host = Program.BuildHost();
33-
var httpClientFactory = host.Services.GetService<IHttpClientFactory>();
46+
var httpClientFactory = host.Services.GetRequiredService<IHttpClientFactory>();
3447

3548
var actualOutput = Program.GetDefaultAgentOnHttpClient(httpClientFactory);
3649

3750
//Assert
3851
Assert.Equal(expectedOutput, actualOutput);
3952
}
40-
}
53+
54+
[Fact]
55+
public void WhenClientDefaultsAreConfigured_ThenEveryClientGetsDefaultUserAgent()
56+
{
57+
//Arrange
58+
var expectedOutput = "CodeMazeDesktopApp/1.1";
59+
60+
//Act
61+
var host = Program.BuildHostWithUserAgentForAllClients();
62+
var httpClientFactory = host.Services.GetRequiredService<IHttpClientFactory>();
63+
64+
var namedClient = httpClientFactory.CreateClient("AnyName");
65+
var defaultClient = httpClientFactory.CreateClient();
66+
67+
//Assert
68+
Assert.Equal(expectedOutput, namedClient.DefaultRequestHeaders.UserAgent.ToString());
69+
Assert.Equal(expectedOutput, defaultClient.DefaultRequestHeaders.UserAgent.ToString());
70+
}
71+
}

‎aspnetcore-features/HowToSetDefaultUserAgentOnHttpClient/Tests/Tests.csproj‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net8.0</TargetFramework>
4+
<TargetFramework>net10.0</TargetFramework>
55
<ImplicitUsings>enable</ImplicitUsings>
66
<Nullable>enable</Nullable>
77

@@ -10,16 +10,20 @@
1010
</PropertyGroup>
1111

1212
<ItemGroup>
13-
<PackageReference Include="coverlet.collector" Version="6.0.0" />
14-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
15-
<PackageReference Include="xunit" Version="2.5.3" />
16-
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
13+
<PackageReference Include="coverlet.collector" Version="10.1.0" />
14+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.11.0" />
15+
<PackageReference Include="xunit" Version="2.9.3" />
16+
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.1" />
1717
</ItemGroup>
1818

1919
<ItemGroup>
2020
<ProjectReference Include="..\HowToSetDefaultUserAgentOnHttpClient\HowToSetDefaultUserAgentOnHttpClient.csproj" />
2121
</ItemGroup>
2222

23+
<ItemGroup>
24+
<FrameworkReference Include="Microsoft.AspNetCore.App" />
25+
</ItemGroup>
26+
2327
<ItemGroup>
2428
<Using Include="Xunit" />
2529
</ItemGroup>
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using HowToSetDefaultUserAgentOnHttpClient;
2+
using Microsoft.AspNetCore.Builder;
3+
using Microsoft.AspNetCore.Hosting;
4+
using Microsoft.AspNetCore.Http;
5+
using Microsoft.Extensions.DependencyInjection;
6+
using System.Net.Http.Headers;
7+
8+
namespace Tests;
9+
10+
public class UserAgentOnTheWireTests : IAsyncLifetime
11+
{
12+
private WebApplication _app = null!;
13+
private string _baseAddress = null!;
14+
15+
public async Task InitializeAsync()
16+
{
17+
var builder = WebApplication.CreateBuilder();
18+
builder.WebHost.UseUrls("http://127.0.0.1:0");
19+
20+
_app = builder.Build();
21+
_app.MapGet("/user-agent", (HttpRequest request) => request.Headers.UserAgent.ToString());
22+
23+
await _app.StartAsync();
24+
_baseAddress = _app.Urls.First();
25+
}
26+
27+
public async Task DisposeAsync() => await _app.DisposeAsync();
28+
29+
[Fact]
30+
public async Task WhenPlainHttpClientCallsTheServer_ThenNoUserAgentArrives()
31+
{
32+
using var httpClient = new HttpClient();
33+
34+
var userAgent = await httpClient.GetStringAsync($"{_baseAddress}/user-agent");
35+
36+
Assert.Equal(string.Empty, userAgent);
37+
}
38+
39+
[Fact]
40+
public async Task WhenNamedClientCallsTheServer_ThenServerReadsTheDefaultUserAgent()
41+
{
42+
var httpClientFactory = Program.BuildHost().Services.GetRequiredService<IHttpClientFactory>();
43+
var httpClient = httpClientFactory.CreateClient("CodeMazeHttpClient");
44+
45+
var userAgent = await httpClient.GetStringAsync($"{_baseAddress}/user-agent");
46+
47+
Assert.Equal("CodeMazeDesktopApp/1.1", userAgent);
48+
}
49+
50+
[Fact]
51+
public async Task WhenRequestSetsItsOwnUserAgent_ThenItReplacesTheDefault()
52+
{
53+
var httpClientFactory = Program.BuildHost().Services.GetRequiredService<IHttpClientFactory>();
54+
var httpClient = httpClientFactory.CreateClient("CodeMazeHttpClient");
55+
56+
var request = new HttpRequestMessage(HttpMethod.Get, $"{_baseAddress}/user-agent");
57+
request.Headers.UserAgent.Add(new ProductInfoHeaderValue("CodeMazeReportJob", "2.0"));
58+
59+
var response = await httpClient.SendAsync(request);
60+
var userAgent = await response.Content.ReadAsStringAsync();
61+
62+
Assert.Equal("CodeMazeReportJob/2.0", userAgent);
63+
}
64+
}

0 commit comments

Comments
 (0)