From 9492b942b92a98297b0b9a64223879c8e21d35af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Huss?= Date: Tue, 20 Dec 2016 22:02:52 +0100 Subject: [PATCH 1/4] Added support for HTTP caching in the https example --- https_examples.cpp | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/https_examples.cpp b/https_examples.cpp index 259e766..960a185 100644 --- a/https_examples.cpp +++ b/https_examples.cpp @@ -1,5 +1,6 @@ #include "server_https.hpp" #include "client_https.hpp" +#include "crypto.hpp" //Added for the json-example #define BOOST_SPIRIT_THREADSAFE @@ -22,7 +23,7 @@ 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); - +std::string build_hash(const std::string full_file_name); int main() { //HTTPS-server at port 8080 using 1 thread //Unless you do more heavy non-threaded processing in the resources, @@ -116,7 +117,17 @@ int main() { path/="index.html"; if(!(boost::filesystem::exists(path) && boost::filesystem::is_regular_file(path))) throw invalid_argument("file does not exist"); - + + //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; + } + } + auto ifs=make_shared(); ifs->open(path.string(), ifstream::in | ios::binary); @@ -126,7 +137,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\nCache-Control: max-age=86400\r\nETag: \""+hash+"\"\r\nContent-Length: " << length << "\r\n\r\n"; default_resource_send(server, response, ifs); } else @@ -181,3 +192,15 @@ 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); +} From d4f5fddba36527b92783e81c11e1484b3cb49636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Huss?= Date: Tue, 20 Dec 2016 22:15:58 +0100 Subject: [PATCH 2/4] Made the cache feature secured in #ifdef block and added it to the http example too --- CMakeLists.txt | 1 + http_examples.cpp | 35 +++++++++++++++++++++++++++++++++++ https_examples.cpp | 12 +++++++++++- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 89b2427..d6d047a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,7 @@ target_link_libraries(http_examples ${CMAKE_THREAD_LIBS_INIT}) find_package(OpenSSL) if(OPENSSL_FOUND) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_OPENSSL") 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..63eeb9b 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); @@ -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 960a185..4227776 100644 --- a/https_examples.cpp +++ b/https_examples.cpp @@ -1,6 +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 @@ -23,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, @@ -109,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())) @@ -118,6 +123,7 @@ 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"); @@ -127,6 +133,8 @@ int main() { 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); @@ -137,7 +145,7 @@ int main() { ifs->seekg(0, ios::beg); - *response << "HTTP/1.1 200 OK\r\nCache-Control: max-age=86400\r\nETag: \""+hash+"\"\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 @@ -193,6 +201,7 @@ void default_resource_send(const HttpsServer &server, const shared_ptr (&buffer[0]); return SimpleWeb::Crypto::md5(ret,1); } +#endif From 36c2264bdc5313daaae8f767f5c03766815ed01d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Huss?= Date: Tue, 20 Dec 2016 22:18:00 +0100 Subject: [PATCH 3/4] oups forgot to link to openssl --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index d6d047a..c94399b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,7 @@ 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) From acea17162cae11f2ce8b2b307797a1dabb7d185d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Huss?= Date: Tue, 20 Dec 2016 22:27:40 +0100 Subject: [PATCH 4/4] oups again, it should have been painless. At least I reviewed my commit --- http_examples.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http_examples.cpp b/http_examples.cpp index 63eeb9b..ffac0ad 100644 --- a/http_examples.cpp +++ b/http_examples.cpp @@ -147,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