public async Task ExceptionHandler_logs_and_returns_errorId()
        {
            // Arrange
            var expectedException = new Exception("Any exception...");
            var logger            = new Mock <ILogger <ExceptionHandlerMiddleware> >();
            var exceptionHandler  = new ExceptionHandlerMiddleware(
                (innerHttpContext) => { throw expectedException; },
                logger.Object
                );

            var context = GetContext();

            // Act
            await exceptionHandler.Invoke(context);

            var resultMessage = GetResultMessage(context);

            // Assert
            Assert.NotEqual(Guid.Empty, resultMessage.ErrorId);
            logger.Verify(l =>
                          l.Log(
                              LogLevel.Error,
                              0,
                              It.Is <FormattedLogValues>(v => v.ToString() == $"[ErrorId={resultMessage.ErrorId}] {context.Request.Method} {context.Request.Path}"),
                              It.Is <Exception>(e => e == expectedException),
                              It.IsAny <Func <object, Exception, string> >())
                          );
        }
        public async Task WhenInfrastrucureExceptionIsRaised_ExceptionHandlerMiddlewareShouldHandleItToCustomErrorResponseAndBadRequestHttpStatus()
        {
            // Arrange
            var middleware = new ExceptionHandlerMiddleware((innerHttpContext) =>
            {
                throw new InfrastructureException("Test", "Test");
            });

            var context = new DefaultHttpContext();

            context.Response.Body = new MemoryStream();


            //Act
            await middleware.Invoke(context, _fixture.CurrentEnvironment);

            context.Response.Body.Seek(0, SeekOrigin.Begin);
            var reader     = new StreamReader(context.Response.Body);
            var streamText = reader.ReadToEnd();
            var response   = JsonConvert.DeserializeObject <ErrorResponse>(streamText);

            //Assert
            response.ShouldNotBe(null);
            response.ShouldBeOfType <ErrorResponse>();
            response.Code.ShouldBe("Test");
            response.Message.ShouldBe("Test");
            context.Response.StatusCode.ShouldBe((int)HttpStatusCode.BadRequest);
        }
        public async Task OnlyLogsOnce()
        {
            var uuid              = string.Empty;
            var optionsMock       = new Mock <IOptions <RollbarOptions> >();
            var rollbarClientMock = new Mock <RollbarClient>(optionsMock.Object);

            rollbarClientMock.SetupSequence(m => m.Send(It.IsAny <Payloads.Payload>()))
            .Returns(() => ReturnItem("test"))
            .Returns(() => ReturnItem("fail"));
            var httpContextMock = new Mock <HttpContext>();

            httpContextMock
            .Setup(h => h.Features.Set(It.IsAny <IRollbarResponseFeature>()));
            var rollbar    = new Rollbar(new IBuilder[] { }, new IExceptionBuilder[] { }, rollbarClientMock.Object);
            var middleware = new ExceptionHandlerMiddleware(context =>
            {
                try
                {
                    throw new Exception("Middleware tests");
                }
                catch (Exception exception)
                {
                    rollbar.SendException(exception).Wait();
                    throw;
                }
            });
            await Assert.ThrowsAsync <Exception>(async() => await middleware.Invoke(httpContextMock.Object, rollbar));

            rollbarClientMock.Verify(m => m.Send(It.IsAny <Payloads.Payload>()), Times.Once());
            httpContextMock.Verify(m => m.Features.Set(It.Is <IRollbarResponseFeature>(f => f.Uuid == "test")));
        }
        public async Task WhenAnUnexpectedExceptionIsRaised_AnExceptionErrorWillBeReturned_WithInternalServerErrorHttpStatus()
        {
            // Arrange
            var            thrownException  = new Exception("Exception with a parameter: {Param1}");
            ExceptionError expectedResponse = new ExceptionError(System.Net.HttpStatusCode.InternalServerError, thrownException, string.Empty);
            var            middleware       = new ExceptionHandlerMiddleware((innerHttpContext) =>
            {
                throw thrownException;
            }, _logger);

            var context = new DefaultHttpContext();

            context.Response.Body = new MemoryStream();

            //Act
            await middleware.Invoke(context);

            context.Response.Body.Seek(0, SeekOrigin.Begin);
            var reader         = new StreamReader(context.Response.Body);
            var streamText     = reader.ReadToEnd();
            var actualResponse = JsonConvert.DeserializeObject <ExceptionError>(streamText);

            //Assert
            Assert.Equal(expectedResponse.StatusCode, actualResponse.StatusCode);
            Assert.Equal(expectedResponse.StatusCode, context.Response.StatusCode);
            Assert.Equal(expectedResponse.StatusMessage, actualResponse.StatusMessage);
            Assert.Equal(expectedResponse.ErrorMessage, actualResponse.ErrorMessage);
        }
