|
2 | 2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | 3 |
|
4 | 4 | using System.Diagnostics; |
| 5 | +using System.Globalization; |
5 | 6 | using Microsoft.AspNetCore.Builder; |
6 | 7 | using Microsoft.AspNetCore.Http; |
7 | 8 | using Microsoft.AspNetCore.Http.Features; |
| 9 | +using Microsoft.AspNetCore.Http.Metadata; |
8 | 10 | using Microsoft.AspNetCore.Routing.Matching; |
9 | 11 | using Microsoft.AspNetCore.Routing.TestObjects; |
10 | 12 | using Microsoft.AspNetCore.Testing; |
@@ -81,7 +83,7 @@ public async Task Invoke_OnCall_WritesToConfiguredLogger() |
81 | 83 |
|
82 | 84 | // Assert |
83 | 85 | Assert.Empty(sink.Scopes); |
84 | | - var write = Assert.Single(sink.Writes); |
| 86 | + var write = Assert.Single(sink.Writes.Where(w => w.EventId.Name == "MatchSuccess")); |
85 | 87 | Assert.Equal(expectedMessage, write.State?.ToString()); |
86 | 88 | Assert.True(eventFired); |
87 | 89 | } |
@@ -262,6 +264,162 @@ public async Task Invoke_CheckForFallbackMetadata_LogIfPresent(bool hasFallbackM |
262 | 264 | } |
263 | 265 | } |
264 | 266 |
|
| 267 | + [Fact] |
| 268 | + public async Task Endpoint_BodySizeFeatureIsReadOnly() |
| 269 | + { |
| 270 | + // Arrange |
| 271 | + var sink = new TestSink(TestSink.EnableWithTypeName<EndpointRoutingMiddleware>); |
| 272 | + var loggerFactory = new TestLoggerFactory(sink, enabled: true); |
| 273 | + var logger = new Logger<EndpointRoutingMiddleware>(loggerFactory); |
| 274 | + |
| 275 | + var httpContext = CreateHttpContext(); |
| 276 | + var expectedRequestSizeLimit = 50; |
| 277 | + var maxRequestBodySizeFeature = new FakeHttpMaxRequestBodySizeFeature(expectedRequestSizeLimit, true); |
| 278 | + httpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(maxRequestBodySizeFeature); |
| 279 | + |
| 280 | + var metadata = new List<object> { new RequestSizeLimitMetadata(100) }; |
| 281 | + var middleware = CreateMiddleware( |
| 282 | + logger: logger, |
| 283 | + matcherFactory: new TestMatcherFactory(isHandled: true, setEndpointCallback: c => |
| 284 | + { |
| 285 | + c.SetEndpoint(new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(metadata), "myapp")); |
| 286 | + })); |
| 287 | + |
| 288 | + // Act |
| 289 | + await middleware.Invoke(httpContext); |
| 290 | + |
| 291 | + // Assert |
| 292 | + var write = Assert.Single(sink.Writes.Where(w => w.EventId.Name == "FeatureIsReadOnly")); |
| 293 | + Assert.Equal($"A request body size limit could not be applied. The {nameof(IHttpMaxRequestBodySizeFeature)} for the server is read-only.", write.Message); |
| 294 | + |
| 295 | + var actualRequestSizeLimit = maxRequestBodySizeFeature.MaxRequestBodySize; |
| 296 | + Assert.Equal(expectedRequestSizeLimit, actualRequestSizeLimit); |
| 297 | + } |
| 298 | + |
| 299 | + [Fact] |
| 300 | + public async Task Endpoint_DoesNotHaveBodySizeFeature() |
| 301 | + { |
| 302 | + // Arrange |
| 303 | + var sink = new TestSink(TestSink.EnableWithTypeName<EndpointRoutingMiddleware>); |
| 304 | + var loggerFactory = new TestLoggerFactory(sink, enabled: true); |
| 305 | + var logger = new Logger<EndpointRoutingMiddleware>(loggerFactory); |
| 306 | + |
| 307 | + var httpContext = CreateHttpContext(); |
| 308 | + |
| 309 | + var metadata = new List<object> { new RequestSizeLimitMetadata(100) }; |
| 310 | + var middleware = CreateMiddleware( |
| 311 | + logger: logger, |
| 312 | + matcherFactory: new TestMatcherFactory(isHandled: true, setEndpointCallback: c => |
| 313 | + { |
| 314 | + c.SetEndpoint(new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(metadata), "myapp")); |
| 315 | + })); |
| 316 | + |
| 317 | + // Act |
| 318 | + await middleware.Invoke(httpContext); |
| 319 | + |
| 320 | + // Assert |
| 321 | + var write = Assert.Single(sink.Writes.Where(w => w.EventId.Name == "FeatureNotFound")); |
| 322 | + Assert.Equal($"A request body size limit could not be applied. This server does not support the {nameof(IHttpMaxRequestBodySizeFeature)}.", write.Message); |
| 323 | + } |
| 324 | + |
| 325 | + [Fact] |
| 326 | + public async Task Endpoint_DoesNotHaveSizeLimitMetadata() |
| 327 | + { |
| 328 | + // Arrange |
| 329 | + var sink = new TestSink(TestSink.EnableWithTypeName<EndpointRoutingMiddleware>); |
| 330 | + var loggerFactory = new TestLoggerFactory(sink, enabled: true); |
| 331 | + var logger = new Logger<EndpointRoutingMiddleware>(loggerFactory); |
| 332 | + |
| 333 | + var httpContext = CreateHttpContext(); |
| 334 | + var expectedRequestSizeLimit = 50; |
| 335 | + var maxRequestBodySizeFeature = new FakeHttpMaxRequestBodySizeFeature(expectedRequestSizeLimit, true); |
| 336 | + httpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(maxRequestBodySizeFeature); |
| 337 | + |
| 338 | + var middleware = CreateMiddleware( |
| 339 | + logger: logger, |
| 340 | + matcherFactory: new TestMatcherFactory(isHandled: true, setEndpointCallback: c => |
| 341 | + { |
| 342 | + c.SetEndpoint(new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(), "myapp")); |
| 343 | + })); |
| 344 | + |
| 345 | + // Act |
| 346 | + await middleware.Invoke(httpContext); |
| 347 | + |
| 348 | + // Assert |
| 349 | + var write = Assert.Single(sink.Writes.Where(w => w.EventId.Name == "MetadataNotFound")); |
| 350 | + Assert.Equal($"The endpoint does not specify the {nameof(IRequestSizeLimitMetadata)}.", write.Message); |
| 351 | + } |
| 352 | + |
| 353 | + [Theory] |
| 354 | + [InlineData(true)] |
| 355 | + [InlineData(false)] |
| 356 | + public async Task Endpoint_HasBodySizeFeature_SetUsingSizeLimitMetadata(bool isRequestSizeLimitDisabled) |
| 357 | + { |
| 358 | + // Arrange |
| 359 | + var sink = new TestSink(TestSink.EnableWithTypeName<EndpointRoutingMiddleware>); |
| 360 | + var loggerFactory = new TestLoggerFactory(sink, enabled: true); |
| 361 | + var logger = new Logger<EndpointRoutingMiddleware>(loggerFactory); |
| 362 | + |
| 363 | + var httpContext = CreateHttpContext(); |
| 364 | + long? expectedRequestSizeLimit = isRequestSizeLimitDisabled ? null : 500L; |
| 365 | + var maxRequestBodySizeFeature = new FakeHttpMaxRequestBodySizeFeature(expectedRequestSizeLimit, false); |
| 366 | + httpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(maxRequestBodySizeFeature); |
| 367 | + var metadata = new RequestSizeLimitMetadata(expectedRequestSizeLimit); |
| 368 | + |
| 369 | + var middleware = CreateMiddleware( |
| 370 | + logger: logger, |
| 371 | + matcherFactory: new TestMatcherFactory(isHandled: true, setEndpointCallback: c => |
| 372 | + { |
| 373 | + c.SetEndpoint(new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(metadata), "myapp")); |
| 374 | + })); |
| 375 | + |
| 376 | + // Act |
| 377 | + await middleware.Invoke(httpContext); |
| 378 | + |
| 379 | + // Assert |
| 380 | + |
| 381 | + if (isRequestSizeLimitDisabled) |
| 382 | + { |
| 383 | + var write = Assert.Single(sink.Writes.Where(w => w.EventId.Name == "MaxRequestBodySizeDisabled")); |
| 384 | + Assert.Equal("The maximum request body size has been disabled.", write.Message); |
| 385 | + } |
| 386 | + else |
| 387 | + { |
| 388 | + var write = Assert.Single(sink.Writes.Where(w => w.EventId.Name == "MaxRequestBodySizeSet")); |
| 389 | + Assert.Equal($"The maximum request body size has been set to {expectedRequestSizeLimit}.", write.Message); |
| 390 | + } |
| 391 | + |
| 392 | + var actualRequestSizeLimit = maxRequestBodySizeFeature.MaxRequestBodySize; |
| 393 | + Assert.Equal(expectedRequestSizeLimit, actualRequestSizeLimit); |
| 394 | + } |
| 395 | + |
| 396 | + private class RequestSizeLimitMetadata(long? maxRequestBodySize) : IRequestSizeLimitMetadata |
| 397 | + { |
| 398 | + |
| 399 | + public long? MaxRequestBodySize => maxRequestBodySize; |
| 400 | + } |
| 401 | + |
| 402 | + private class FakeHttpMaxRequestBodySizeFeature : IHttpMaxRequestBodySizeFeature |
| 403 | + { |
| 404 | + public FakeHttpMaxRequestBodySizeFeature( |
| 405 | + long? maxRequestBodySize = null, |
| 406 | + bool isReadOnly = false) |
| 407 | + { |
| 408 | + MaxRequestBodySize = maxRequestBodySize; |
| 409 | + IsReadOnly = isReadOnly; |
| 410 | + } |
| 411 | + |
| 412 | + public bool IsReadOnly { get; } |
| 413 | + |
| 414 | + public long? MaxRequestBodySize { get; set; } |
| 415 | + } |
| 416 | + |
| 417 | + private static void AssertLog(WriteContext log, LogLevel level, string message) |
| 418 | + { |
| 419 | + Assert.Equal(level, log.LogLevel); |
| 420 | + Assert.Equal(message, log.State.ToString()); |
| 421 | + } |
| 422 | + |
265 | 423 | private HttpContext CreateHttpContext() |
266 | 424 | { |
267 | 425 | var httpContext = new DefaultHttpContext |
|
0 commit comments