aspnet / KestrelHttpServer

[Archived] A cross platform web server for ASP.NET Core. Project moved to https://github.com/aspnet/AspNetCore
Apache License 2.0
2.62k stars 528 forks source link

Differences between Kestrel and WebListener #282

Closed jruckert closed 9 years ago

jruckert commented 9 years ago

Hi,

As per the request to outline some of the issues i've been having swapping out weblistener and moving to kestrel (https://github.com/aspnet/Hosting/issues/419)

I've created a simple HttpGet that accepts a guid as an input parameter, under the Weblistener i can see that everything is fine:

image

However when i swap this over to Kestrel (without any change in code, just the profile)

2015-10-23_10-43-39

The guid does not get parsed out. I'm also finding the same experiences with IFormFile with additional parameters and a couple of other options that i'll document and attach to this case.

Any advice would be greatly appreciated.

Cheers, Jonathan

Tratcher commented 9 years ago

This is probably caused by #124 which has a pending PR to fix it.

jruckert commented 9 years ago

@Tratcher could this explain the issues that i'm having with IFormFile? (which is a POST event).

Tratcher commented 9 years ago

Can you share a repro for the IFormFile? There's no reason for that to be different, it's implemented in a shared library. A raw header and body dump would be useful, or an httpclient sample.

Schlurcher commented 9 years ago

I've also experienced issues with IFormFile on Kestrel. Models won't get bound and in the rare case where it works the uploaded image is always garbled up. WebListener works fine from what I can tell.

Should I just paste a fiddler dump here?

jruckert commented 9 years ago

@Schlurcher that would be great. I'm having trouble isolating the issue into a separate project. I think it may be to the number of end points/controllers that i have in the solution ( > 300)

Schlurcher commented 9 years ago
POST http://127.0.0.1:5000/admin/videos/edit/1 HTTP/1.1
Host: 127.0.0.1:5000
Connection: keep-alive
Content-Length: 1404
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://ipv4.fiddler:5000
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryUzAtRALXTdA3EBrQ
DNT: 1
Referer: http://ipv4.fiddler:5000/admin/videos/edit/1
Accept-Encoding: gzip, deflate
Accept-Language: de-DE,en-US;q=0.8,en;q=0.6,de;q=0.4
Cookie: HL4nRbLOHHo=CfDJ8E8AbrWIfKBGitnIXH55UfJUhmVTLsZWAsuF4uqfWyF5zqO5Jzh119Z5eLylFr0tLSnwOBVK2q99HUiY1_borymauA681hgPDOQCVPJ9Qzvn4CyY3LKtzNjLim4Sen6weBlfF6-x3Tw4loE1i7Ar2GM

------WebKitFormBoundaryUzAtRALXTdA3EBrQ
Content-Disposition: form-data; name="Title"

Karma vs Lich King
------WebKitFormBoundaryUzAtRALXTdA3EBrQ
Content-Disposition: form-data; name="Slug"

karma-vs-lich-king
------WebKitFormBoundaryUzAtRALXTdA3EBrQ
Content-Disposition: form-data; name="Description"

Im letzten Versuch. Typisch!
------WebKitFormBoundaryUzAtRALXTdA3EBrQ
Content-Disposition: form-data; name="ReleaseDate"

2010-03-25
------WebKitFormBoundaryUzAtRALXTdA3EBrQ
Content-Disposition: form-data; name="FileUrl"

//mykarma.de/Videos/Lich%20King%20-%2025%20-%20Darlen.mp4
------WebKitFormBoundaryUzAtRALXTdA3EBrQ
Content-Disposition: form-data; name="ThumbnailUpload"; filename="edit_16x16.gif"
Content-Type: image/gif

GIF89a  Õ#  ÿ;–Û¥×ôÊ'  7oÎÖúÿu¼î™ù*5BÿËRÿ6 ]: v¼î“_  ›ÿÿì³feÌ™ù 4¡——ÿÿÿùÿúçÿóÍÑúÿ1”â¥×õoÎÌÌÿÒøÿo×ÿë¤oÑÿÌÿ“  ÿÿÿ                                                                                    !ù  # ,       kÀ‘pH
ŽÅähÃY„ÊáFi. Ê‚ sˆP®YáxEI­¡Q~ &i1xÇ×:€iðz|EdI
†u‚E
nD’
—Q›
pQ      QB§«­CA ;
------WebKitFormBoundaryUzAtRALXTdA3EBrQ
Content-Disposition: form-data; name="__RequestVerificationToken"

CfDJ8E8AbrWIfKBGitnIXH55UfIzRH223JY3l1QJmp1R1iPsbHgFn8212AM4_0CUhASieNwzyUE0X58LCBobIPRuCtYAjBzJ73T3YNQtCiS_9G6LcLWYHC59bxTmH22YC-NlgLOkgVYkYDxlcIrNyxFBG38
------WebKitFormBoundaryUzAtRALXTdA3EBrQ--