Пример #5
0
        public async Task InvokeAsyncThrowsExceptionTest()
        {
            var problemDetailsFactory            = SetupProblemDetailsFactory();
            var expectedProblemDetails           = problemDetailsFactory.InternalServerError();
            var expectedSerializedProblemDetails = JsonSerializer.Serialize(expectedProblemDetails);
            var expectedProblemDetailsBytes      = Encoding.UTF8.GetBytes(expectedSerializedProblemDetails);
            var expectedArgumentException        = new ArgumentException("Test Message");

            var headers = SetupHeaders();

            var mockLogger = new Mock <ILogger <ExceptionHandlerMiddleware> >();

            var mockHttpRequest     = mockLogger.SetupHttpRequest();
            var mockHttpResponse    = SetupHttpResponse(mockLogger, headers, expectedProblemDetailsBytes);
            var mockConnectionInfo  = mockLogger.SetupConnectionInfo();
            var mockHttpContext     = mockLogger.SetupHttpContext(mockHttpRequest, mockHttpResponse, mockConnectionInfo);
            var mockRequestDelegate = SetupRequestDelegate(mockHttpContext, expectedArgumentException);

            var middleware = new ExceptionHandlerMiddleware(mockRequestDelegate.Object, mockLogger.Object, problemDetailsFactory);
            await middleware.InvokeAsync(mockHttpContext.Object);

            VerifyRequestDelegate(mockHttpContext, mockRequestDelegate);
            AssertHeaders(headers);
            VerifyContext(mockHttpContext);
            VerifyHttpResponse(mockHttpResponse, expectedProblemDetailsBytes);
            VerifyLogs(mockLogger, expectedSerializedProblemDetails, expectedArgumentException);
            mockLogger.VerifyBeginScope("Internal Server Error");
            mockLogger.VerifyLogResponse();
        }
        public async Task ExceptionHandler_returns_ExceptionResultMessage()
        {
            // Arrange
            var expectedException = new Exception("Any exception...");
            var logger            = new Mock <ILogger <ExceptionHandlerMiddleware> >();
            var exceptionHandler  = new ExceptionHandlerMiddleware(
                (innerHttpContext) => { throw expectedException; },
                logger.Object
                );

            var context = GetContext();

            // Act
            await exceptionHandler.Invoke(context);

            var resultMessage = GetResultMessage(context);

            // Assert
            Assert.NotNull(resultMessage);
            Assert.NotEqual(Guid.Empty, resultMessage.ErrorId);
            Assert.Equal(
                "An error occurred and your message couldn't be processed. If the error persists, contact the admin informing the error id provided.",
                resultMessage.Message
                );
        }
        public async Task WhenAnApiBaseExceptionIsRaised_AExceptionErrorWillBeReturned_WithAProvidedHttpStatus()
        {
            // Arrange
            ApiBaseException thrownException  = new ApiBaseException(System.Net.HttpStatusCode.GatewayTimeout, "A Test Exception");
            ExceptionError   expectedResponse = new ExceptionError(System.Net.HttpStatusCode.GatewayTimeout, thrownException, string.Empty);

            var middleware = new ExceptionHandlerMiddleware((innerHttpContext) =>
            {
                throw thrownException;
            }, _logger);

            var context = new DefaultHttpContext();

            context.Response.Body = new MemoryStream();

            //Act
            await middleware.Invoke(context);

            context.Response.Body.Seek(0, SeekOrigin.Begin);
            var reader         = new StreamReader(context.Response.Body);
            var streamText     = reader.ReadToEnd();
            var actualResponse = JsonConvert.DeserializeObject <ExceptionError>(streamText);

            //Assert
            Assert.Equal(expectedResponse.StatusCode, actualResponse.StatusCode);
            Assert.Equal(expectedResponse.StatusCode, context.Response.StatusCode);
            Assert.Equal(expectedResponse.StatusMessage, actualResponse.StatusMessage);
            Assert.Equal(expectedResponse.ErrorMessage, actualResponse.ErrorMessage);
        }
