private static HttpResponseMessage HandleExceptionInternal(ExceptionContext context, ApiVersionNotDeterminedException exception) {
            if (exception == null) {
                return null;
            }

            return context.Request.CreateResponse(HttpStatusCode.BadRequest, exception.Message);
        }
        private IHttpActionResult HandleExceptionResult(ExceptionContext context)
        {
            Exception exception = context.Exception;

            HttpRequestMessage request = context.Request;
            if (request == null)
            {
                return null;
            }

            HttpRequestContext requestContext = context.RequestContext;
            if (requestContext == null)
            {
                return null;
            }

            HttpConfiguration configuration = requestContext.Configuration;
            if (configuration == null)
            {
                return null;
            }

            IContentNegotiator contentNegotiator = configuration.Services.GetContentNegotiator();
            if (contentNegotiator == null)
            {
                return null;
            }

            return GetExceptionActionResult(exception, requestContext.IncludeErrorDetail, contentNegotiator, request,
                configuration.Formatters);
        }
        private static HttpResponseMessage HandleExceptionInternal(ExceptionContext context, ApiVersionFormatException exception) {
            if (exception == null) {
                return null;
            }

            return context.Request.CreateErrorResponse(HttpStatusCode.BadRequest, ExceptionResources.CannotDetermineRequestVersion, exception);
        }
        private static HttpResponseMessage HandleExceptionInternal(ExceptionContext context, ApiControllerNotFoundException exception) {
            if (exception == null) {
                return null;
            }

            return context.Request.CreateResponse(HttpStatusCode.NotFound, String.Format(ExceptionResources.ApiDoesntExist, exception.ControllerIdentification));
        }
        private static HttpResponseMessage HandleExceptionInternal(ExceptionContext context, AmbigiousApiRequestException exception) {
            if (exception == null) {
                return null;
            }

            // multiple matching types
            return context.Request.CreateResponse(HttpStatusCode.InternalServerError, exception.Message);
        }
        public void Log(Exception ex, HttpRequestMessage request, string catchBlockName)
        {
            var catchBlock = new ExceptionContextCatchBlock(catchBlockName, true, false);
            var exceptionContext = new ExceptionContext(ex, catchBlock, request);
            var exceptionLoggerContext = new ExceptionLoggerContext(exceptionContext);

            Log(exceptionLoggerContext);
        }
        /// <summary>Initializes a new instance of the <see cref="ExceptionHandlerContext"/> class.</summary>
        /// <param name="exceptionContext">The exception context.</param>
        public ExceptionHandlerContext(ExceptionContext exceptionContext)
        {
            if (exceptionContext == null)
            {
                throw new ArgumentNullException("exceptionContext");
            }

            _exceptionContext = exceptionContext;
        }
