| 39 | |
| 40 | |
| 41 | void StaticFileController::service(HttpRequest &request, HttpResponse &response) |
| 42 | { |
| 43 | QByteArray path=request.getPath(); |
| 44 | // Check if we have the file in cache |
| 45 | qint64 now=QDateTime::currentMSecsSinceEpoch(); |
| 46 | mutex.lock(); |
| 47 | CacheEntry* entry=cache.object(path); |
| 48 | if (entry && (cacheTimeout==0 || entry->created>now-cacheTimeout)) |
| 49 | { |
| 50 | QByteArray document=entry->document; //copy the cached document, because other threads may destroy the cached entry immediately after mutex unlock. |
| 51 | QByteArray filename=entry->filename; |
| 52 | mutex.unlock(); |
| 53 | Logger::logger()->log(Logger::LANServer, "StaticFileController: Cache hit for %s",path.data()); |
| 54 | setContentType(filename,response); |
| 55 | response.setHeader("Cache-Control","max-age="+QByteArray::number(maxAge/1000)); |
| 56 | response.write(document,true); |
| 57 | } |
| 58 | else |
| 59 | { |
| 60 | mutex.unlock(); |
| 61 | // The file is not in cache. |
| 62 | Logger::logger()->log(Logger::LANServer, "StaticFileController: Cache miss for %s",path.data()); |
| 63 | // Forbid access to files outside the docroot directory |
| 64 | if (path.contains("/..")) |
| 65 | { |
| 66 | Logger::logger()->log(Logger::LANServer, "StaticFileController: detected forbidden characters in path %s",path.data()); |
| 67 | response.setStatus(403,"forbidden"); |
| 68 | response.write("403 forbidden",true); |
| 69 | return; |
| 70 | } |
| 71 | // If the filename is a directory, append index.html. |
| 72 | if (QFileInfo(docroot+path).isDir()) |
| 73 | { |
| 74 | path+="/index.html"; |
| 75 | } |
| 76 | // Try to open the file |
| 77 | QFile file(docroot+path); |
| 78 | Logger::logger()->log(Logger::LANServer, "StaticFileController: Open file %s",qPrintable(file.fileName())); |
| 79 | if (file.open(QIODevice::ReadOnly)) |
| 80 | { |
| 81 | setContentType(path,response); |
| 82 | response.setHeader("Cache-Control","max-age="+QByteArray::number(maxAge/1000)); |
| 83 | response.setHeader("Content-Length",QByteArray::number(file.size())); |
| 84 | if (file.size()<=maxCachedFileSize) |
| 85 | { |
| 86 | // Return the file content and store it also in the cache |
| 87 | entry=new CacheEntry(); |
| 88 | while (!file.atEnd() && !file.error()) |
| 89 | { |
| 90 | QByteArray buffer=file.read(65536); |
| 91 | response.write(buffer); |
| 92 | entry->document.append(buffer); |
| 93 | } |
| 94 | entry->created=now; |
| 95 | entry->filename=path; |
| 96 | mutex.lock(); |
| 97 | cache.insert(request.getPath(),entry,entry->document.size()); |
| 98 | mutex.unlock(); |
nothing calls this directly
no test coverage detected