Summary: | 413 errors not returned to browser - also fails to server errordocument if present | ||
---|---|---|---|
Product: | Apache httpd-2 | Reporter: | Gareth Webbley <garethwebbley> |
Component: | Core | Assignee: | Apache HTTPD Bugs Mailing List <bugs> |
Status: | RESOLVED DUPLICATE | ||
Severity: | normal | CC: | tom |
Priority: | P3 | ||
Version: | 2.0.48 | ||
Target Milestone: | --- | ||
Hardware: | PC | ||
OS: | All |
Description
Gareth Webbley
2003-03-06 14:16:51 UTC
After further testing this appears to only be a problem with IE. All works as expected with Opera and Mozilla. I have also encountered this bug, and in my testing it has not been attributable to a specific browser - it has affected any and every browser I have tested. I believe this is a similar bug to 21544 - http://nagoya.apache.org/bugzilla/show_bug.cgi?id=21544 - and I disagree with the conclusion that was drawn there. I am testing over a fast network link ot the server, and transmitting the file takes very little time - less than one second. Occasionally the 413 responce IS thrown up, especially if LimitRequestBody is small (I tested at 100kb, and the 413 error was returned for files upto 200kb), but testing with the limit set to 1048576 bytes and uploading a 1048577 byte file causes a null responce. Software used: Apache 2.0.48 Linux 2.4.20 Internet Explorer 6 SP 1 Mozilla Firebird 0.6 Expected Responce: Server replies with 413 error message Actual Responce: The server closes the connection Code to replicate: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Error</title> </head> <body marginheight="0" marginwidth="0" rightmargin="0" topmargin="0" leftmargin="0" bottommargin="0"> <form id="attachForm" name="attachForm" enctype="multipart/form-data" method="post" action="/html/test413.html"> <BR><input class="browseAttach" name="file" size="25" type="file"> <P><INPUT TYPE="submit" VALUE="Upload file" METHOD="post"> </form> </body> </html> in httpd.conf: LimitRequestBody 1048576 Choose a file > 1048576 bytes Sounds like a server crash. What program receives the upload? Is there anything related in the errorlog? Only what is to be expected : [Sun Jan 25 22:05:40 2004] [error] [client 192.168.0.50] Requested content-length of 1049317 is larger than the configured limit of 1048576, referer: http://site/news/tst-upload.html The error gets there, but no responce/status code is returned to the browser. FWIW, I was doing some testing recently with an Apache 2-based server and a plug-in which can return 413, trying to see how to get IE to display a custom message via ErrorDocument. My network traces showed the server always seemed to return the right data (either 302 or 413 response based on type of ErrorDocument) but IE would not display it. But then I tried a large error document (8K or so IIRC) and then it worked. This is a slightly different flow than when Apache generates the 413. I saw a similar bug to this in 2.0 in the C-L parsing error path in ap_http_filter; it failed to set ctx->remaining = 0, and then some later filter aborted and just closed the connection. Perhaps the same thing is correct for the ctx->remaining > ctx->limit case. I vote for this bug to be fixed too! It's really annoying! I too get this in the error log: [Tue Jul 26 12:47:35 2005] [error] [client x.x.x.x] Request content-length of 28495103 is larger than the configured limit of 5242880 And a strace of httpd -X shows the following (with comments): open("/home/xxx/public_html/.htaccess", O_RDONLY|O_LARGEFILE) = 5 fstat64(5, {st_mode=S_IFREG|0660, st_size=818, ...}) = 0 fstat64(5, {st_mode=S_IFREG|0660, st_size=818, ...}) = 0 old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40015000 read(5, "# Error documents\r\nErrorDocument"..., 4096) = 818 read(5, "", 4096) = 0 close(5) = 0 munmap(0x40015000, 4096) = 0 lstat64("/home/xxx/public_html/cgi-bin", {st_mode=S_IFDIR|0755, st_size=136, ...}) = 0 open("/home/xxx/public_html/cgi-bin/.htaccess", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory) lstat64("/home/xxx/public_html/cgi-bin/foo.cgi", {st_mode=S_IFREG|0755, st_size=4928, ...}) = 0 open("/home/xxx/public_html/cgi-bin/foo.cgi", O_RDONLY|O_LARGEFILE) = 5 fcntl64(5, F_DUPFD, 15) = 20 close(5) = 0 read(20, "#!/usr/bin/perl -w\n\n# This is a t"..., 4096) = 4096 close(20) = 0 time(NULL) = 1122378455 write(15, "[Tue Jul 26 12:47:35 2005] [erro"..., 139) = 139 ^^^ This corresponds to the error_log entry alarm(300) = 0 alarm(0) = 300 alarm(300) = 0 alarm(0) = 300 alarm(300) = 0 alarm(0) = 300 write(4, "HTTP/1.1 413 Request Entity Too "..., 685) = 685 ^^^ This *looks* like it's trying to return something to the browser! And the handle (4) is the same one that is all requests and responses are read from/written to throughout the strace dump. time(NULL) = 1122378455 write(17, "host-x-x-x-x.xxxxx.com"..., 263) = 263 ^^^ This corresponds to the access_log entry alarm(30) = 0 shutdown(4, 1 /* send */) = 0 select(5, [4], NULL, NULL, {2, 0}) = 1 (in [4], left {2, 0}) read(4, "\231Hy\230\2710\217\253\20r\201t\3443)\227<\24XC,\2168"..., 512) = 512 select(5, [4], NULL, NULL, {2, 0}) = 1 (in [4], left {2, 0}) read(4, "\37\207\37qm\373\7\201^\254\215\272\273o\340]~\f\237>|"..., 512) = 512 ^^^ These last 4 lines are then repeated, and repeated (although the actual data changes). The handle is again 4, and the data corresponds to a file uploaded in the request, so it looks like httpd is accepting the request!!! I'm not that knowledgable at programming under *nix (yet), so I thought I'd post this in case it helps anyone. After a day of reading source-code and running Ethereal (which I wish I'd done first!), I think I understand what is going on. I dont think this is actually a bug in apache at all... This is what happens: * The browser sends the request. In my case it is a multi-part POST which includes a file too big for the limit set by LimitRequestBody. * The server responds with the expected 413 error page. It then calls lingering_close() in main/http_main.c which partially closes the socket, stopping the server sending any more outgoing data, and also causing a TCP FIN to be sent to the browser. The FIN packet indicates that the server is done sending and wishes to close the connection. The server then continues to accept incoming data from the browser in order to try and avoid a situation that happens later anyway (read on). * Instead of displaying the returned 413 error page, the browser ignores both the 413 error page and the FIN packet and continues to send it's request! The server continues to soak it up (waiting for the connection to close). * After a designated timeout period (30 seconds), the server decides to give up waiting for the browser to stop spewing rubbish, and closes the connection. When the TCP mechanism at the server-end then recieves further incoming packets from the browser, it responds with an RST packet. This is precisely the situation that lingering_close() tries to prevent, because the browser then believes the connection to have been unexpectedly reset. This causes the browser to discard any previous response from the server (which is why no one ever sees the 413 error page!) and display the familliar "Net Reset Error". I dont know the ins and outs of the HTTP protocol, and frankly I want to go to bed, not wade through RFCs! But it seems to me that this is an issue with the browser isn't it? Surely if a response has been sent to the browser, and that response was an error, and it was followed by a TCP FIN packet, isn't it reasonable to assume that the rest of the request can be discarded? Surely this would make more sense, especially in the case where the request is large and the error is the "413 Request Entity Too Large" error! I've tried a couple of browsers. The following exhibited the above behavior: MSIE 6 Firefox 1.0.6 However the following worked ok: Opera 7.53 It looks like Opera waits for a "100 Continue" response from the server before spewing the large upload... I'll post a bug report on FireFox's Bugzilla too. Screw IE though. :o) I'd very much like to hear what any of the apache team think about all this! As I said before, I'm still learning about a lot of this stuff... Before I go, here's an (edited) Ethereal capture of the above bahavior: FRAME TIME SOURCE IP DESTINATION IP 1 0.000000 192.168.0.1 web.se.rv.er TCP 2076 > http [SYN] Seq=0 Ack=0 Win=64240 Len=0 MSS=1460 2 0.046966 web.se.rv.er 192.168.0.1 TCP http > 2076 [SYN, ACK] Seq=0 Ack=1 Win=5840 Len=0 MSS=1460 3 0.047054 192.168.0.1 web.se.rv.er TCP 2076 > http [ACK] Seq=1 Ack=1 Win=64240 Len=0 4 0.050230 192.168.0.1 web.se.rv.er HTTP POST /foo.html HTTP/1.1 ^^^ server sends request... 5 0.050940 192.168.0.1 web.se.rv.er HTTP Continuation ^^^ ...and then immediately starts sending the file. From the packet: Content-Type: multipart/form-data; boundary=------[snip]\r\n Content-Length: 28495103\r\n \r\n Data (1345 bytes) 6 0.114983 web.se.rv.er 192.168.0.1 TCP http > 2076 [ACK] Seq=1 Ack=671 Win=6700 Len=0 7 0.115087 192.168.0.1 web.se.rv.er HTTP Continuation 8 0.115093 192.168.0.1 web.se.rv.er HTTP Continuation 9 0.152971 web.se.rv.er 192.168.0.1 TCP http > 2076 [ACK] Seq=1 Ack=2131 Win=8760 Len=0 10 0.153055 192.168.0.1 web.se.rv.er HTTP Continuation 11 0.153063 192.168.0.1 web.se.rv.er HTTP Continuation ^^^ various server acknowledgments, and the browser sendings... 12 0.193151 web.se.rv.er 192.168.0.1 HTTP HTTP/1.1 413 Request Entity Too Large ^^^ server respondes with 413 error (packet includes the HTML error page)... 13 0.193968 web.se.rv.er 192.168.0.1 TCP http > 2076 [FIN, ACK] Seq=676 Ack=2131 Win=8760 Len=0 ^^^ ...followed by a FIN packet 14 0.194024 192.168.0.1 web.se.rv.er HTTP Continuation 15 0.231948 web.se.rv.er 192.168.0.1 TCP http > 2076 [ACK] Seq=677 Ack=5051 Win=14600 Len=0 16 0.232125 192.168.0.1 web.se.rv.er HTTP Continuation ^^^ browser continues to send, server continues to acknowledge. . . . this continues for 30 seconds until . . . 888 31.572576 web.se.rv.er 192.168.0.1 TCP [TCP ZeroWindow] http > 3510 [RST] Seq=706 889 31.785558 web.se.rv.er 192.168.0.1 TCP [TCP ZeroWindow] [TCP Dup ACK 888#1] http > 3510 [RST] Seq=706 890 31.843627 web.se.rv.er 192.168.0.1 TCP [TCP ZeroWindow] [TCP Dup ACK 888#2] http > 3510 [RST] Seq=706 891 31.883537 web.se.rv.er 192.168.0.1 TCP [TCP ZeroWindow] [TCP Dup ACK 888#3] http > 3510 [RST] Seq=706 ^^^ server responds with RST packets. Browser stops sending and displays error. Right. In this scenario, Apache can't keep reading unlimited data from the browser, yet doing so is the only way to get the browser to read the error response. If the browser were to send Expect: 100-Continue and Content-Length with the request, Apache can reject it before the browser starts sending the data. Apache either responds with an error such as 413, or Apache sends 100-Continue to tell the browser to start sending data. IE doesn't implement this. (no knowledge here of which browsers do) The lingering close bug is a genuine cause of this problem, insofar as this issue is fixable; so marking this as a duplicate of that bug. *** This bug has been marked as a duplicate of 35292 *** |