Beispiel #8
0
        internal async Task <HttpResponseMessage> SendFluentApiAsync(HttpRequestMessage request, CancellationToken cancellationToken, HttpControllerDescriptor controllerDescriptor)
        {
            ExceptionDispatchInfo exceptionInfo;
            HttpControllerContext controllerContext = null;

            try
            {
                IHttpController controller = controllerDescriptor.CreateController(request);
                if (controller == null)
                {
                    var httpError = new HttpError(string.Format(CultureInfo.CurrentCulture, "No HTTP resource was found that matches the request URI '{0}'.", request.RequestUri));
                    if (request.ShouldIncludeErrorDetail())
                    {
                        httpError.Add(HttpErrorKeys.MessageDetailKey, "No controller was created to handle this request.");
                    }

                    return(request.CreateErrorResponse(HttpStatusCode.NotFound, httpError));
                }

                controllerContext = CreateControllerContext(request, controllerDescriptor, controller);
                return(await controller.ExecuteAsync(controllerContext, cancellationToken));
            }
            catch (OperationCanceledException)
            {
                // Propogate the canceled task without calling exception loggers or handlers.
                throw;
            }
            catch (HttpResponseException httpResponseException)
            {
                return(httpResponseException.Response);
            }
            catch (Exception exception)
            {
                exceptionInfo = ExceptionDispatchInfo.Capture(exception);
            }

            Debug.Assert(exceptionInfo.SourceException != null);

            ExceptionContext exceptionContext = new ExceptionContext(
                exceptionInfo.SourceException,
                ExceptionCatchBlocks.HttpControllerDispatcher,
                request)
            {
                ControllerContext = controllerContext,
            };

            await ExceptionLogger.LogAsync(exceptionContext, cancellationToken);

            HttpResponseMessage response = await ExceptionHandler.HandleAsync(exceptionContext, cancellationToken);

            if (response == null)
            {
                exceptionInfo.Throw();
            }

            return(response);
        }
        /// <summary>
        /// Handles the specified exception by rethrowing it
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="context"></param>
        public virtual HttpResponseMessage HandleException(ExceptionContext context, BaseApiException ex) {
            HttpResponseMessage result = null;

            result = result ?? HandleExceptionInternal(context, ex as ApiControllerNotFoundException);
            result = result ?? HandleExceptionInternal(context, ex as AmbigiousApiRequestException);
            result = result ?? HandleExceptionInternal(context, ex as ApiVersionFormatException);
            result = result ?? HandleExceptionInternal(context, ex as ApiVersionNotDeterminedException);

            return result;
        }
        public void FormsPersistenceControllerReturnsBadRequestHttpResponseExceptionForGeneralException()
        {
            var exceptionContext = new ExceptionContext(new Exception("General error"), new ExceptionContextCatchBlock("test", true, true));
            var exceptionHandlerContext = new ExceptionHandlerContext(exceptionContext);
            var globalExceptionHandler = new GlobalExceptionHandler();

            globalExceptionHandler.Handle(exceptionHandlerContext);
            var result = exceptionHandlerContext.Result.ExecuteAsync(new CancellationToken()).Result;

            Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode);
            Assert.AreEqual("Error occurred during API call - General error", result.Content.ReadAsStringAsync().Result);
        }
        public void FormsPersistenceControllerReturnsNotFoundHttpResponseExceptionForNotFoundException()
        {
            var exceptionContext = new ExceptionContext(new NotFoundException("Not found error"), new ExceptionContextCatchBlock("test", true, true));
            var exceptionHandlerContext = new ExceptionHandlerContext(exceptionContext);
            var globalExceptionHandler = new GlobalExceptionHandler();

            globalExceptionHandler.Handle(exceptionHandlerContext);
            var result = exceptionHandlerContext.Result.ExecuteAsync(new CancellationToken()).Result;
            
            Assert.AreEqual(HttpStatusCode.NotFound, result.StatusCode);
            Assert.AreEqual("Not found error", result.Content.ReadAsStringAsync().Result);
        }
        public void FilesPersistenceControllerReturnsBadRequestHttpResponseExceptionForUnsupportedOperationException()
        {
            var exceptionContext = new ExceptionContext(new UnsupportedOperationException("Unsupported operation"), new ExceptionContextCatchBlock("test", true, true));
            var exceptionHandlerContext = new ExceptionHandlerContext(exceptionContext);
            var globalExceptionHandler = new GlobalExceptionHandler();

            globalExceptionHandler.Handle(exceptionHandlerContext);
            var result = exceptionHandlerContext.Result.ExecuteAsync(new CancellationToken()).Result;

            Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode);
            Assert.AreEqual("Unsupported operation", result.Content.ReadAsStringAsync().Result);
        }
        public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            ExceptionDispatchInfo exceptionInfo;

            try
            {
                return await _innerResult.ExecuteAsync(cancellationToken);
            }
            catch (Exception e)
            {
                exceptionInfo = ExceptionDispatchInfo.Capture(e);
            }

            // This code path only runs if the task is faulted with an exception
            Exception exception = exceptionInfo.SourceException;
            Debug.Assert(exception != null);

            ExceptionContext exceptionContext = new ExceptionContext(exception, ExceptionCatchBlocks.IExceptionFilter,
                _context);

            await _exceptionLogger.LogAsync(exceptionContext, cancellationToken);

            HttpActionExecutedContext executedContext = new HttpActionExecutedContext(_context, exception);

            // Note: exception filters need to be scheduled in the reverse order so that
            // the more specific filter (e.g. Action) executes before the less specific ones (e.g. Global)
            for (int i = _filters.Length - 1; i >= 0; i--)
            {
                IExceptionFilter exceptionFilter = _filters[i];
                await exceptionFilter.ExecuteExceptionFilterAsync(executedContext, cancellationToken);
            }

            if (executedContext.Response == null)
            {
                executedContext.Response = await _exceptionHandler.HandleAsync(exceptionContext, cancellationToken);
            }

            if (executedContext.Response != null)
            {
                return executedContext.Response;
            }
            else
            {
                // Preserve the original stack trace when the exception is not changed by any filter.
                if (exception == executedContext.Exception)
                {
                    exceptionInfo.Throw();
                }

                // If the exception is changed by a filter, throw the new exception instead.
                throw executedContext.Exception;
            }
        }
        public void ExceptionGet_ReturnsSpecifiedInstance()
        {
            // Arrange
            Exception expectedException = new InvalidOperationException();
            ExceptionContext context = new ExceptionContext(expectedException, ExceptionCatchBlocks.HttpServer);
            ExceptionLoggerContext product = CreateProductUnderTest(context);

            // Act
            Exception exception = product.Exception;

            // Assert
            Assert.Same(expectedException, exception);
        }
        public void CatchBlockGet_ReturnsSpecifiedInstance()
        {
            // Arrange
            ExceptionContextCatchBlock expectedCatchBlock = new ExceptionContextCatchBlock("IgnoreName", false, false);
            ExceptionContext context = new ExceptionContext(new Exception(), expectedCatchBlock);
            ExceptionLoggerContext product = CreateProductUnderTest(context);

            // Act
            ExceptionContextCatchBlock catchBlock = product.CatchBlock;

            // Assert
            Assert.Same(expectedCatchBlock, catchBlock);
        }
        public IHttpActionResult Record(AngularExceptionModel model)
        {
            // Create the exception and exception context
            var exception = new AngularException(model.ToString());
            var catchBlock = new ExceptionContextCatchBlock("catchBlock", true, false);
            var context = new ExceptionContext(exception, catchBlock, Request);
            var loggerContext = new ExceptionLoggerContext(context);

            // Call elmah & log the exception
            var logger = new ExceptionHandling.ElmahExceptionLogger();
            logger.Log(loggerContext);

            // Return
            return Ok();
        }
        /// <summary>Calls an exception handler and determines the response handling it, if any.</summary>
        /// <param name="handler">The unhandled exception handler.</param>
        /// <param name="context">The exception context.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
        /// <returns>
        /// A task that, when completed, contains the response message to return when the exception is handled, or
        /// <see langword="null"/> when the exception remains unhandled.
        /// </returns>
        public static Task<HttpResponseMessage> HandleAsync(this IExceptionHandler handler,
            ExceptionContext context, CancellationToken cancellationToken)
        {
            if (handler == null)
            {
                throw new ArgumentNullException("handler");
            }

            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            ExceptionHandlerContext handlerContext = new ExceptionHandlerContext(context);
            return HandleAsyncCore(handler, handlerContext, cancellationToken);
        }
        /// <summary>Calls an exception logger.</summary>
        /// <param name="logger">The unhandled exception logger.</param>
        /// <param name="context">The exception context.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
        /// <returns>A task representing the asynchronous exception logging operation.</returns>
        public static Task LogAsync(this IExceptionLogger logger, ExceptionContext context,
            CancellationToken cancellationToken)
        {
            if (logger == null)
            {
                throw new ArgumentNullException("logger");
            }

            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            ExceptionLoggerContext loggerContext = new ExceptionLoggerContext(context);
            return logger.LogAsync(loggerContext, cancellationToken);
        }
        public void RequestGet_ReturnsSpecifiedInstance()
        {
            // Arrange
            using (HttpRequestMessage expectedRequest = new HttpRequestMessage())
            {
                ExceptionContext context = new ExceptionContext(new Exception(), ExceptionCatchBlocks.HttpServer, expectedRequest);

                ExceptionLoggerContext product = CreateProductUnderTest(context);

                // Act
                HttpRequestMessage request = product.Request;

                // Assert
                Assert.Same(expectedRequest, request);
            }
        }
        public void ErrorIsLogged()
        {
            var exception = new ArgumentException("Test");
            var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "http://www.server.domain");
            var httpRouteData = new HttpRouteData(new HttpRoute());
            var httpControllerContext = new HttpControllerContext(new HttpConfiguration(), httpRouteData, httpRequestMessage);
            var actionContext = new HttpActionContext(httpControllerContext, new ReflectedHttpActionDescriptor());
            actionContext.ActionArguments.Add("Key1", "Value1");
            actionContext.ActionArguments.Add("Key2", "Value2");

            var exceptionContext = new ExceptionContext(exception, new ExceptionContextCatchBlock("TestBlock", false, false), actionContext);
            var loggerContext = new ExceptionLoggerContext(exceptionContext);

            sut.Log(loggerContext);

            logger.Received().LogError(correlation, exception, "Unhandled exception from request: {0}({1})", httpRequestMessage, "Key1: Value1, Key2: Value2");
        }
        /// <inheritdoc/>
        protected sealed override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (request == null)
            {
                throw Error.ArgumentNull("request");
            }

            request.Properties[HttpPropertyKeys.IsBatchRequest] = true;

            ExceptionDispatchInfo exceptionInfo;

            try
            {
                return await ProcessBatchAsync(request, cancellationToken);
            }
            catch (HttpResponseException httpResponseException)
            {
                return httpResponseException.Response;
            }
            catch (Exception exception)
            {
                exceptionInfo = ExceptionDispatchInfo.Capture(exception);
            }

            Debug.Assert(exceptionInfo.SourceException != null);

            ExceptionContext exceptionContext = new ExceptionContext(exceptionInfo.SourceException,
                ExceptionCatchBlocks.HttpBatchHandler, request);
            await ExceptionLogger.LogAsync(exceptionContext, cancellationToken);
            HttpResponseMessage response = await ExceptionHandler.HandleAsync(exceptionContext, cancellationToken);

            if (response == null)
            {
                exceptionInfo.Throw();
            }

            return response;
        }
 private static ExceptionHandlerContext CreateContext(ExceptionContext exceptionContext)
 {
     return(new ExceptionHandlerContext(exceptionContext));
 }
        internal static async Task<bool> PrepareHeadersAsync(HttpResponseBase responseBase, HttpRequestMessage request,
            HttpResponseMessage response, IExceptionLogger exceptionLogger, CancellationToken cancellationToken)
        {
            Contract.Assert(response != null);
            HttpResponseHeaders responseHeaders = response.Headers;
            Contract.Assert(responseHeaders != null);
            HttpContent content = response.Content;
            bool isTransferEncodingChunked = responseHeaders.TransferEncodingChunked == true;
            HttpHeaderValueCollection<TransferCodingHeaderValue> transferEncoding = responseHeaders.TransferEncoding;

            if (content != null)
            {
                HttpContentHeaders contentHeaders = content.Headers;
                Contract.Assert(contentHeaders != null);

                if (isTransferEncodingChunked)
                {
                    // According to section 4.4 of the HTTP 1.1 spec, HTTP responses that use chunked transfer
                    // encoding must not have a content length set. Chunked should take precedence over content
                    // length in this case because chunked is always set explicitly by users while the Content-Length
                    // header can be added implicitly by System.Net.Http.
                    contentHeaders.ContentLength = null;
                }
                else
                {
                    Exception exception = null;

                    // Copy the response content headers only after ensuring they are complete.
                    // We ask for Content-Length first because HttpContent lazily computes this
                    // and only afterwards writes the value into the content headers.
                    try
                    {
                        var unused = contentHeaders.ContentLength;
                    }
                    catch (Exception ex)
                    {
                        exception = ex;
                    }

                    if (exception != null)
                    {
                        ExceptionContext exceptionContext = new ExceptionContext(exception,
                            WebHostExceptionCatchBlocks.HttpControllerHandlerComputeContentLength, request, response);
                        await exceptionLogger.LogAsync(exceptionContext, cancellationToken);

                        SetEmptyErrorResponse(responseBase);
                        return false;
                    }
                }

                // Select output buffering based on the user-controlled buffering policy
                bool isBuffered = _bufferPolicySelector.Value != null ?
                    _bufferPolicySelector.Value.UseBufferedOutputStream(response) : true;
                responseBase.BufferOutput = isBuffered;
            }

            // Ignore the Transfer-Encoding header if it is just "chunked"; the host will provide it when no
            // Content-Length is present and BufferOutput is disabled (and this method guarantees those conditions).
            // HttpClient sets this header when it receives chunked content, but HttpContent does not include the
            // frames. The ASP.NET contract is to set this header only when writing chunked frames to the stream.
            // A Web API caller who desires custom framing would need to do a different Transfer-Encoding (such as
            // "identity, chunked").
            if (isTransferEncodingChunked && transferEncoding.Count == 1)
            {
                transferEncoding.Clear();

                // In the case of a conflict between a Transfer-Encoding: chunked header and the output buffering
                // policy, honor the Transnfer-Encoding: chunked header and ignore the buffer policy.
                // If output buffering is not disabled, ASP.NET will not write the TransferEncoding: chunked header.
                responseBase.BufferOutput = false;
            }

            return true;
        }
        private static async Task WriteErrorResponseContentAsync(HttpResponseBase httpResponseBase,
            HttpRequestMessage request, HttpResponseMessage errorResponse, CancellationToken cancellationToken,
            IExceptionLogger exceptionLogger)
        {
            HttpRequestMessage ignoreUnused = request;

            try
            {
                Exception exception = null;
                cancellationToken.ThrowIfCancellationRequested();

                try
                {
                    // Asynchronously write the content of the new error HttpResponseMessage
                    await errorResponse.Content.CopyToAsync(httpResponseBase.OutputStream);
                    return;
                }
                catch (Exception ex)
                {
                    exception = ex;
                }

                Contract.Assert(exception != null);

                ExceptionContext exceptionContext = new ExceptionContext(exception,
                    WebHostExceptionCatchBlocks.HttpControllerHandlerBufferError, request, errorResponse);
                await exceptionLogger.LogAsync(exceptionContext, cancellationToken);

                // Failure writing the error response.  Likely cause is a formatter
                // serialization exception.  Create empty error response and
                // return a non-faulted task.
                SetEmptyErrorResponse(httpResponseBase);
            }
            finally
            {
                // Dispose the temporary HttpResponseMessage carrying the error response
                errorResponse.Dispose();
            }
        }
        internal static async Task<bool> CopyErrorResponseAsync(ExceptionContextCatchBlock catchBlock,
            HttpContextBase httpContextBase, HttpRequestMessage request, HttpResponseMessage response,
            Exception exception, IExceptionLogger exceptionLogger, IExceptionHandler exceptionHandler,
            CancellationToken cancellationToken)
        {
            Contract.Assert(httpContextBase != null);
            Contract.Assert(httpContextBase.Response != null);
            Contract.Assert(request != null);
            Contract.Assert(exception != null);
            Contract.Assert(catchBlock != null);
            Contract.Assert(catchBlock.CallsHandler);

            HttpResponseBase httpResponseBase = httpContextBase.Response;
            HttpResponseMessage errorResponse = null;
            HttpResponseException responseException = exception as HttpResponseException;

            // Ensure all headers and content are cleared to eliminate any partial results.
            ClearContentAndHeaders(httpResponseBase);

            // If the exception we are handling is HttpResponseException,
            // that becomes the error response.
            if (responseException != null)
            {
                errorResponse = responseException.Response;
            }
            else
            {
                ExceptionContext exceptionContext = new ExceptionContext(exception, catchBlock, request)
                {
                    Response = response
                };
                await exceptionLogger.LogAsync(exceptionContext, cancellationToken);
                errorResponse = await exceptionHandler.HandleAsync(exceptionContext, cancellationToken);

                if (errorResponse == null)
                {
                    return false;
                }
            }

            Contract.Assert(errorResponse != null);
            if (!await CopyResponseStatusAndHeadersAsync(httpContextBase, request, errorResponse, exceptionLogger,
                cancellationToken))
            {
                // Don't rethrow the original exception unless explicitly requested to do so. In this case, the
                // exception handler indicated it wanted to handle the exception; it simply failed create a stable
                // response to send.
                return true;
            }

            // The error response may return a null content if content negotiation
            // fails to find a formatter, or this may be an HttpResponseException without
            // content.  In either case, cleanup and return a completed task.

            if (errorResponse.Content == null)
            {
                errorResponse.Dispose();
                return true;
            }

            CopyHeaders(errorResponse.Content.Headers, httpContextBase);

            await WriteErrorResponseContentAsync(httpResponseBase, request, errorResponse, cancellationToken,
                exceptionLogger);
            return true;
        }
        internal static async Task WriteStreamedResponseContentAsync(HttpContextBase httpContextBase,
            HttpRequestMessage request, HttpResponseMessage response, IExceptionLogger exceptionLogger,
            CancellationToken cancellationToken)
        {
            Contract.Assert(httpContextBase != null);
            Contract.Assert(httpContextBase.Response != null);
            Contract.Assert(request != null);
            Contract.Assert(response != null);
            Contract.Assert(response.Content != null);

            Exception exception = null;
            cancellationToken.ThrowIfCancellationRequested();

            try
            {
                // Copy the HttpContent into the output stream asynchronously.
                await response.Content.CopyToAsync(httpContextBase.Response.OutputStream);
                return;
            }
            catch (Exception ex)
            {
                exception = ex;
            }

            Contract.Assert(exception != null);

            ExceptionContextCatchBlock catchBlock = WebHostExceptionCatchBlocks.HttpControllerHandlerStreamContent;
            ExceptionContext exceptionContext = new ExceptionContext(exception, catchBlock, request, response);
            await exceptionLogger.LogAsync(exceptionContext, cancellationToken);

            // Streamed content may have been written and cannot be recalled.
            // Our only choice is to abort the connection.
            httpContextBase.Request.Abort();
        }
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (request == null)
            {
                throw Error.ArgumentNull("request");
            }

            ExceptionDispatchInfo exceptionInfo;
            HttpControllerContext controllerContext = null;

            try
            {
                HttpControllerDescriptor controllerDescriptor = ControllerSelector.SelectController(request);
                if (controllerDescriptor == null)
                {
                    return request.CreateErrorResponse(
                        HttpStatusCode.NotFound,
                        Error.Format(SRResources.ResourceNotFound, request.RequestUri),
                        SRResources.NoControllerSelected);
                }

                IHttpController controller = controllerDescriptor.CreateController(request);
                if (controller == null)
                {
                    return request.CreateErrorResponse(
                        HttpStatusCode.NotFound,
                        Error.Format(SRResources.ResourceNotFound, request.RequestUri),
                        SRResources.NoControllerCreated);
                }

                controllerContext = CreateControllerContext(request, controllerDescriptor, controller);
                return await controller.ExecuteAsync(controllerContext, cancellationToken);
            }
            catch (OperationCanceledException)
            {
                // Propogate the canceled task without calling exception loggers or handlers.
                throw;
            }
            catch (HttpResponseException httpResponseException)
            {
                return httpResponseException.Response;
            }
            catch (Exception exception)
            {
                exceptionInfo = ExceptionDispatchInfo.Capture(exception);
            }

            Debug.Assert(exceptionInfo.SourceException != null);

            ExceptionContext exceptionContext = new ExceptionContext(
                exceptionInfo.SourceException,
                ExceptionCatchBlocks.HttpControllerDispatcher,
                request)
                {
                    ControllerContext = controllerContext,
                };

            await ExceptionLogger.LogAsync(exceptionContext, cancellationToken);
            HttpResponseMessage response = await ExceptionHandler.HandleAsync(exceptionContext, cancellationToken);

            if (response == null)
            {
                exceptionInfo.Throw();
            }

            return response;
        }
        private async Task<HttpResponseMessage> BufferResponseContentAsync(HttpRequestMessage request,
            HttpResponseMessage response, CancellationToken cancellationToken)
        {
            ExceptionDispatchInfo exceptionInfo;

            cancellationToken.ThrowIfCancellationRequested();

            try
            {
                await response.Content.LoadIntoBufferAsync();
                return response;
            }
            catch (Exception exception)
            {
                exceptionInfo = ExceptionDispatchInfo.Capture(exception);
            }

            // If the content can't be buffered, create a buffered error response for the exception
            // This code will commonly run when a formatter throws during the process of serialization

            Debug.Assert(exceptionInfo.SourceException != null);

            ExceptionContext exceptionContext = new ExceptionContext(exceptionInfo.SourceException,
                OwinExceptionCatchBlocks.HttpMessageHandlerAdapterBufferContent, request, response);

            await _exceptionLogger.LogAsync(exceptionContext, cancellationToken);
            HttpResponseMessage errorResponse = await _exceptionHandler.HandleAsync(exceptionContext,
                cancellationToken);

            response.Dispose();

            if (errorResponse == null)
            {
                exceptionInfo.Throw();
                return null;
            }

            // We have an error response to try to buffer and send back.

            response = errorResponse;
            cancellationToken.ThrowIfCancellationRequested();

            Exception errorException;

            try
            {
                // Try to buffer the error response and send it back.
                await response.Content.LoadIntoBufferAsync();
                return response;
            }
            catch (Exception exception)
            {
                errorException = exception;
            }

            // We tried to send back an error response with content, but we couldn't. It's an edge case; the best we
            // can do is to log that exception and send back an empty 500.

            ExceptionContext errorExceptionContext = new ExceptionContext(errorException,
                OwinExceptionCatchBlocks.HttpMessageHandlerAdapterBufferError, request, response);
            await _exceptionLogger.LogAsync(errorExceptionContext, cancellationToken);

            response.Dispose();
            return request.CreateResponse(HttpStatusCode.InternalServerError);
        }
Beispiel #29
0
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (request == null)
            {
                throw Error.ArgumentNull("request");
            }

            if (_disposed)
            {
                return request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, SRResources.HttpServerDisposed);
            }

            // The first request initializes the server
            EnsureInitialized();

            // Capture current synchronization context and add it as a parameter to the request
            SynchronizationContext context = SynchronizationContext.Current;
            if (context != null)
            {
                request.SetSynchronizationContext(context);
            }

            // Add HttpConfiguration object as a parameter to the request 
            request.SetConfiguration(_configuration);

            // Ensure we have a principal, even if the host didn't give us one
            IPrincipal originalPrincipal = Thread.CurrentPrincipal;
            if (originalPrincipal == null)
            {
                Thread.CurrentPrincipal = _anonymousPrincipal;
            }

            // Ensure we have a principal on the request context (if there is a request context).
            HttpRequestContext requestContext = request.GetRequestContext();

            if (requestContext == null)
            {
                requestContext = new RequestBackedHttpRequestContext(request);

                // if the host did not set a request context we will also set it back to the request.
                request.SetRequestContext(requestContext);
            }

            try
            {
                ExceptionDispatchInfo exceptionInfo;

                try
                {
                    return await base.SendAsync(request, cancellationToken);
                }
                catch (OperationCanceledException)
                {
                    // Propogate the canceled task without calling exception loggers or handlers.
                    throw;
                }
                catch (HttpResponseException exception)
                {
                    return exception.Response;
                }
                catch (Exception exception)
                {
                    exceptionInfo = ExceptionDispatchInfo.Capture(exception);
                }

                Debug.Assert(exceptionInfo.SourceException != null);

                ExceptionContext exceptionContext = new ExceptionContext(exceptionInfo.SourceException,
                    ExceptionCatchBlocks.HttpServer, request);
                await ExceptionLogger.LogAsync(exceptionContext, cancellationToken);
                HttpResponseMessage response = await ExceptionHandler.HandleAsync(exceptionContext,
                    cancellationToken);

                if (response == null)
                {
                    exceptionInfo.Throw();
                }

                return response;
            }
            finally
            {
                Thread.CurrentPrincipal = originalPrincipal;
            }
        }
 private static ExceptionHandlerContext CreateContext(ExceptionContext exceptionContext)
 {
     return new ExceptionHandlerContext(exceptionContext);
 }
