Skip to content

Webdav Get 0 bytes - stream already consumed by loggingresponse #73

@houbi56

Description

@houbi56

We found an issue that emerged in our test/QA-environment where if debug-logging is activated a WebDav GET request would return 0 bytes.
Traced this (after many a wild goose chases :)) to the behaviour of the WebDavIndirectResult.cs (in branch release/2.0 which we're using).

        public override async Task ExecuteResultAsync(ActionContext context)
        {
            var response = context.HttpContext.Response;

            // Register the WebDAV response if it's disposable
            if (_result is IDisposable disposableResult)
            {
                response.RegisterForDispose(disposableResult);
            }
            _logger?.LogDebug("WebDavIndirectResult before ExecuteResultAsync");
            // Sets the HTTP status code
            await base.ExecuteResultAsync(context).ConfigureAwait(false);
            _logger?.LogDebug("WebDavIndirectResult after ExecuteResultAsync");

            // Sets the reason phrase
            var responseFeature = context.HttpContext.Features.Get<IHttpResponseFeature>();
            if (responseFeature != null)
            {
                responseFeature.ReasonPhrase = _result.StatusCode.GetReasonPhrase();
            }

            if (_logger?.IsEnabled(LogLevel.Debug) ?? false)
            {
                _logger?.LogDebug("WebDavIndirectResult logging before");
                var loggingResponse = new LoggingWebDavResponse(_context);
               //Stream consumed here
                await _result.ExecuteResultAsync(loggingResponse, context.HttpContext.RequestAborted).ConfigureAwait(false);
                if (!string.IsNullOrEmpty(loggingResponse.ContentType))
                {
                    var mediaType = new MediaType(loggingResponse.ContentType);
                    if (_supportedMediaTypes.Any(x => mediaType.IsSubsetOf(x)))
                    {
                        var doc = loggingResponse.Load();
                        if (doc != null)
                        {
                            _logger.LogDebug(
                                "WebDAV Response: {Response}",
                                doc.ToString(SaveOptions.OmitDuplicateNamespaces));
                        }
                    }
                }
                _logger?.LogDebug("WebDavIndirectResult logging return");
                return;
            }

            // Writes the XML response
            //Stream also consumed here
            await _result.ExecuteResultAsync(new WebDavResponse(_context, response), context.HttpContext.RequestAborted).ConfigureAwait(false);
        }

The above code causes the document stream to be consumed twice, first in the LoggingWebDavResponse and then in the await _result.ExeCuteResultAsync(...) at the bottom.
Second time the stream is already consumed causing the stream.CopyToAsync(body) to write 0 bytes.

I'd be happy to put up a PR but there are multiple ways this issue can be alleviated so I would need your input on the preferred way.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions