diff options
author | David Kalnischkies <david@kalnischkies.de> | 2015-03-30 19:52:32 +0200 |
---|---|---|
committer | David Kalnischkies <david@kalnischkies.de> | 2015-04-19 01:13:09 +0200 |
commit | 117038bac90261351518870b3f48136f134d4bfc (patch) | |
tree | b486af6bb5e0b9fa0e843276459c236c03b26da7 | |
parent | a09f6eb8fc67cd2d836019f448f18580396185e5 (diff) |
handle servers closing encoded connections correctly
Servers who advertise that they close the connection get the 'Closes'
encoding flag, but this conflicts with servers who response with a
transfer-encoding (e.g. encoding) as it is saved in the same flag.
We have a better flag for the keep-alive (or not) of the connection
anyway, so we check this instead of the encoding.
This is in practice not much of a problem as real servers we talk to are
HTTP1.1 servers (with keep-alive) and there isn't much point in doing
chunked encoding if you are going to close anyway, but our simple
testserver stumbles over this if pressed and its a bit cleaner, too.
Git-Dch: Ignore
-rw-r--r-- | methods/http.cc | 6 | ||||
-rw-r--r-- | test/interactive-helper/aptwebserver.cc | 28 |
2 files changed, 24 insertions, 10 deletions
diff --git a/methods/http.cc b/methods/http.cc index 021b284d0..947002cc6 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -442,7 +442,7 @@ bool HttpServerState::RunData(FileFd * const File) { /* Closes encoding is used when the server did not specify a size, the loss of the connection means we are done */ - if (Encoding == Closes) + if (Persistent == false) In.Limit(-1); else if (JunkSize != 0) In.Limit(JunkSize); @@ -524,7 +524,7 @@ bool HttpServerState::Die(FileFd &File) // See if this is because the server finished the data stream if (In.IsLimit() == false && State != HttpServerState::Header && - Encoding != HttpServerState::Closes) + Persistent == true) { Close(); if (LErrno == 0) @@ -571,7 +571,7 @@ bool HttpServerState::Flush(FileFd * const File) return true; } - if (In.IsLimit() == true || Encoding == ServerState::Closes) + if (In.IsLimit() == true || Persistent == false) return true; } return false; diff --git a/test/interactive-helper/aptwebserver.cc b/test/interactive-helper/aptwebserver.cc index 644629a33..86d5c06f0 100644 --- a/test/interactive-helper/aptwebserver.cc +++ b/test/interactive-helper/aptwebserver.cc @@ -598,17 +598,24 @@ static void * handleClient(void * voidclient) /*{{{*/ { int client = *((int*)(voidclient)); std::clog << "ACCEPT client " << client << std::endl; - std::vector<std::string> messages; bool closeConnection = false; - std::list<std::string> headers; - while (closeConnection == false && ReadMessages(client, messages)) + while (closeConnection == false) { - // if we announced a closing, do the close - if (std::find(headers.begin(), headers.end(), std::string("Connection: close")) != headers.end()) + std::vector<std::string> messages; + if (ReadMessages(client, messages) == false) break; - headers.clear(); + + std::list<std::string> headers; for (std::vector<std::string>::const_iterator m = messages.begin(); m != messages.end() && closeConnection == false; ++m) { + // if we announced a closing in previous response, do the close now + if (std::find(headers.begin(), headers.end(), std::string("Connection: close")) != headers.end()) + { + closeConnection = true; + break; + } + headers.clear(); + std::clog << ">>> REQUEST from " << client << " >>>" << std::endl << *m << std::endl << "<<<<<<<<<<<<<<<<" << std::endl; std::string filename; @@ -760,9 +767,16 @@ static void * handleClient(void * voidclient) /*{{{*/ else sendError(client, 404, *m, sendContent, "", headers); } + + // if we announced a closing in the last response, do the close now + if (std::find(headers.begin(), headers.end(), std::string("Connection: close")) != headers.end()) + closeConnection = true; + + if (_error->PendingError() == true) + break; _error->DumpErrors(std::cerr); - messages.clear(); } + _error->DumpErrors(std::cerr); close(client); std::clog << "CLOSE client " << client << std::endl; return NULL; |