HTTP/1.1 200 OK
Date: Sat, 24 Oct 2015 23:27:10 GMT
Content-Type: text/html; charset=utf-8
Server: Kestrel
X-Frame-Options: SAMEORIGIN
Transfer-Encoding: chunked

400
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="IE=9; IE=EDGE" /> 

        <title>Videoverwaltung - Karma</title>

        <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.5/css/bootstrap.min.css" />
<meta name="x-stylesheet-fallback-test" class="hidden" /><script>!function(a,b,c){var d,e=document,f=e.getElementsByTagName("SCRIPT"),g=f[f.length-1].previousElementSibling,h=e.defaultView&&e.defaultView.getComputedStyle?e.defaultView.getComputedStyle(g):g.currentStyle;if(h&&h[a]!==b)for(d=0;d<c.length;d++)e.write('<link rel="stylesheet" href="'+c[d]+'"/>')}("visibility","hidden",["\/lib\/bootstrap\/dist\/css\/bootstrap.min.css"]);</script>
        <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap-touch-carousel/0.8.0/css/bootstrap-touch-carousel.css" />
<meta name="x-stylesheet-fallback
400
-test" class="carousel-caption" /><script>!function(a,b,c){var d,e=document,f=e.getElementsByTagName("SCRIPT"),g=f[f.length-1].previousElementSibling,h=e.defaultView&&e.defaultView.getComputedStyle?e.defaultView.getComputedStyle(g):g.currentStyle;if(h&&h[a]!==b)for(d=0;d<c.length;d++)e.write('<link rel="stylesheet" href="'+c[d]+'"/>')}("display","none",["\/lib\/bootstrap-touch-carousel\/css\/bootstrap-touch-carousel.css"]);</script>
        <link rel="stylesheet" href="/lib/bootstrap-fileinput/css/fileinput.min.css?v=XRDJzlez50HDRC-tkP7tOQDMu1IL-eswJeHRnp0l5ts" />
        <link rel="stylesheet" href="/css/site.css?v=H2ee9luM7oumnp7Sk5Ehox-rPZhXLXL5GEri_XIqCMI" />

</head>
<body>
    <div id="wrapper">
        <div id="page">
            <div id="header">

                <div class="gold-separator gold-separator-top"></div>

                <div id="logo" class="container-fluid clearfix">
                    <div id="karma-logo" class="pull-left"></div>
                    <div id="faction-l
400
ogo" class="pull-right"></div>
                </div>

                <div class="gold-separator gold-separator-double"></div>

                <div id="menu" class="navbar">
                    <div class="container-fluid">
                        <ul class="nav navbar-nav">
                            <li>
                                <a href="/">Home</a>
                            </li>
                            <li>
                                <a href="/roster">Mitglieder</a>
                            </li>
                            <li>
                                <a href="">Forum</a>
                            </li>
                            <li>
                                <a href="/videos">Videos</a>
                            </li>
                            <li class="dropdown">
                                <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">

401
           Gilde <span class="caret"></span>
                                </a>
                                <ul class="dropdown-menu">
                                    <li>
                                        <a href="/guild/about">
                                            Ãœber Karma
                                        </a>
                                    </li>
                                    <li>
                                        <a href="/guild/history">Geschichte</a>
                                    </li>
                                </ul>
                            </li>
                        </ul>

    <ul class="nav navbar-nav navbar-right">
        <li><a href="/account/login">Anmelden</a></li>
    </ul>

                    </div>
                </div>

                <div class="gold-separator gold-separator-middle"></div>

            </div>

            <div id="content">
                <div class="cont
400
ainer-fluid">

<div class="page-header">
    <h2>Videoverwaltung</h2>
</div>

<form class="form-horizontal" enctype="multipart/form-data" action="/admin/videos/edit/1" method="post">
    <div class="text-danger validation-summary-errors" data-valmsg-summary="true"><ul><li>Das Feld &quot;Title&quot; ist erforderlich.</li>
<li>Das Feld &quot;Slug&quot; ist erforderlich.</li>
<li>Das Feld &quot;Description&quot; ist erforderlich.</li>
<li>Das Feld &quot;FileUrl&quot; ist erforderlich.</li>
</ul></div>
    <div class="form-group">
        <label class="col-md-3 control-label" for="Title">Title</label>
        <div class="col-md-9">
            <input class="form-control input-validation-error" type="text" data-val="true" data-val-required="Das Feld &quot;Title&quot; ist erforderlich." id="Title" name="Title" value="" />
            <span class="text-danger field-validation-error" data-valmsg-for="Title" data-valmsg-replace="true">Das Feld &quot;Title&quot; ist erforderlich.</sp
