|
16 | 16 |
|
17 | 17 | #endregion |
18 | 18 |
|
| 19 | +using System.Net; |
| 20 | +using System.Net.Http.Headers; |
19 | 21 | using Greet; |
20 | 22 | using Grpc.Core; |
21 | 23 | using Grpc.Net.Client.Internal; |
@@ -144,27 +146,93 @@ public void CreateClient_NoAddress_ThrowError() |
144 | 146 | } |
145 | 147 |
|
146 | 148 | [Test] |
147 | | - public void CreateClient_ConfigureHttpClient_ThrowError() |
| 149 | + public async Task CreateClient_ConfigureHttpClient_LogMessage() |
148 | 150 | { |
149 | 151 | // Arrange |
| 152 | + var testSink = new TestSink(); |
| 153 | + Uri? requestUri = null; |
| 154 | + HttpRequestHeaders? requestHeaders = null; |
| 155 | + |
150 | 156 | var services = new ServiceCollection(); |
| 157 | + services.AddLogging(configure => configure.SetMinimumLevel(LogLevel.Trace)); |
| 158 | + services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, TestLoggerProvider>(s => new TestLoggerProvider(testSink, true))); |
151 | 159 | services |
152 | 160 | .AddGrpcClient<TestGreeterClient>() |
153 | | - .ConfigureHttpClient(options => options.BaseAddress = new Uri("http://contoso")) |
| 161 | + .ConfigureHttpClient(options => |
| 162 | + { |
| 163 | + options.BaseAddress = new Uri("http://contoso"); |
| 164 | + options.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", "abc"); |
| 165 | + }) |
| 166 | + .ConfigurePrimaryHttpMessageHandler(() => |
| 167 | + { |
| 168 | + return TestHttpMessageHandler.Create(async r => |
| 169 | + { |
| 170 | + requestUri = r.RequestUri; |
| 171 | + requestHeaders = r.Headers; |
| 172 | + |
| 173 | + var streamContent = await ClientTestHelpers.CreateResponseContent(new HelloReply()).DefaultTimeout(); |
| 174 | + return ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent); |
| 175 | + }); |
| 176 | + }); |
| 177 | + |
| 178 | + var serviceProvider = services.BuildServiceProvider(validateScopes: true); |
| 179 | + |
| 180 | + var clientFactory = CreateGrpcClientFactory(serviceProvider); |
| 181 | + |
| 182 | + // Act |
| 183 | + var client = clientFactory.CreateClient<TestGreeterClient>(nameof(TestGreeterClient)); |
| 184 | + var response = await client.SayHelloAsync(new HelloRequest()).ResponseAsync.DefaultTimeout(); |
| 185 | + |
| 186 | + // Assert |
| 187 | + Assert.AreEqual("http://contoso", client.CallInvoker.Channel.Address.OriginalString); |
| 188 | + Assert.AreEqual(new Uri("http://contoso/greet.Greeter/SayHello"), requestUri); |
| 189 | + Assert.AreEqual("bearer abc", requestHeaders!.GetValues("authorization").Single()); |
| 190 | + |
| 191 | + Assert.IsTrue(testSink.Writes.Any(w => w.EventId.Name == "HttpClientActionsPartiallySupported")); |
| 192 | + } |
| 193 | + |
| 194 | + [Test] |
| 195 | + public async Task CreateClient_ConfigureHttpClient_OverridenByGrpcConfiguration() |
| 196 | + { |
| 197 | + // Arrange |
| 198 | + Uri? requestUri = null; |
| 199 | + HttpRequestHeaders? requestHeaders = null; |
| 200 | + |
| 201 | + var services = new ServiceCollection(); |
| 202 | + services |
| 203 | + .AddGrpcClient<TestGreeterClient>(o => o.Address = new Uri("http://eshop")) |
| 204 | + .ConfigureHttpClient(options => |
| 205 | + { |
| 206 | + options.BaseAddress = new Uri("http://contoso"); |
| 207 | + options.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", "abc"); |
| 208 | + options.DefaultRequestHeaders.TryAddWithoutValidation("HTTPCLIENT-KEY", "httpclient-value"); |
| 209 | + }) |
154 | 210 | .ConfigurePrimaryHttpMessageHandler(() => |
155 | 211 | { |
156 | | - return new NullHttpHandler(); |
| 212 | + return TestHttpMessageHandler.Create(async r => |
| 213 | + { |
| 214 | + requestUri = r.RequestUri; |
| 215 | + requestHeaders = r.Headers; |
| 216 | + |
| 217 | + var streamContent = await ClientTestHelpers.CreateResponseContent(new HelloReply()).DefaultTimeout(); |
| 218 | + return ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent); |
| 219 | + }); |
157 | 220 | }); |
158 | 221 |
|
159 | 222 | var serviceProvider = services.BuildServiceProvider(validateScopes: true); |
160 | 223 |
|
161 | 224 | var clientFactory = CreateGrpcClientFactory(serviceProvider); |
162 | 225 |
|
163 | 226 | // Act |
164 | | - var ex = Assert.Throws<InvalidOperationException>(() => clientFactory.CreateClient<TestGreeterClient>(nameof(TestGreeterClient)))!; |
| 227 | + var client = clientFactory.CreateClient<TestGreeterClient>(nameof(TestGreeterClient)); |
| 228 | + var response = await client.SayHelloAsync(new HelloRequest(), headers: new Metadata { new Metadata.Entry("authorization", "bearer 123"), new Metadata.Entry("call-key", "call-value") }).ResponseAsync.DefaultTimeout(); |
165 | 229 |
|
166 | 230 | // Assert |
167 | | - Assert.AreEqual("The ConfigureHttpClient method is not supported when creating gRPC clients. Unable to create client with name 'TestGreeterClient'.", ex.Message); |
| 231 | + Assert.AreEqual("http://eshop", client.CallInvoker.Channel.Address.OriginalString); |
| 232 | + Assert.AreEqual(new Uri("http://eshop/greet.Greeter/SayHello"), requestUri); |
| 233 | + Assert.AreEqual("bearer 123", requestHeaders!.GetValues("authorization").Single()); |
| 234 | + Assert.AreEqual("httpclient-value", requestHeaders!.GetValues("httpclient-key").Single()); |
| 235 | + Assert.AreEqual("call-value", requestHeaders!.GetValues("call-key").Single()); |
168 | 236 | } |
169 | 237 |
|
170 | 238 | #if NET462 |
@@ -292,6 +360,10 @@ internal class TestGreeterClient : Greeter.GreeterClient |
292 | 360 | { |
293 | 361 | public TestGreeterClient(CallInvoker callInvoker) : base(callInvoker) |
294 | 362 | { |
| 363 | + if (callInvoker is CallOptionsConfigurationInvoker callOptionsInvoker) |
| 364 | + { |
| 365 | + callInvoker = callOptionsInvoker.InnerInvoker; |
| 366 | + } |
295 | 367 | CallInvoker = (HttpClientCallInvoker)callInvoker; |
296 | 368 | } |
297 | 369 |
|
|
0 commit comments