diff --git a/CMakeLists.txt b/CMakeLists.txt index 89b2427..c94399b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,8 @@ target_link_libraries(http_examples ${CMAKE_THREAD_LIBS_INIT}) find_package(OpenSSL) if(OPENSSL_FOUND) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_OPENSSL") + target_link_libraries(http_examples ${OPENSSL_LIBRARIES}) include_directories(SYSTEM ${OPENSSL_INCLUDE_DIR}) add_executable(https_examples https_examples.cpp) diff --git a/http_examples.cpp b/http_examples.cpp index ba3c608..ffac0ad 100644 --- a/http_examples.cpp +++ b/http_examples.cpp @@ -1,5 +1,8 @@ #include "server_http.hpp" #include "client_http.hpp" +#ifdef HAVE_OPENSSL +#include "crypto.hpp" +#endif //Added for the json-example #define BOOST_SPIRIT_THREADSAFE @@ -19,6 +22,10 @@ using namespace boost::property_tree; typedef SimpleWeb::Server HttpServer; typedef SimpleWeb::Client HttpClient; +#ifdef HAVE_OPENSSL +std::string build_hash(const std::string full_file_name); +#endif + //Added for the default_resource example void default_resource_send(const HttpServer &server, const shared_ptr &response, const shared_ptr &ifs); @@ -108,6 +115,7 @@ int main() { try { auto web_root_path=boost::filesystem::canonical("web"); auto path=boost::filesystem::canonical(web_root_path/request->path); + std::string cache_ctrl = ""; //Check if path is within web_root_path if(distance(web_root_path.begin(), web_root_path.end())>distance(path.begin(), path.end()) || !equal(web_root_path.begin(), web_root_path.end(), path.begin())) @@ -117,6 +125,19 @@ int main() { if(!(boost::filesystem::exists(path) && boost::filesystem::is_regular_file(path))) throw invalid_argument("file does not exist"); +#ifdef HAVE_OPENSSL + //Support for HTTP Cache + std::string hash = build_hash(path.string()); + auto it=request->header.find("If-None-Match"); + if(it!=request->header.end()) { + if (it->second == "\""+hash+"\"") { + *response << "HTTP/1.1 304 Not Modified\r\nCache-Control: max-age=86400\r\nETag: \""+hash+"\"\r\n\r\n"; + return; + } + } + cache_ctrl = "Cache-Control: max-age=86400\r\nETag: \""+hash+"\"\r\n"; +#endif + auto ifs=make_shared(); ifs->open(path.string(), ifstream::in | ios::binary); @@ -126,7 +147,7 @@ int main() { ifs->seekg(0, ios::beg); - *response << "HTTP/1.1 200 OK\r\nContent-Length: " << length << "\r\n\r\n"; + *response << "HTTP/1.1 200 OK\r\n" << cache_ctrl << "Content-Length: " << length << "\r\n\r\n"; default_resource_send(server, response, ifs); } else @@ -180,3 +201,17 @@ void default_resource_send(const HttpServer &server, const shared_ptr buffer(size); + if (!file.read(buffer.data(), size)) + return ret; + ret = reinterpret_cast (&buffer[0]); + return SimpleWeb::Crypto::md5(ret,1); +} +#endif diff --git a/https_examples.cpp b/https_examples.cpp index 259e766..4227776 100644 --- a/https_examples.cpp +++ b/https_examples.cpp @@ -1,5 +1,8 @@ #include "server_https.hpp" #include "client_https.hpp" +#ifdef HAVE_OPENSSL +#include "crypto.hpp" +#endif //Added for the json-example #define BOOST_SPIRIT_THREADSAFE @@ -22,7 +25,9 @@ typedef SimpleWeb::Client HttpsClient; //Added for the default_resource example void default_resource_send(const HttpsServer &server, const shared_ptr &response, const shared_ptr &ifs); - +#ifdef HAVE_OPENSSL +std::string build_hash(const std::string full_file_name); +#endif int main() { //HTTPS-server at port 8080 using 1 thread //Unless you do more heavy non-threaded processing in the resources, @@ -108,6 +113,7 @@ int main() { try { auto web_root_path=boost::filesystem::canonical("web"); auto path=boost::filesystem::canonical(web_root_path/request->path); + std::string cache_ctrl = ""; //Check if path is within web_root_path if(distance(web_root_path.begin(), web_root_path.end())>distance(path.begin(), path.end()) || !equal(web_root_path.begin(), web_root_path.end(), path.begin())) @@ -116,7 +122,20 @@ int main() { path/="index.html"; if(!(boost::filesystem::exists(path) && boost::filesystem::is_regular_file(path))) throw invalid_argument("file does not exist"); - + +#ifdef HAVE_OPENSSL + //Support for HTTP Cache + std::string hash = build_hash(path.string()); + auto it=request->header.find("If-None-Match"); + if(it!=request->header.end()) { + if (it->second == "\""+hash+"\"") { + *response << "HTTP/1.1 304 Not Modified\r\nCache-Control: max-age=86400\r\nETag: \""+hash+"\"\r\n\r\n"; + return; + } + } + cache_ctrl = "Cache-Control: max-age=86400\r\nETag: \""+hash+"\"\r\n"; +#endif + auto ifs=make_shared(); ifs->open(path.string(), ifstream::in | ios::binary); @@ -126,7 +145,7 @@ int main() { ifs->seekg(0, ios::beg); - *response << "HTTP/1.1 200 OK\r\nContent-Length: " << length << "\r\n\r\n"; + *response << "HTTP/1.1 200 OK\r\n" << cache_ctrl << "Content-Length: " << length << "\r\n\r\n"; default_resource_send(server, response, ifs); } else @@ -181,3 +200,17 @@ void default_resource_send(const HttpsServer &server, const shared_ptr buffer(size); + if (!file.read(buffer.data(), size)) + return ret; + ret = reinterpret_cast (&buffer[0]); + return SimpleWeb::Crypto::md5(ret,1); +} +#endif