summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2015-03-30 19:52:32 +0200
committerDavid Kalnischkies <david@kalnischkies.de>2015-04-19 01:13:09 +0200
commit117038bac90261351518870b3f48136f134d4bfc (patch)
treeb486af6bb5e0b9fa0e843276459c236c03b26da7
parenta09f6eb8fc67cd2d836019f448f18580396185e5 (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.cc6
-rw-r--r--test/interactive-helper/aptwebserver.cc28
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;