2

Consider an http server that reflects the body of a request into the response. In pseudocode:

recv_req_headers()
send_resp_headers()
while have_req_body_data:
    chunk = recv_req_body_chunk()
    send_resp_body_chunk(chunk)

Similarly, consider an http client that sends the whole request before reading the response:

send_req_headers()
send_req_body()
recv_resp_headers()
recv_resp_body()

Now, when these two try to communicate, they deadlock, as the server will stop consuming the request once its send buffers are full. At that point, both sides are blocked in an attempt to send data to the other side.

Which side is in violation of the HTTP specs? I've read through RFC 7230 and RFC 7231 but failed to find guidance in either. There are similar questions, but no satisfactory answers.

Community
  • 1
  • 1
avakar
  • 32,009
  • 9
  • 68
  • 103
  • Why would they deadlock? The client sends the whole request before receiving the response. The server gets a whole request and is able to send a complete response. – apokryfos Jan 28 '17 at 08:00
  • The server doesn't get the entire request, it reads chunks and resends them to the client. Eventually the send buffer will fill up and the server will block in `send_resp_chunk` and then the client will block in `send_req_body`. – avakar Jan 28 '17 at 08:02
  • This would only deadlock if the client resent the response back to the server. Otherwise the client only sends a finite amount of data to the server so the server will read a finite amount of chunks. – apokryfos Jan 28 '17 at 08:04
  • No, because you can only have finite amount of data in transit. If the request is, say, 1GB in size, the client can't send it in its entirety without the server reading from the connection. The network receive buffers are not 1GB in size. – avakar Jan 28 '17 at 08:13
  • The server would probably just send a 413 due to this once the server's buffer is full. This will terminate the connection and drop any pending data. There's no violation of the specs here. Both sides are doing what's permitted by the protocol but at large volumes. – apokryfos Jan 28 '17 at 08:18
  • I don't understand what you mean. Can you elaborate? This server doesn't send 413. Is it in violation of the specs because of that? – avakar Jan 28 '17 at 08:27
  • My point is that neither side is doing anything in violation of the specs. Once the buffers fill up the side whose buffers filled up will give up on the connection. If the side whose buffers filled up is the server then the server needs to send a 413 response. However if it's the client then the client will simply need to drop the connection. I guess the violation comes if one or both of the 2 sides don't react correctly to their buffers filling up. However the client reaction is (I think) due to the TCP/IP spec rather than the HTTP spec. – apokryfos Jan 28 '17 at 08:30
  • When you say "once the buffers fill up the side whose buffers filled up will give up on the connection," where is that requirement coming from? That is not TCP behavior (TCP connections don't drop in this case, they just stall) and I can't find anything in the HTTP specs either. – avakar Jan 28 '17 at 08:47
  • Hmm, you're right about the TCP part, then the server would need to send a 413 if it no longer can handle the incoming request. It's not a deadlock though, that's the point. The client knows what to send exactly even if it eventually can't be processed by the server. – apokryfos Jan 28 '17 at 09:10
  • You might just as well say that the client can't handle the response. The two are in a symmetrical position. That's why I'm looking for a specs quote or something that would authoritatively require at least one side to always consume data from the connection. – avakar Jan 28 '17 at 09:43
  • But the client is not yet at a position to start consuming the response since it hasn't finished sending the request so it can't know if it can handle the response. I think that in this case there is no deadlock (as the client is not really waiting for the server while the server waits for the client) and there's no violation of the protocols. It's just a depletion of resources. Its also why you can't effectively block DDoS attacks via protocol rules because the individual requests are legitimate and it's the volume of them which is causing problems. – apokryfos Jan 28 '17 at 10:05
  • @apokryfos HTTP spec does not have any way of sending another status (for example 413) in the middle of a current transfer. Headers appear only ONCE at the beginning. In this case the HTTP connection simply stalls. However, most Linux systems (and most modems and routers run on Linux) will automatically disconnect TCP connections with no data transfer after a long timeout (this is to handle IE7 misbehaviour). So at some point some router on the internet (your home Wifi or your DSL or the router at various ISPs along the way etc.) will break the connection. – slebetman Jan 28 '17 at 12:00

0 Answers0