コード例 #1
0
        /// <summary>
        /// Dispatch the WebDAV request based on the given HTTP context.
        /// </summary>
        /// <param name="httpContext">
        /// HTTP context for this request.
        /// </param>
        /// <returns>
        /// A task that represents the request dispatching operation.
        /// </returns>
        public async Task DispatchRequestAsync(IHttpContext httpContext)
        {
            // Make sure a HTTP context is specified
            if (httpContext == null)
            {
                throw new ArgumentNullException(nameof(httpContext));
            }

            // Make sure the HTTP context has a request
            var request = httpContext.Request;

            if (request == null)
            {
                throw new ArgumentException("The HTTP context doesn't have a request.", nameof(httpContext));
            }

            // Make sure the HTTP context has a response
            var response = httpContext.Response;

            if (response == null)
            {
                throw new ArgumentException("The HTTP context doesn't have a response.", nameof(httpContext));
            }

            // Determine the request log-string
            var logRequest = $"{request.HttpMethod}:{request.Url}:{request.RemoteEndPoint}";
            var range      = request.GetRange();

            if (null != range)
            {
                logRequest += $" ({range.Start?.ToString() ?? string.Empty}-{range.End?.ToString() ?? string.Empty})";
            }

            // Log the request
            s_log.Log(LogLevel.Info, () => $"{logRequest} - Start processing");

            try
            {
                // Set the Server header of the response message. This has no
                // functional use, but it can be used to diagnose problems by
                // determining the actual WebDAV server and version.
                response.SetHeaderValue("Server", s_serverName);

                // Start the stopwatch
                var sw = Stopwatch.StartNew();

                IRequestHandler requestHandler;
                try
                {
                    // Obtain the request handler for this message
                    requestHandler = _requestHandlerFactory.GetRequestHandler(httpContext);

                    // Make sure we got a request handler
                    if (requestHandler == null)
                    {
                        // Log warning
                        s_log.Log(LogLevel.Warning, () => $"{logRequest} - Not implemented.");

                        // This request is not implemented
                        httpContext.Response.SetStatus(DavStatusCode.NotImplemented);
                        return;
                    }
                }
                catch (Exception exc)
                {
                    // Log error
                    s_log.Log(LogLevel.Error, $"Unexpected exception while trying to obtain the request handler (method={request.HttpMethod}, url={request.Url}, source={request.RemoteEndPoint}", exc);

                    // Abort
                    return;
                }

                try
                {
                    // Handle the request
                    if (await requestHandler.HandleRequestAsync(httpContext, _store).ConfigureAwait(false))
                    {
                        // Log processing duration
                        s_log.Log(LogLevel.Info, () => $"{logRequest} - Finished processing ({sw.ElapsedMilliseconds}ms, HTTP result: {httpContext.Response.Status})");
                    }
                    else
                    {
                        // Log warning
                        s_log.Log(LogLevel.Warning, () => $"{logRequest} - Not processed.");

                        // Set status code to bad request
                        httpContext.Response.SetStatus(DavStatusCode.NotImplemented);
                    }
                }
                catch (HttpListenerException hle) when(hle.ErrorCode == ERROR_OPERATION_ABORTED)
                {
                    s_log.Log(LogLevel.Error, $"Operation aborted at (method={request.HttpMethod}, url={request.Url}, source={request.RemoteEndPoint}");
                }
                // happens when client cancel operation, usially nothing to scare
                catch (HttpListenerException hle) when(hle.ErrorCode == ERROR_CONNECTION_INVALID)
                {
                    s_log.Log(LogLevel.Error, $"An operation was attempted on a nonexistent network connection at (method={request.HttpMethod}, url={request.Url}, source={request.RemoteEndPoint}");
                }
                // happens when client cancel operation, usially nothing to scare
                catch (HttpListenerException hle) when(hle.ErrorCode == ERROR_NETNAME_DELETED)
                {
                    s_log.Log(LogLevel.Error, $"The specified network name is no longer available at (method={request.HttpMethod}, url={request.Url}, source={request.RemoteEndPoint}");
                }
                catch (HttpListenerException excListener)
                {
                    if (excListener.ErrorCode != ERROR_OPERATION_ABORTED)
                    {
                        throw;
                    }
                }

                catch (AggregateException aex) when(aex.InnerExceptions.Count == 1 &&
                                                    aex.InnerExceptions[0] is AuthenticationException auex)
                {
                    var status = DavStatusCode.Unauthorized;

                    httpContext.Response.SetStatus(status);
                    httpContext.Response.StatusDescription = $"{status.GetStatusDescription()}: {auex.Message}";
                    s_log.Log(LogLevel.Error, $"Error while handling request (method={request.HttpMethod}, url={request.Url} {httpContext.Response.StatusDescription}");
                }

                catch (Exception exc)
                {
                    s_log.Log(LogLevel.Error, $"Unexpected exception while handling request (method={request.HttpMethod}, url={request.Url}, source={request.RemoteEndPoint}", exc);
                    //, source={request.RemoteEndPoint}", exc); // request.RemoteEndPoint may be disposed

                    try
                    {
                        // Attempt to return 'InternalServerError' (if still possible)
                        httpContext.Response.SetStatus(DavStatusCode.InternalServerError);
                    }
                    catch
                    {
                        // We might not be able to send the response, because a response
                        // was already initiated by the the request handler.
                    }
                }
                finally
                {
                    // Check if we need to dispose the request handler
                    // ReSharper disable once SuspiciousTypeConversion.Global
                    (requestHandler as IDisposable)?.Dispose();
                }
            }
            finally
            {
                // Always close the context
                await httpContext.CloseAsync().ConfigureAwait(false);
            }
        }
