Skip to content

Commit

Permalink
webserver: handle "If-Modified-Since" header for better caching
Browse files Browse the repository at this point in the history
  • Loading branch information
Montellese committed Sep 6, 2012
1 parent e9ab7ad commit e3c5071
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 7 deletions.
47 changes: 41 additions & 6 deletions xbmc/network/WebServer.cpp
Expand Up @@ -275,6 +275,7 @@ int CWebServer::HandleRequest(IHTTPRequestHandler *handler, const HTTPRequest &r
}

struct MHD_Response *response = NULL;
int responseCode = handler->GetHTTPResonseCode();
switch (handler->GetHTTPResponseType())
{
case HTTPNone:
Expand All @@ -286,7 +287,7 @@ int CWebServer::HandleRequest(IHTTPRequestHandler *handler, const HTTPRequest &r
break;

case HTTPFileDownload:
ret = CreateFileDownloadResponse(request.connection, handler->GetHTTPResponseFile(), request.method, response);
ret = CreateFileDownloadResponse(request.connection, handler->GetHTTPResponseFile(), request.method, response, responseCode);
break;

case HTTPMemoryDownloadNoFreeNoCopy:
Expand Down Expand Up @@ -324,7 +325,7 @@ int CWebServer::HandleRequest(IHTTPRequestHandler *handler, const HTTPRequest &r
for (multimap<string, string>::const_iterator it = header.begin(); it != header.end(); it++)
MHD_add_response_header(response, it->first.c_str(), it->second.c_str());

MHD_queue_response(request.connection, handler->GetHTTPResonseCode(), response);
MHD_queue_response(request.connection, responseCode, response);
MHD_destroy_response(response);
delete handler;

Expand Down Expand Up @@ -354,15 +355,43 @@ int CWebServer::CreateRedirect(struct MHD_Connection *connection, const string &
return MHD_NO;
}

int CWebServer::CreateFileDownloadResponse(struct MHD_Connection *connection, const string &strURL, HTTPMethod methodType, struct MHD_Response *&response)
int CWebServer::CreateFileDownloadResponse(struct MHD_Connection *connection, const string &strURL, HTTPMethod methodType, struct MHD_Response *&response, int &responseCode)
{
CFile *file = new CFile();

if (file->Open(strURL, READ_NO_CACHE))
{
bool getData = true;
if (methodType != HEAD)
{
response = MHD_create_response_from_callback ( file->GetLength(),
if (methodType == GET)
{
string ifModifiedSince = GetRequestHeaderValue(connection, MHD_HEADER_KIND, "If-Modified-Since");
if (!ifModifiedSince.empty())
{
CDateTime ifModifiedSinceDate;
ifModifiedSinceDate.SetFromRFC1123DateTime(ifModifiedSince);

struct __stat64 statBuffer;
if (file->Stat(&statBuffer) == 0)
{
struct tm *time = localtime((time_t *)&statBuffer.st_mtime);
if (time != NULL)
{
CDateTime lastModified = *time;
if (lastModified.GetAsUTCDateTime() <= ifModifiedSinceDate)
{
getData = false;
response = MHD_create_response_from_data (0, NULL, MHD_NO, MHD_NO);
responseCode = MHD_HTTP_NOT_MODIFIED;
}
}
}
}
}

if (getData)
response = MHD_create_response_from_callback(file->GetLength(),
2048,
&CWebServer::ContentReaderCallback, file,
&CWebServer::ContentReaderFreeCallback);
Expand All @@ -371,6 +400,8 @@ int CWebServer::CreateFileDownloadResponse(struct MHD_Connection *connection, co
}
else
{
getData = false;

CStdString contentLength;
contentLength.Format("%I64d", file->GetLength());

Expand Down Expand Up @@ -408,8 +439,12 @@ int CWebServer::CreateFileDownloadResponse(struct MHD_Connection *connection, co
expiryTime += CDateTimeSpan(365, 0, 0, 0);
MHD_add_response_header(response, "Expires", expiryTime.GetAsRFC1123DateTime());

file->Close();
delete file;
// only close the CFile instance if libmicrohttpd doesn't have to grab the data of the file
if (!getData)
{
file->Close();
delete file;
}
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion xbmc/network/WebServer.h
Expand Up @@ -92,7 +92,7 @@ class CWebServer : public JSONRPC::ITransportLayer
static int HandleRequest(IHTTPRequestHandler *handler, const HTTPRequest &request);
static void ContentReaderFreeCallback (void *cls);
static int CreateRedirect(struct MHD_Connection *connection, const std::string &strURL, struct MHD_Response *&response);
static int CreateFileDownloadResponse(struct MHD_Connection *connection, const std::string &strURL, HTTPMethod methodType, struct MHD_Response *&response);
static int CreateFileDownloadResponse(struct MHD_Connection *connection, const std::string &strURL, HTTPMethod methodType, struct MHD_Response *&response, int &responseCode);
static int CreateErrorResponse(struct MHD_Connection *connection, int responseType, HTTPMethod method, struct MHD_Response *&response);
static int CreateMemoryDownloadResponse(struct MHD_Connection *connection, void *data, size_t size, bool free, bool copy, struct MHD_Response *&response);

Expand Down

0 comments on commit e3c5071

Please sign in to comment.