400
an>
        </div>
    </div>

    <div class="form-group">
        <label class="col-md-3 control-label" for="Slug">Slug</label>
        <div class="col-md-9">
            <p class="form-control-static"></p>
            <input type="hidden" class="input-validation-error" data-val="true" data-val-required="Das Feld &quot;Slug&quot; ist erforderlich." id="Slug" name="Slug" value="" />
        </div>
    </div>
    <div class="form-group">
        <label class="col-md-3 control-label" for="Description">Description</label>
        <div class="col-md-9">
            <input class="form-control input-validation-error" type="text" data-val="true" data-val-required="Das Feld &quot;Description&quot; ist erforderlich." id="Description" name="Description" value="" />
            <span class="text-danger field-validation-error" data-valmsg-for="Description" data-valmsg-replace="true">Das Feld &quot;Description&quot; ist erforderlich.</span>
        </div>
    </div>
    <div class="form-group">

400
 <label class="col-md-3 control-label" for="ReleaseDate">ReleaseDate</label>
        <div class="col-md-9">
            <input class="form-control" type="date" id="ReleaseDate" name="ReleaseDate" value="" />
            <span class="text-danger field-validation-valid" data-valmsg-for="ReleaseDate" data-valmsg-replace="true"></span>
        </div>
    </div>
    <div class="form-group">
        <label class="col-md-3 control-label" for="FileUrl">FileUrl</label>
        <div class="col-md-9">
            <input class="form-control input-validation-error" type="text" data-val="true" data-val-required="Das Feld &quot;FileUrl&quot; ist erforderlich." id="FileUrl" name="FileUrl" value="" />
            <span class="text-danger field-validation-error" data-valmsg-for="FileUrl" data-valmsg-replace="true">Das Feld &quot;FileUrl&quot; ist erforderlich.</span>
        </div>
    </div>
    <div class="form-group">
        <label class="col-md-3 control-label" for="ThumbnailUpload">ThumbnailUpload</label>

401
        <div class="col-md-9">
            <input class="form-control" type="file" id="ThumbnailUpload" name="ThumbnailUpload" />
            <span class="text-danger field-validation-valid" data-valmsg-for="ThumbnailUpload" data-valmsg-replace="true"></span>
            <img src="/admin/videos/thumbnail/1" />
        </div>
    </div>
    <div class="form-group">
        <div class="col-sm-offset-3 col-sm-9">
            <button type="submit" class="btn btn-success">Speichern</button>
            <a class="btn btn-default" href="/admin/videos">Abbrechen</a>
            <button type="submit" class="btn btn-danger pull-right">Löschen</button>
        </div>
    </div>
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8E8AbrWIfKBGitnIXH55UfJ7WqwNH6B2cbiqy-rISBPLgWf6YIh5oUon_3i-7XU5MYPi0T8g9eigWQ2FFobSztAVxvHp_Ca4eAsMGZ355FccrZnfT7I2riB3EHTERnQNY0M3BNbDKBiwqTfTogYtqv8" /></form>
                </div>
            </div>
        </div>

        <footer id="footer"></footer>

400
</div>

    <script src="//content.jwplatform.com/libraries/fl6IlGzn.js"></script>
    <script src="//static.wowhead.com/widgets/power.js"></script>
    <script>var wowhead_tooltips = { "colorlinks": true, "iconizelinks": true, "renamelinks": true }</script>

        <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.4.min.js"></script>
<script>(window.jQuery||document.write("<script src=\"\/lib\/jquery\/dist\/jquery.min.js\"><\/script>"));</script>
        <script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.5/bootstrap.min.js"></script>
<script>(window.jQuery && window.jQuery.fn && window.jQuery.fn.modal||document.write("<script src=\"\/lib\/bootstrap\/dist\/js\/bootstrap.min.js\"><\/script>"));</script>
        <script src="https://ajax.aspnetcdn.com/ajax/hammer.js/2.0.4/hammer.min.js"></script>
<script>(window.Hammer||document.write("<script src=\"\/lib\/hammer.js\/hammer.js\"><\/script>"));</script>
        <script src="https://ajax.aspnetcdn.com/ajax/bootstrap-t
20c
ouch-carousel/0.8.0/js/bootstrap-touch-carousel.js"></script>
<script>(window.Hammer && window.Hammer.Instance||document.write("<script src=\"\/lib\/bootstrap-touch-carousel\/dist\/js\/bootstrap-touch-carousel.js\"><\/script>"));</script>
        <script src="/lib/bootstrap-fileinput/js/fileinput.min.js"></script>
        <script src="/lib/bootstrap-fileinput/js/fileinput_locale_de.js"></script>
        <script src="/js/site.js?v=pWWKhjbo2BKFSXcher5Oy60tW3sCWgrpnMZr5fZSujY"></script>

</body>
</html>
0
Schlurcher commented 9 years ago