Пример #8
0
        public async Task InvokeAsync_ThrowsExceptionWhenNextIsNotSet()
        {
            ExceptionHandlerMiddleware middleware = new ExceptionHandlerMiddleware();
            var context   = this.GetContext();
            var exception = await ShouldThrowAsyncExtensions.ShouldThrowAsync <MiddlewarePipelineException>(() => middleware.InvokeAsync(context));

            exception.Message.ShouldContain("must have a Next middleware");
        }
Пример #9
0
        public async Task InvokeAsync_NoExceptionFromNextMiddleware()
        {
            ExceptionHandlerMiddleware middleware = new ExceptionHandlerMiddleware()
            {
                Next = new DummyMiddleware()
            };
            var context = this.GetContext();
            await middleware.InvokeAsync(context);

            context.Response.StatusCode.ShouldBe(202);
        }
        public async Task WhenAModelStateValidationExceptionIsRaised_AValidationErrorWillBeReturned_WithBadRequestHttpStatus()
        {
            // Arrange
            var requestDTO = new RequestModelBasic()
            {
                Id = 0, Message = string.Empty, CreatedOn = DateTime.Now
            };

            // Perform a validation using ModelState
            var modelState = new ModelStateDictionary();

            modelState.AddModelError("Error_1", "Input string '1.3' is not a valid integer. Path 'userId', line 2, position 17.");
            modelState["Error_1"].RawValue = "1.3";
            modelState.AddModelError("Error_2", "Could not convert string to DateTime: 2018:10. Path 'momentsDate', line 4, position 28.");
            ValidationException thrownException = new ValidationException("bad_request", modelState, string.Empty);

            ValidationError expectedResponse = new ValidationError(thrownException.ValidationFailures, string.Empty);

            var middleware = new ExceptionHandlerMiddleware((innerHttpContext) =>
            {
                throw thrownException;
            }, _logger);

            var context = new DefaultHttpContext();

            context.Response.Body = new MemoryStream();

            //Act
            await middleware.Invoke(context);

            context.Response.Body.Seek(0, SeekOrigin.Begin);
            var reader         = new StreamReader(context.Response.Body);
            var streamText     = reader.ReadToEnd();
            var actualResponse = JsonConvert.DeserializeObject <ValidationError>(streamText);

            //Assert
            Assert.Equal(expectedResponse.StatusCode, actualResponse.StatusCode);
            Assert.Equal(expectedResponse.StatusCode, context.Response.StatusCode);
            Assert.Equal(expectedResponse.StatusMessage, actualResponse.StatusMessage);
            Assert.NotNull(actualResponse.Errors);
            Assert.Equal(expectedResponse.Errors.Count, actualResponse.Errors.Count);

            for (int i = 0; i < actualResponse.Errors.Count; i++)
            {
                Assert.Equal(expectedResponse.Errors[i].Code, actualResponse.Errors[i].Code);
                Assert.Equal(expectedResponse.Errors[i].Message, actualResponse.Errors[i].Message);
                Assert.Equal(expectedResponse.Errors[i].AttemptedValue, actualResponse.Errors[i].AttemptedValue);
                Assert.Equal(expectedResponse.Errors[i].Field, actualResponse.Errors[i].Field);
            }
        }
    private ExceptionHandlerMiddleware CreateMiddleware(
        RequestDelegate next,
        IOptions <ExceptionHandlerOptions> options)
    {
        next ??= c => Task.CompletedTask;
        var listener = new DiagnosticListener("Microsoft.AspNetCore");

        var middleware = new ExceptionHandlerMiddleware(
            next,
            NullLoggerFactory.Instance,
            options,
            listener);

        return(middleware);
    }
        public async Task WhenAFluentValidationExceptionIsRaised_AValidationErrorWillBeReturned_WithBadRequestHttpStatus()
        {
            // Arrange
            var requestDTO = new RequestModelBasic()
            {
                Id = 0, Message = string.Empty, CreatedOn = DateTime.Now
            };

            // Perform a validation using a FluentValidator
            var validator = new RequestModelBasicValidator();

            FluentValidation.Results.ValidationResult validationResult = validator.Validate(requestDTO);
            ValidationException thrownException = new ValidationException(validationResult.Errors, string.Empty);

            ValidationError expectedResponse = new ValidationError(validationResult.Errors, string.Empty);

            var middleware = new ExceptionHandlerMiddleware((innerHttpContext) =>
            {
                throw thrownException;
            }, _logger);

            var context = new DefaultHttpContext();

            context.Response.Body = new MemoryStream();

            //Act
            await middleware.Invoke(context);

            context.Response.Body.Seek(0, SeekOrigin.Begin);
            var reader         = new StreamReader(context.Response.Body);
            var streamText     = reader.ReadToEnd();
            var actualResponse = JsonConvert.DeserializeObject <ValidationError>(streamText);

            //Assert
            Assert.Equal(expectedResponse.StatusCode, actualResponse.StatusCode);
            Assert.Equal(expectedResponse.StatusCode, context.Response.StatusCode);
            Assert.Equal(expectedResponse.StatusMessage, actualResponse.StatusMessage);
            Assert.NotNull(actualResponse.Errors);
            Assert.Equal(expectedResponse.Errors.Count, actualResponse.Errors.Count);

            for (int i = 0; i < actualResponse.Errors.Count; i++)
            {
                Assert.Equal(expectedResponse.Errors[i].Code, actualResponse.Errors[i].Code);
                Assert.Equal(expectedResponse.Errors[i].Message, actualResponse.Errors[i].Message);
                Assert.Equal(expectedResponse.Errors[i].AttemptedValue.ToString(), actualResponse.Errors[i].AttemptedValue.ToString());
                Assert.Equal(expectedResponse.Errors[i].Field, actualResponse.Errors[i].Field);
            }
        }
        public void SetUp()
        {
            var serviceCollection = new ServiceCollection();
            var config            = new ConfigurationRoot(new List <IConfigurationProvider>());
            var builder           = new OcelotBuilder(serviceCollection, config);
            var services          = serviceCollection.BuildServiceProvider();
            var loggerFactory     = services.GetService <IOcelotLoggerFactory>();
            var configRepo        = services.GetService <IInternalConfigurationRepository>();
            var repo = services.GetService <IRequestScopedDataRepository>();

            _next = async context => {
                await Task.CompletedTask;
                throw new Exception("BOOM");
            };
            _middleware        = new ExceptionHandlerMiddleware(_next, loggerFactory, configRepo, repo);
            _downstreamContext = new DownstreamContext(new DefaultHttpContext());
        }
Пример #14
0
        public async Task InvokeAsyncSuccessTest()
        {
            var mockHttpContext     = new Mock <HttpContext>();
            var mockRequestDelegate = new Mock <RequestDelegate>();

            mockRequestDelegate.Setup(requestDelegate => requestDelegate.Invoke(mockHttpContext.Object));
            var mockLogger = new Mock <ILogger <ExceptionHandlerMiddleware> >();

            var middleware = new ExceptionHandlerMiddleware(mockRequestDelegate.Object, mockLogger.Object, null);
            await middleware.InvokeAsync(mockHttpContext.Object);

            mockRequestDelegate.Verify(requestDelegate => requestDelegate.Invoke(mockHttpContext.Object), Times.Once);
            // If an exception was thrown, then this test will fail with null references as the required objects were not setup.
            // We could setup additional mocks to verify the methods weren't called.
            // However, due to complications with extension methods, as detailed in the throws exception case below,
            // I am fine with leaving this scenario simple with the null reference exceptions.
        }
        public async Task WhenAnUnExpectedExceptionIsRaised_CustomExceptionMiddlewareShouldHandleItToInternalServerErrorHttpStatus()
        {
            // Arrange
            var middleware = new ExceptionHandlerMiddleware(next: (innerHttpContext) =>
            {
                throw new Exception();
            });

            var context = new DefaultHttpContext();

            context.Response.Body = new MemoryStream();

            //Act
            await middleware.Invoke(context, _fixture.CurrentEnvironment);

            //Assert
            context.Response.StatusCode.ShouldBe((int)HttpStatusCode.InternalServerError);
        }
