RickStrahl / Westwind.AspnetCore.LiveReload

ASP.NET Core Live Reload Middleware that monitors file changes in your project and automatically reloads the browser's active page
Other
469 stars 42 forks source link

Writing to the response body is invalid for responses with status code 304 #2

Closed Swellenator closed 5 years ago

Swellenator commented 5 years ago

Using .NET Core 3 Preview 5, blazor server side

I get an exception Writing to the response body is invalid for responses with status code 304.

Full stack trace:

info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0] User profile is available. Using 'C:\Users\[user]\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest. info: Microsoft.Hosting.Lifetime[0] Now listening on: http://localhost:4698 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down. info: Microsoft.Hosting.Lifetime[0] Hosting environment: Development info: Microsoft.Hosting.Lifetime[0] Content root path: c:\[projectfolder] info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 GET http://localhost:4698/[page] warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3] Failed to determine the https port for redirect. info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0] Executing endpoint '/_Host' info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[3] Route matched with {page = "/_Host"}. Executing page /_Host info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[103] Executing an implicit handler method - ModelState is Valid info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[104] Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult. info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[4] Executed page /_Host in 218.5164ms info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1] Executed endpoint '/_Host' info: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished in 470.51140000000004ms 200 text/html; charset=utf-8 info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 GET http://localhost:4698/_framework/blazor.server.js info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 GET http://localhost:4698/css/main.css info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[2] Sending file. Request path: '/_framework/blazor.server.js'. Physical path: 'N/A' info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[2] Sending file. Request path: '/css/main.css'. Physical path: 'c:\[projectfolder]\wwwroot\css\main.css' info: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished in 37.6282ms 200 image/png info: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished in 33.9769ms 200 text/css info: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished in 39.5815ms 200 application/javascript info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 GET http://localhost:4698/js/script.min.js info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[2] Sending file. Request path: '/js/script.min.js'. Physical path: 'c:\[projectfolder]\wwwroot\js\script.min.js' info: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished in 21.4679ms 200 application/javascript info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 GET http://localhost:4698/_framework/blazor.boot.json info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[6] The file /_framework/blazor.boot.json was not modified info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 POST http://localhost:4698/_blazor/negotiate text/plain;charset=UTF-8 0 info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0] Executing endpoint '/_blazor/negotiate' info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1] Executed endpoint '/_blazor/negotiate' info: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished in 55.9662ms 200 application/json fail: Microsoft.AspNetCore.Server.Kestrel[13] Connection id "0HLN31AAM3HVJ", Request id "0HLN31AAM3HVJ:00000002": An unhandled exception was thrown by the application. System.InvalidOperationException: Writing to the response body is invalid for responses with status code 304. at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ThrowWritingToResponseBodyNotSupported() at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.FirstWriteAsyncInternal(ReadOnlyMemory1 data, CancellationToken cancellationToken) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.FirstWriteAsync(ReadOnlyMemory1 data, CancellationToken cancellationToken) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.WritePipeAsync(ReadOnlyMemory1 data, CancellationToken cancellationToken) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponsePipeWriter.WriteAsync(ReadOnlyMemory1 source, CancellationToken cancellationToken) at System.IO.Pipelines.WriteOnlyPipeStream.WriteAsyncInternal(ReadOnlyMemory1 source, CancellationToken cancellationToken) at System.IO.Pipelines.WriteOnlyPipeStream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) at System.IO.Pipelines.WriteOnlyPipeStream.Write(Byte[] buffer, Int32 offset, Int32 count) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponseStream.Write(Byte[] buffer, Int32 offset, Int32 count) at System.IO.Stream.Write(ReadOnlySpan1 buffer) at Westwind.AspNetCore.LiveReload.LiveReloadMiddleware.InvokeAsync(HttpContext context) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication1 application) info: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished in 215.2517ms 304 application/json info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 GET http://localhost:4698/__livereload info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 GET http://localhost:4698/_blazor?id=sm4IsWwVfa1mnD6Obu0ynw info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0] Executing endpoint '/_blazor' info: Microsoft.AspNetCore.SignalR.HubConnectionContext[1] Completed connection handshake. Using HubProtocol 'blazorpack'.`

My Configure method is

public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { // Before other output generating middleware handlers app.UseLiveReload(); app.UseDeveloperExceptionPage(); } else { // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } ...

So the live reload middleware is the first one in the stack. The website still reloads fine so it's not making any functional problem just would be better not to have an exception in there.

Cheers

RickStrahl commented 5 years ago

That makes sense. I think the solution here is that injection should only happen on a 200 response.

RickStrahl commented 5 years ago

Added the 200 check in e745b11d7d5064b086346884850a51e66a511df7

Swellenator commented 5 years ago

Hmmm doesn't seem to be fixed in 0.1.2, still getting

fail: Microsoft.AspNetCore.Server.Kestrel[13] Connection id "0HLN3VHHND77G", Request id "0HLN3VHHND77G:00000002": An unhandled exception was thrown by the application. System.InvalidOperationException: Writing to the response body is invalid for responses with status code 304.

Should it be fixed? It's hard to tell what commits are in the release.

RickStrahl commented 5 years ago

The commit is linked here: e745b11

I don't have a good reliable way to generate 304's - how are you generating those? From the StaticFileModule?

It looks like the error is different now, so the code path loooks like it's bypassing the translation code correctly. I do write to the response basically copying the original stream, so looks like I have to check for an empty stream and not write in that case.

4c36612eaeb90caf09ddba93d5517c3a18df7b6c

RickStrahl commented 5 years ago

Can you retry your failure scenario with 0.1.4+ to verify whether this is fixed?

aliostad commented 4 years ago

Just curious, I am getting these reports on my library, did you find out what it was?

https://github.com/aliostad/CacheCow/issues/241

RickStrahl commented 4 years ago

Yeah you can't write headers after the response started and Core does some crazy stuff to determine when the response is started. Basically I'd look for any code that's adding headers or setting properties (like the content-length) that affect the response after the response has been initialized.

Specifically in my case the problem is that Core does a FlushAsync() call at the very beginning of writing to the Response. Once that fires you can't mess with headers. In my ResponseStreamBuffer subclass I had to override it to handle any header adjustments in there.

RickStrahl commented 4 years ago

Ok I looked a little closer at your error message and realized that the error is something different.

The message is pretty clear though: A 304 should have no content attached to it, so I'd guess your code has to check to see whether the response is a valid response code (ie. 200) and only then write the cache out? If it's 304, you need to write the cache headers? Or are you generating the 304 in which case you can skip writing more easily.

I ran into a similar thing (I think with a 204 - no content and accidentally writing output anyway). I had to check explicitly for a 200 response and only then write my modified content.

aliostad commented 4 years ago

Thanks!

Yeah the error is clear. My problem is that it happens only sparingly. I wonder if it could have anything to do with sending headers early, etc due to its inconsistent occurrence.

I think I have to set up a test bed and run it for a while to see if I can catch it.