コード例 #2
0
ファイル: WebDavDispatcher.cs プロジェクト: zivillian/nwebdav
        /// <summary>
        /// Dispatch the WebDAV request based on the given HTTP context.
        /// </summary>
        /// <param name="httpContext">
        /// HTTP context for this request.
        /// </param>
        /// <returns>
        /// A task that represents the request dispatching operation.
        /// </returns>
        public async Task DispatchRequestAsync(IHttpContext httpContext)
        {
            // Make sure a HTTP context is specified
            if (httpContext == null)
            {
                throw new ArgumentNullException(nameof(httpContext));
            }

            // Make sure the HTTP context has a request
            var request = httpContext.Request;

            if (request == null)
            {
                throw new ArgumentException("The HTTP context doesn't have a request.", nameof(httpContext));
            }

            // Make sure the HTTP context has a response
            var response = httpContext.Response;

            if (response == null)
            {
                throw new ArgumentException("The HTTP context doesn't have a response.", nameof(httpContext));
            }

            // Determine the request log-string
            var logRequest = $"{request.HttpMethod}:{request.Url}:{request.RemoteEndPoint}";

            // Log the request
            s_log.Log(LogLevel.Info, () => $"{logRequest} - Start processing");

            try
            {
                // Set the Server header of the response message. This has no
                // functional use, but it can be used to diagnose problems by
                // determining the actual WebDAV server and version.
                response.SetHeaderValue("Server", s_serverName);

                // Start the stopwatch
                var sw = Stopwatch.StartNew();

                IRequestHandler requestHandler;
                try
                {
                    // Obtain the request handler for this message
                    requestHandler = _requestHandlerFactory.GetRequestHandler(httpContext);

                    // Make sure we got a request handler
                    if (requestHandler == null)
                    {
                        // Log warning
                        s_log.Log(LogLevel.Warning, () => $"{logRequest} - Not implemented.");

                        // This request is not implemented
                        httpContext.Response.SetStatus(DavStatusCode.NotImplemented);
                        return;
                    }
                }
                catch (Exception exc)
                {
                    // Log error
                    s_log.Log(LogLevel.Error, () => $"Unexpected exception while trying to obtain the request handler (method={request.HttpMethod}, url={request.Url}, source={request.RemoteEndPoint}", exc);

                    // Abort
                    return;
                }

                try
                {
                    // Handle the request
                    if (await requestHandler.HandleRequestAsync(httpContext, _store).ConfigureAwait(false))
                    {
                        // Log processing duration
                        s_log.Log(LogLevel.Info, () => $"{logRequest} - Finished processing ({sw.ElapsedMilliseconds}ms, HTTP result: {httpContext.Response.Status})");
                    }
                    else
                    {
                        // Log warning
                        s_log.Log(LogLevel.Warning, () => $"{logRequest} - Not processed.");

                        // Set status code to bad request
                        httpContext.Response.SetStatus(DavStatusCode.NotImplemented);
                    }
                }
                catch (Exception exc)
                {
                    // Log what's going wrong
                    s_log.Log(LogLevel.Error, () => $"Unexpected exception while handling request (method={request.HttpMethod}, url={request.Url}, source={request.RemoteEndPoint}", exc);

                    try
                    {
                        // Attempt to return 'InternalServerError' (if still possible)
                        httpContext.Response.SetStatus(DavStatusCode.InternalServerError);
                    }
                    catch
                    {
                        // We might not be able to send the response, because a response
                        // was already initiated by the the request handler.
                    }
                }
                finally
                {
                    // Check if we need to dispose the request handler
                    // ReSharper disable once SuspiciousTypeConversion.Global
                    (requestHandler as IDisposable)?.Dispose();
                }
            }
            finally
            {
                // Always close the context
                await httpContext.CloseAsync().ConfigureAwait(false);
            }
        }