Beispiel #31
0
 private static ExceptionHandlerContext CreateProductUnderTest(ExceptionContext exceptionContext)
 {
     return(new ExceptionHandlerContext(exceptionContext));
 }
        private async Task SendResponseContentAsync(HttpRequestMessage request, HttpResponseMessage response,
            IOwinResponse owinResponse, CancellationToken cancellationToken)
        {
            Contract.Assert(response != null);
            Contract.Assert(response.Content != null);

            Exception exception;
            cancellationToken.ThrowIfCancellationRequested();

            try
            {
                await response.Content.CopyToAsync(owinResponse.Body);
                return;
            }
            catch (Exception ex)
            {
                exception = ex;
            }

            // We're streaming content, so we can only call loggers, not handlers, as we've already (possibly) send the
            // status code and headers across the wire. Log the exception, but then just abort.
            ExceptionContext exceptionContext = new ExceptionContext(exception,
                OwinExceptionCatchBlocks.HttpMessageHandlerAdapterStreamContent, request, response);
            await _exceptionLogger.LogAsync(exceptionContext, cancellationToken);
            await AbortResponseAsync();
        }
        private async Task<bool> HandleTryComputeLengthExceptionAsync(Exception exception, HttpRequestMessage request,
            HttpResponseMessage response, IOwinResponse owinResponse, CancellationToken cancellationToken)
        {
            Contract.Assert(owinResponse != null);

            ExceptionContext exceptionContext = new ExceptionContext(exception,
                OwinExceptionCatchBlocks.HttpMessageHandlerAdapterComputeContentLength, request, response);
            await _exceptionLogger.LogAsync(exceptionContext, cancellationToken);

            // Send back an empty error response if TryComputeLength throws.
            owinResponse.StatusCode = (int)HttpStatusCode.InternalServerError;
            SetHeadersForEmptyResponse(owinResponse.Headers);
            return false;
        }