Пример #16
0
        static async Task Awaited(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
        {
            ExceptionDispatchInfo?edi = null;

            try
            {
                await task;
            }
            catch (Exception exception)
            {
                // Get the Exception, but don't continue processing in the catch block as its bad for stack usage.
                edi = ExceptionDispatchInfo.Capture(exception);
            }

            if (edi != null)
            {
                await middleware.HandleException(context, edi);
            }
        }
Пример #17
0
        public async Task InvokeAsync_CallLogExceptionAsync()
        {
            Exception loggedException             = null;
            ExceptionHandlerMiddleware middleware = new ExceptionHandlerMiddleware()
            {
                Next = new FaultyMiddleware(),
                LogExceptionAsync = (Exception e) =>
                {
                    loggedException = e;
                    return(Task.CompletedTask);
                }
            };
            var context = this.GetContext();
            await middleware.InvokeAsync(context);

            var typedLoggedException = loggedException.ShouldBeOfType <ApplicationException>();

            typedLoggedException.Message.ShouldBe("oh no!");
        }
        public async Task WhenUnauthorizedExceptionIsRaised_ExceptionHandlerMiddlewareShouldHandleItToUnauthorizedHttpStatus()
        {
            // Arrange
            var middleware = new ExceptionHandlerMiddleware((innerHttpContext) =>
            {
                throw new UnauthorizedAccessException();
            });

            var context = new DefaultHttpContext();

            context.Response.Body = new MemoryStream();

            //Act
            await middleware.Invoke(context, _fixture.CurrentEnvironment);

            context.Response.Body.Seek(0, SeekOrigin.Begin);

            //Assert
            context.Response.StatusCode.ShouldBe((int)HttpStatusCode.Unauthorized);
        }
Пример #19
0
        public async Task InvokeAsync_NoExceptionHandler()
        {
            ExceptionHandlerMiddleware middleware = new ExceptionHandlerMiddleware()
            {
                Next = new FaultyMiddleware()
            };
            var context = this.GetContext();
            await middleware.InvokeAsync(context);

            context.Response.StatusCode.ShouldBe(500);
            context.Response.Body.Position = 0;
            var contents = context.Response.Body.ReadAsString();
            var response = JsonConvert.DeserializeObject <ErrorResponse>(contents);

            response.ShouldNotBeNull();
            response.CorrelationId.ShouldNotBeNullOrWhiteSpace();
            response.Error.ShouldNotBeNull();
            response.Error.Code.ShouldBe("INTERNAL_SERVER_ERROR");
            response.Error.Message.ShouldBe("An internal server error occurred");
        }
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app)
        {
            app.UseExceptionHandler(ExceptionHandlerMiddleware.ExceptionHandler());

            app.UseRouting();

            app.UseCors();

            app.UseAuthentication();

            app.UseAuthorization();

            app.UseMiddleware <RequestResponseLoggingMiddleware>();

            app.UseSwagger();

            app.UseSwaggerUI(new CustomSwaggerUIOptions());

            app.UseEndpoints(endpointRouterBuilder => endpointRouterBuilder.MapControllers());
        }
