Opened 9 years ago

Closed 9 years ago

#164 closed defect (invalid)

nginx dropping response body for DELETE request

Reported by: Priit Laes Owned by: somebody
Priority: minor Milestone:
Component: nginx-core Version: 1.1.x
Keywords: Cc:
uname -a:
Linux [xxx] 2.6.32-042stab053.5 #1 SMP Tue Mar 27 11:42:17 MSD 2012 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.1.19
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-log-path=/var/log/nginx/access.log --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --lock-path=/var/lock/nginx.lock --pid-path=/var/run/nginx.pid --with-debug --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_realip_module --with-http_stub_status_module --with-http_ssl_module --with-http_sub_module --with-http_xslt_module --with-ipv6 --with-sha1=/usr/include/openssl --with-md5=/usr/include/openssl --with-mail --with-mail_ssl_module --add-module=/build/buildd-nginx_1.1.19-1~bpo60+1-amd64-T0OX_L/nginx-1.1.19/debian/modules/nginx-auth-pam --add-module=/build/buildd-nginx_1.1.19-1~bpo60+1-amd64-T0OX_L/nginx-1.1.19/debian/modules/nginx-echo --add-module=/build/buildd-nginx_1.1.19-1~bpo60+1-amd64-T0OX_L/nginx-1.1.19/debian/modules/nginx-upstream-fair --add-module=/build/buildd-nginx_1.1.19-1~bpo60+1-amd64-T0OX_L/nginx-1.1.19/debian/modules/nginx-dav-ext-module

Description

I'm using nginx together with uWSGI and noticed that responses for HTTP-DELETE requests are dropping response body even when status-code is 200. As per W3C's HTTP spec:

A successful response SHOULD be 200 (OK) if the response includes an entity describing the status, 202 (Accepted) if the action has not yet been enacted, or 204 (No Content) if the action has been enacted but the response does not include an entity.

Change History (6)

comment:1 by Maxim Dounin, 9 years ago

Could you please provide more details? By itself nginx doesn't return 200 to DELETE requests (i.e. with dav module used), and there is no special handling of responses to DELETE requests (once they are got from upstream server).

in reply to:  1 comment:2 by Priit Laes, 9 years ago

Replying to Maxim Dounin:

Could you please provide more details? By itself nginx doesn't return 200 to DELETE requests (i.e. with dav module used), and there is no special handling of responses to DELETE requests (once they are got from upstream server).

I am running a Flask app (Python/WSGI) via uWSGI, that handles DELETE request that should return a html-page with a status code 200 upon success, but no html-data reaches the client (tested with Firefox and WebKitGtk+/Epiphany):

Connection:		keep-alive
Content-Encoding:	gzip
Content-Type:		text/html; charset=utf-8
Date:			Tue, 08 May 2012 08:52:34 GMT
Server:			nginx/1.1.19
Set-Cookie:		session="fKnOV3aID9ayTPSalblgzc3yBr0=?shopping_cart=STU3Ci4=&shopping_cart_num=STAKLg==&shopping_cart_shp=STAKLg==&shopping_cart_sum=STAKLg=="; Path=/; HttpOnly
Transfer-Encoding:	chunked

Now exactly the same Flask app running using builtin werkzeug debug server responds to the successful http-DELETE request with code 200 and also sends out the html body:

Content-Length:	1621
Content-Type:	text/html; charset=utf-8
Date:		Tue, 08 May 2012 08:00:23 GMT
Server:		Werkzeug/0.8.3 Python/2.7.3
Set-Cookie:	session="rnPcxMKofR/N73YYrp2RrCLjGrw=?checkout=STU3Ci4=&shopping_cart=STI1Nwou&shopping_cart_num=STAKLg==&shopping_cart_shp=STAKLg==&shopping_cart_sum=STAKLg=="; Path=/; HttpOnly
Request Headers:

Now I'm not actually sure whether it's nginx or uWSGI that drops the message body, but the data does not reach the browser for sure. I'm also aware that the HTTP/1.1 spec doesn't actually say much whether to return data, but when the DELETE request is successful, there are following three options:

  • 200 (OK) if the response includes an entity describing the status
  • 202 (Accepted) if the action has not yet been enacted
  • 204 (No Content) if the action has been enacted but the response does not include an entity.

comment:3 by Maxim Dounin, 9 years ago

Quick test with uWSGI and trivial python app (variant of http://mdounin.ru/hg/nginx-tests/file/tip/uwsgi.t) suggests both nginx and uWSGI are ok, body is correctly returned. Could you please provide debug log?

You may also try to test with telnet/netcat and/or trace what happens on the wire to rule out possible client problems. (Actually, I suspect gzip compression and/or chunked encoding may be a problem for dav clients, you may try switching gzip off to test it.)

comment:4 by Priit Laes, 9 years ago

I'm now pretty sure that the problem isn't caused by nginx:

[debug] 28988#0: *4021 http uwsgi status 200 "200 OK"
[debug] 28988#0: *4021 http uwsgi header: "Content-Type: text/html; charset=utf-8"
[debug] 28988#0: *4021 http uwsgi header: "Content-Length: 1621"
[debug] 28988#0: *4021 http uwsgi header: "Set-Cookie: session=[]
[debug] 28988#0: *4021 http uwsgi header done
[debug] 28988#0: *4021 xslt filter header
[debug] 28988#0: *4021 HTTP/1.1 200 OK
Server: nginx/1.1.19
Date: Wed, 09 May 2012 03:37:58 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: session=[]
Content-Encoding: gzip

[debug] 28988#0: *4021 write new buf t:1 f:0 0000000000715FC8, pos 0000000000715FC8, size: 368 file: 0, size: 0
[debug] 28988#0: *4021 http write filter: l:0 f:0 s:368
[debug] 28988#0: *4021 http cacheable: 0
[debug] 28988#0: *4021 http upstream process upstream
[debug] 28988#0: *4021 pipe read upstream: 1
[debug] 28988#0: *4021 pipe preread: 1621
[debug] 28988#0: *4021 readv: 1:2220
[error] 28988#0: *4021 readv() failed (104: Connection reset by peer) while reading upstream, client: [xxx], server: [xxx], request: "DELETE /cart/_api/1584 HTTP/1.1", upstream: "uwsgi://unix:socket:", host: "[xxx]", referrer: "http://[xxx]"
[debug] 28988#0: *4021 pipe recv chain: -1
[debug] 28988#0: *4021 pipe write downstream: 1
[debug] 28988#0: *4021 pipe write downstream done
[debug] 28988#0: *4021 event timer: 13, old: 1336534738388, new: 1336534738391
[debug] 28988#0: *4021 http upstream exit: 0000000000000000

I also tried with curl and it returned the data fine. One difference betwen curl and browser is that with browser, the DELETE request is using the XMLHttpRequest.

comment:5 by Priit Laes, 9 years ago

When discussing this with uwsgi author, he pointed out that the problem was actually in the Python app:

08:21 < unbit> plaes: does your DELETE request (not-response) have a body ?
08:40 < unbit> and do you read that body in your app ?
08:41 < unbit> from the nginx logs it looks like it has a body and you are not reading it in the app
08:43 < plaes> so DELETE request shouldn't have the body?
08:43 < unbit> no i mean if a request has a body you have to read/consume it
08:44 < unbit> otherwise the socket will be clobbered

After reading the request body in the application view, things magically (see Clarke's third law) worked.

comment:6 by Maxim Dounin, 9 years ago

Resolution: invalid
Status: newclosed

Ok, closing this.

Note: See TracTickets for help on using tickets.