summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <kalnischkies@gmail.com>2012-07-12 12:04:36 +0200
committerDavid Kalnischkies <kalnischkies@gmail.com>2012-07-12 12:04:36 +0200
commit056c36565706cad136df288db777c01555f4ecd9 (patch)
treec97a2f993eb141cfae880d90dc0f4ea57c4be2db
parent06b3095f81d9a730e8cb95274c8208cb0604cdfe (diff)
add (partial) partial request support for the webserver
-rw-r--r--test/interactive-helper/aptwebserver.cc71
1 files changed, 63 insertions, 8 deletions
diff --git a/test/interactive-helper/aptwebserver.cc b/test/interactive-helper/aptwebserver.cc
index 4ef9631b8..ff60d64a3 100644
--- a/test/interactive-helper/aptwebserver.cc
+++ b/test/interactive-helper/aptwebserver.cc
@@ -35,7 +35,7 @@ char const * const httpcodeToStr(int const httpcode) { /*{{{*/
case 203: return "203 Non-Authoritative Information";
case 204: return "204 No Content";
case 205: return "205 Reset Content";
- case 206: return "206 Partial Conent";
+ case 206: return "206 Partial Content";
// Redirections 3xx
case 300: return "300 Multiple Choices";
case 301: return "301 Moved Permanently";
@@ -113,6 +113,8 @@ bool sendHead(int const client, int const httpcode, std::list<std::string> &head
date.append(TimeRFC1123(time(NULL)));
headers.push_back(date);
+ headers.push_back("Accept-Ranges: bytes");
+
std::clog << ">>> RESPONSE >>>" << std::endl;
bool Success = true;
for (std::list<std::string>::const_iterator h = headers.begin();
@@ -135,7 +137,8 @@ bool sendFile(int const client, FileFd &data) { /*{{{*/
while ((Success &= data.Read(buffer, sizeof(buffer), &actual)) == true) {
if (actual == 0)
break;
- Success &= FileFd::Write(client, buffer, actual);
+ if (Success == true)
+ Success &= FileFd::Write(client, buffer, actual);
}
if (Success == true)
Success &= FileFd::Write(client, "\r\n", 2);
@@ -268,7 +271,7 @@ void sendDirectoryListing(int const client, std::string const &dir, std::string
sendData(client, response);
}
/*}}}*/
-bool parseFirstLine(int const client, std::string const &request, std::string &filename, bool &sendContent) { /*{{{*/
+bool parseFirstLine(int const client, std::string const &request, std::string &filename, bool &sendContent, bool &closeConnection) { /*{{{*/
if (strncmp(request.c_str(), "HEAD ", 5) == 0)
sendContent = false;
if (strncmp(request.c_str(), "GET ", 4) != 0)
@@ -289,8 +292,12 @@ bool parseFirstLine(int const client, std::string const &request, std::string &f
size_t httpstart = fileend;
for (; request[httpstart] == ' '; ++httpstart);
- if (strncmp(request.c_str() + httpstart, "HTTP/1.1\r", 9) != 0) {
- sendError(client, 500, request, sendContent, "Not an HTTP/1.1 request");
+ if (strncmp(request.c_str() + httpstart, "HTTP/1.1\r", 9) == 0)
+ closeConnection = strcasecmp(LookupTag(request, "Connection", "Keep-Alive").c_str(), "Keep-Alive") != 0;
+ else if (strncmp(request.c_str() + httpstart, "HTTP/1.0\r", 9) == 0)
+ closeConnection = strcasecmp(LookupTag(request, "Connection", "Keep-Alive").c_str(), "close") == 0;
+ else {
+ sendError(client, 500, request, sendContent, "Not an HTTP/1.{0,1} request");
return false;
}
@@ -384,15 +391,15 @@ int main(int const argc, const char * argv[])
<< " on socket " << sock << std::endl;
while (ReadMessages(client, messages)) {
+ bool closeConnection = false;
for (std::vector<std::string>::const_iterator m = messages.begin();
- m != messages.end(); ++m) {
+ m != messages.end() && closeConnection == false; ++m) {
std::clog << ">>> REQUEST >>>>" << std::endl << *m
<< std::endl << "<<<<<<<<<<<<<<<<" << std::endl;
-
std::list<std::string> headers;
std::string filename;
bool sendContent = true;
- if (parseFirstLine(client, *m, filename, sendContent) == false)
+ if (parseFirstLine(client, *m, filename, sendContent, closeConnection) == false)
continue;
std::string host = LookupTag(*m, "Host", "");
@@ -419,6 +426,52 @@ int main(int const argc, const char * argv[])
continue;
}
}
+ condition = LookupTag(*m, "If-Range", "");
+ bool ignoreRange = false;
+ if (condition.empty() == false) {
+ time_t cache;
+ if (RFC1123StrToTime(condition.c_str(), cache) == false ||
+ cache < data.ModificationTime())
+ ignoreRange = true;
+ }
+ condition = LookupTag(*m, "Range", "");
+ if (ignoreRange == false && condition.empty() == false &&
+ strncmp(condition.c_str(), "bytes=", 6) == 0) {
+ size_t end = condition.find(',');
+ // FIXME: support multiple byte-ranges
+ if (end == std::string::npos) {
+ size_t start = 6;
+ unsigned long long filestart = strtoull(condition.c_str() + start, NULL, 10);
+ // FIXME: no fileend support
+ size_t dash = condition.find('-') + 1;
+ unsigned long long fileend = strtoull(condition.c_str() + dash, NULL, 10);
+ unsigned long long filesize = data.FileSize();
+ if (fileend == 0 || fileend == filesize) {
+ if (filesize > filestart) {
+ data.Skip(filestart);
+ std::ostringstream contentlength;
+ contentlength << "Content-Length: " << (filesize - filestart);
+ headers.push_back(contentlength.str());
+ std::ostringstream contentrange;
+ contentrange << "Content-Range: bytes " << filestart << "-"
+ << filesize - 1 << "/" << filesize;
+ headers.push_back(contentrange.str());
+ sendHead(client, 206, headers);
+ if (sendContent == true)
+ sendFile(client, data);
+ continue;
+ } else {
+ headers.push_back("Content-Length: 0");
+ std::ostringstream contentrange;
+ contentrange << "Content-Range: bytes 0-0/" << filesize;
+ headers.push_back(contentrange.str());
+ sendHead(client, 416, headers);
+ continue;
+ }
+ }
+ }
+ }
+
addFileHeaders(headers, data);
sendHead(client, 200, headers);
if (sendContent == true)
@@ -448,6 +501,8 @@ int main(int const argc, const char * argv[])
}
_error->DumpErrors(std::cerr);
messages.clear();
+ if (closeConnection == true)
+ break;
}
std::clog << "CLOSE client " << client