If need be I probably could also whip together a small project, though that will have to wait until tomorrow.

Tratcher commented 9 years ago

Was this with beta7 or beta8? There was a request body corruption bug fixed near the end of beta8 https://github.com/aspnet/KestrelHttpServer/issues/234.

jruckert commented 9 years ago

When i do a HttpPost, i can see that under the IFormCollection there are no files that have been identified (i put in a dummy ModelBinder to see what was going on), i'm just trying to get a Trace/Header for you, but there is no easy way of seeing this as the sender is a C# HttpClient.

Schlurcher commented 9 years ago

@Tratcher: 1.0.0-rc1-15767

jruckert commented 9 years ago

With weblistener:

image

With Kestrel:

image
jruckert commented 9 years ago

@Tratcher seems that this is still an issue - I'm trying to get a dump of the C# HttpClient and what it sends.

web listener:

image

Kestrel:

image
jruckert commented 9 years ago

POST /api/update/myfile HTTP/1.1 Connection: Keep-Alive Content-Type: multipart/form-data; boundary="a777ef07-5c41-4610-8845-bd9beef7a4e1" Authorization: Negotiate XXXXX Expect: 100-continue Host: localhost:26544 X-IIS-WindowsAuthToken: 5dc X-Forwarded-For: [::1]:20660 X-Forwarded-Proto: http Content-Length: 42424

--a777ef07-5c41-4610-8845-bd9beef7a4e1 Content-Type: text/plain; charset=utf-8 Content-Disposition: form-data; name="Status"

Approved --a777ef07-5c41-4610-8845-bd9beef7a4e1 Content-Type: text/plain; charset=utf-8 Content-Disposition: form-data; name="ElapsedTime"

00:00:07.6969261 --a777ef07-5c41-4610-8845-bd9beef7a4e1 Content-Disposition: form-data; name="turnDocument"; filename="Turn.docx"; filename*=utf-8''%22Turn.docx%22

PK * FILE CONTENT IN HERE REMOVED * --a777ef07-5c41-4610-8845-bd9beef7a4e1--

jruckert commented 9 years ago

Note when i change the Content-Disposition: (and remove the filename)

to be only

Content-Disposition: form-data; name="turnDocument"

the error still persists.

Schlurcher commented 9 years ago

I've whipped together a project which repros the behaviour.

https://github.com/Schlurcher/KillerKestrel

The magic happens on the Contact page. Works with WebListener, fails with Kestrel.

jruckert commented 9 years ago

Just an update from what i have found overnight.

If i change the C# client logic from

multipartFormDataContent.Add(new ByteArrayContent(fileBytes), '"' + "turnDocument" + '"', '"' + "Turn.docx" + '"');

to

multipartFormDataContent.Add(new StreamContent(documentStream), '"' + "turnDocument" + '"', '"' + "Turn.docx" + '"');

This can parse the body of the content as expected using Kestrel.

jruckert commented 9 years ago

I reverted the code back to 1.0.0-beta8 and it is now working, however with the latest RC1 this is broken.

Working Repo of the issue is here (including Minimal Web App and Http Console App, and Blank Word Document):

https://github.com/jruckert/WindowsAuthOnly

TestController

[Route("api/test")]
    public class TestController : Controller
    {
        [HttpPost("update/document")]
        public IActionResult UpdateDocumentAndStatus(IFormFile document)

running under web -> IFormFile document is null

running under weblistener -> IFormFile document is populated.

Tratcher commented 9 years ago

@Schlurcher your killerkestrel sample fails for me when using either weblistener or kestrel. The HttpContext.Request.Form is populated and has one file, but it doesn't bind to ThumbnailUpload.

Schlurcher commented 9 years ago

Weird. I just pulled it on a different machine and F5'd it, with basically the same results as on my other machine.

With WebListener:

listener

(Title is hidden, but it's populated.)

With IIS Express proxied Kestrel:

iisproxykestrel

With Kestrel:

kestrel

Sometimes Kestrel ALMOST works:

kestrelalmost

Plus sometimes the requests just seem to "hang" there for ages, until I hit Save again, and then both get flushed with varying results.

Schlurcher commented 9 years ago

Still on rc1, btw. Should I rollback to beta8 like jruckert and post the results?

Tratcher commented 9 years ago

I think we're all looking at different issues in different versions. We will get the aspnetvnext feed updated soon and then we can all sync up on the same versions and continue debugging.

jruckert commented 9 years ago

Agree, the latest rc1 on myget seems to have the issue and we are hanging out for the next update! I will continue work using the weblistener and revisit this once the feed is updated.

Schlurcher commented 9 years ago

@Tratcher Seems like the new rc1 bits took care of it. Everything works now for my case.

jruckert commented 9 years ago

@Tratcher same here

DamianEdwards commented 9 years ago

Closing this out as it seems latest bits fix this.