Skip to content

Buffering the entire request body in the pipe does not return the buffered data on the next read #8142

Closed
@davidfowl

Description

@davidfowl

Describe the bug

Buffering a content-length request body to the end doesn't return the buffered data after reading.

To Reproduce

using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace WebApplication101
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.Use(async (context, next) =>
            {
                if (context.Request.ContentLength is null)
                {
                    await next();
                    return;
                }

                await context.Request.BufferAsync();

                await next();
            });

            app.UseRouting(routes =>
            {
                routes.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });

                routes.MapPost("/api/values", async context =>
                {
                    var result = await context.Request.BodyPipe.ReadAsync();
                    var buffer = result.Buffer;

                    var value = Encoding.UTF8.GetString(buffer.ToArray());

                    await context.Response.WriteAsync(value);
                });
            });
        }
    }

    public static class RequestBufferingExtensions
    {
        public static async Task BufferAsync(this HttpRequest request)
        {
            // Buffer the entire request body into the pipe
            var cancellationToken = request.HttpContext.RequestAborted;

            while (true)
            {
                var result = await request.BodyPipe.ReadAsync(cancellationToken);
                var buffer = result.Buffer;
                request.BodyPipe.AdvanceTo(buffer.Start, buffer.End);

                if (result.IsCompleted)
                {
                    break;
                }
            }
        }
    }
}

Reading the request body hangs in the second middleware.

Expected behavior

The api/values end point should parse the buffered body

Metadata

Metadata

Assignees

Labels

DoneThis issue has been fixedarea-networkingIncludes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractionsbugThis issue describes a behavior which is not expected - a bug.

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions