Skip to content
Browse files

webserver: handle "If-Modified-Since" header for better caching

  • Loading branch information...
1 parent e9ab7ad commit e3c5071bb023c57cc2822466b1aa652ce9d03925 @Montellese committed Sep 4, 2012
Showing with 42 additions and 7 deletions.
  1. +41 −6 xbmc/network/WebServer.cpp
  2. +1 −1 xbmc/network/WebServer.h
View
47 xbmc/network/WebServer.cpp
@@ -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:
@@ -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:
@@ -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;
@@ -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);
@@ -371,6 +400,8 @@ int CWebServer::CreateFileDownloadResponse(struct MHD_Connection *connection, co
}
else
{
+ getData = false;
+
CStdString contentLength;
contentLength.Format("%I64d", file->GetLength());
@@ -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
{
View
2 xbmc/network/WebServer.h
@@ -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);

0 comments on commit e3c5071

Please sign in to comment.
Something went wrong with that request. Please try again.