Пример #21
0
        public ExceptionHandlerMiddlewareTests()
        {
            _configRepo        = new Mock <IInternalConfigurationRepository>();
            _repo              = new Mock <IRequestScopedDataRepository>();
            _downstreamContext = new DownstreamContext(new DefaultHttpContext());
            _loggerFactory     = new Mock <IOcelotLoggerFactory>();
            _logger            = new Mock <IOcelotLogger>();
            _loggerFactory.Setup(x => x.CreateLogger <ExceptionHandlerMiddleware>()).Returns(_logger.Object);
            _next = async context => {
                await Task.CompletedTask;

                if (_shouldThrowAnException)
                {
                    throw new Exception("BOOM");
                }

                context.HttpContext.Response.StatusCode = (int)HttpStatusCode.OK;
            };
            _middleware = new ExceptionHandlerMiddleware(_next, _loggerFactory.Object, _configRepo.Object, _repo.Object);
        }
Пример #22
0
        public async Task InvokeAsync_DefaultExceptionHandler_BadRequest()
        {
            ExceptionHandlerMiddleware middleware = new ExceptionHandlerMiddleware()
            {
                Next             = new BadRequestMiddleware(),
                ExceptionHandler = ExceptionHandlerMiddleware.DefaultExceptionHandler
            };
            var context = this.GetContext();
            await middleware.InvokeAsync(context);

            context.Response.StatusCode.ShouldBe(400);
            context.Response.Body.Position = 0;
            var contents = context.Response.Body.ReadAsString();
            var response = JsonConvert.DeserializeObject <ErrorResponse>(contents);

            response.ShouldNotBeNull();
            response.CorrelationId.ShouldNotBeNullOrWhiteSpace();
            response.Error.ShouldNotBeNull();
            response.Error.Code.ShouldBe("BAD_REQUEST");
            response.Error.Message.ShouldBe("oh no!");
        }
Пример #23
0
        public async Task ExceptionHandlerMiddleware_CatchException()
        {
            // Arrange
            var    exHandler               = new Mock <IExceptionHandler>();
            int    expectedStatusCode      = 500;
            string expectedResponseContent = "test";

            exHandler.Setup(x => x.CreateResponseContent()).Returns(expectedResponseContent);
            exHandler.Setup(x => x.GetHttpStatusCode()).Returns(expectedStatusCode);

            var exHandlerFactory = new Mock <IExceptionHandlerFactory>();

            Exception ex = new Exception();

            exHandlerFactory.Setup(x => x.GetExceptionHandler(ex)).Returns(exHandler.Object);

            var middleware = new ExceptionHandlerMiddleware(exHandlerFactory.Object, (innerHttpContext) =>
            {
                throw ex;
            });

            var context = new DefaultHttpContext();

            context.Response.Body = new MemoryStream();

            // Act
            await middleware.Invoke(context);

            // Assert
            context.Response.Body.Seek(0, SeekOrigin.Begin);
            var reader          = new StreamReader(context.Response.Body);
            var responseContent = reader.ReadToEnd();

            responseContent.Should().BeEquivalentTo(expectedResponseContent);
            context.Response.StatusCode.Should().Be(expectedStatusCode);
        }
Пример #24
0
 public ExceptionHandlerMiddlewareTests()
 {
     _next       = A.Fake <RequestDelegate>();
     _executor   = A.Fake <IActionResultExecutor <ObjectResult> >();
     _middleware = new ExceptionHandlerMiddleware(_next, _executor, A.Fake <ILogger <ExceptionHandlerMiddleware> >());
 }
Пример #25
0
 public ExceptionHandlerMiddlewareTest()
 {
     _next = new Mock <RequestDelegate>();
     _exceptionMiddleware = new ExceptionHandlerMiddleware(_next.Object);
 }