Now using boost::filesystem in the default_resource examples.
This commit is contained in:
parent
2177e330b7
commit
dc944ce2fb
4 changed files with 92 additions and 96 deletions
|
|
@ -15,7 +15,7 @@ else()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#Only tested with versions 1.55 and 1.56
|
#Only tested with versions 1.55 and 1.56
|
||||||
find_package(Boost 1.54.0 COMPONENTS system thread coroutine context REQUIRED)
|
find_package(Boost 1.54.0 COMPONENTS system thread coroutine context filesystem REQUIRED)
|
||||||
message("Boost include dir: ${Boost_INCLUDE_DIR}")
|
message("Boost include dir: ${Boost_INCLUDE_DIR}")
|
||||||
message("Boost libraries: ${Boost_LIBRARIES}")
|
message("Boost libraries: ${Boost_LIBRARIES}")
|
||||||
include_directories(${Boost_INCLUDE_DIR})
|
include_directories(${Boost_INCLUDE_DIR})
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ Compile with a C++11 compiler supporting regex (for instance g++ 4.9):
|
||||||
|
|
||||||
On Linux using g++: add `-pthread`
|
On Linux using g++: add `-pthread`
|
||||||
|
|
||||||
Note: added `-lboost_thread` to make the json-example thread safe. Also added `-lboost_coroutine -lboost_context` to make synchronous and asynchronous flushing of response stream work. On some systems you might have to use postfix `-mt` to link to these libraries.
|
Note: added `-lboost_filesystem` for the default_resource example, and `-lboost_thread` to make the json-example thread safe. Also added `-lboost_coroutine -lboost_context` to make synchronous and asynchronous flushing of response stream work. On some systems you might have to use postfix `-mt` to link to these libraries.
|
||||||
|
|
||||||
You can now also compile using CMake and make:
|
You can now also compile using CMake and make:
|
||||||
|
|
||||||
|
|
@ -49,7 +49,7 @@ make
|
||||||
|
|
||||||
#### HTTP
|
#### HTTP
|
||||||
|
|
||||||
`g++ -O3 -std=c++11 http_examples.cpp -lboost_system -lboost_thread -lboost_coroutine -lboost_context -o http_examples`
|
`g++ -O3 -std=c++11 http_examples.cpp -lboost_system -lboost_thread -lboost_coroutine -lboost_context -lboost_filesystem -o http_examples`
|
||||||
|
|
||||||
Then to run the server and client examples: `./http_examples`
|
Then to run the server and client examples: `./http_examples`
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@ Also, direct your favorite browser to for instance http://localhost:8080/
|
||||||
|
|
||||||
#### HTTPS
|
#### HTTPS
|
||||||
|
|
||||||
`g++ -O3 -std=c++11 https_examples.cpp -lboost_system -lboost_thread -lboost_coroutine -lboost_context -lssl -lcrypto -o https_examples`
|
`g++ -O3 -std=c++11 https_examples.cpp -lboost_system -lboost_thread -lboost_coroutine -lboost_context -lboost_filesystem -lssl -lcrypto -o https_examples`
|
||||||
|
|
||||||
Before running the server, an RSA private key (server.key) and an SSL certificate (server.crt) must be created. Follow, for instance, the instructions given here (for a self-signed certificate): http://www.akadia.com/services/ssh_test_certificate.html
|
Before running the server, an RSA private key (server.key) and an SSL certificate (server.crt) must be created. Follow, for instance, the instructions given here (for a self-signed certificate): http://www.akadia.com/services/ssh_test_certificate.html
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@
|
||||||
#include <boost/property_tree/json_parser.hpp>
|
#include <boost/property_tree/json_parser.hpp>
|
||||||
|
|
||||||
//Added for the default_resource example
|
//Added for the default_resource example
|
||||||
#include<fstream>
|
#include <fstream>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
//Added for the json-example:
|
//Added for the json-example:
|
||||||
|
|
@ -81,53 +82,50 @@ int main() {
|
||||||
//Default file: index.html
|
//Default file: index.html
|
||||||
//Can for instance be used to retrieve an HTML 5 client that uses REST-resources on this server
|
//Can for instance be used to retrieve an HTML 5 client that uses REST-resources on this server
|
||||||
server.default_resource["GET"]=[](HttpServer::Response& response, shared_ptr<HttpServer::Request> request) {
|
server.default_resource["GET"]=[](HttpServer::Response& response, shared_ptr<HttpServer::Request> request) {
|
||||||
string filename="web";
|
boost::filesystem::path web_root_path("web");
|
||||||
|
if(!boost::filesystem::exists(web_root_path))
|
||||||
string path=request->path;
|
cerr << "Could not find web root." << endl;
|
||||||
|
|
||||||
//Replace all ".." with "." (so we can't leave the web-directory)
|
|
||||||
size_t pos;
|
|
||||||
while((pos=path.find(".."))!=string::npos) {
|
|
||||||
path.erase(pos, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
filename+=path;
|
|
||||||
ifstream ifs;
|
|
||||||
//A simple platform-independent file-or-directory check do not exist, but this works in most of the cases:
|
|
||||||
if(filename.find('.')==string::npos) {
|
|
||||||
if(filename[filename.length()-1]!='/')
|
|
||||||
filename+='/';
|
|
||||||
filename+="index.html";
|
|
||||||
}
|
|
||||||
ifs.open(filename, ifstream::in);
|
|
||||||
|
|
||||||
if(ifs) {
|
|
||||||
ifs.seekg(0, ios::end);
|
|
||||||
size_t length=ifs.tellg();
|
|
||||||
|
|
||||||
ifs.seekg(0, ios::beg);
|
|
||||||
|
|
||||||
response << "HTTP/1.1 200 OK\r\nContent-Length: " << length << "\r\n\r\n";
|
|
||||||
|
|
||||||
//read and send 128 KB at a time if file-size>buffer_size
|
|
||||||
size_t buffer_size=131072;
|
|
||||||
if(length>buffer_size) {
|
|
||||||
vector<char> buffer(buffer_size);
|
|
||||||
size_t read_length;
|
|
||||||
while((read_length=ifs.read(&buffer[0], buffer_size).gcount())>0) {
|
|
||||||
response.stream.write(&buffer[0], read_length);
|
|
||||||
response << HttpServer::flush;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
response << ifs.rdbuf();
|
|
||||||
|
|
||||||
ifs.close();
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
string content="Could not open file "+filename;
|
auto path=web_root_path;
|
||||||
response << "HTTP/1.1 400 Bad Request\r\nContent-Length: " << content.length() << "\r\n\r\n" << content;
|
path+=request->path;
|
||||||
|
if(boost::filesystem::exists(path)) {
|
||||||
|
if(boost::filesystem::canonical(web_root_path)<=boost::filesystem::canonical(path)) {
|
||||||
|
if(boost::filesystem::is_directory(path))
|
||||||
|
path+="/index.html";
|
||||||
|
if(boost::filesystem::exists(path) && boost::filesystem::is_regular_file(path)) {
|
||||||
|
ifstream ifs;
|
||||||
|
ifs.open(path.string(), ifstream::in);
|
||||||
|
|
||||||
|
if(ifs) {
|
||||||
|
ifs.seekg(0, ios::end);
|
||||||
|
size_t length=ifs.tellg();
|
||||||
|
|
||||||
|
ifs.seekg(0, ios::beg);
|
||||||
|
|
||||||
|
response << "HTTP/1.1 200 OK\r\nContent-Length: " << length << "\r\n\r\n";
|
||||||
|
|
||||||
|
//read and send 128 KB at a time if file-size>buffer_size
|
||||||
|
size_t buffer_size=131072;
|
||||||
|
if(length>buffer_size) {
|
||||||
|
vector<char> buffer(buffer_size);
|
||||||
|
size_t read_length;
|
||||||
|
while((read_length=ifs.read(&buffer[0], buffer_size).gcount())>0) {
|
||||||
|
response.stream.write(&buffer[0], read_length);
|
||||||
|
response << HttpServer::flush;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
response << ifs.rdbuf();
|
||||||
|
|
||||||
|
ifs.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
string content="Could not open path "+request->path;
|
||||||
|
response << "HTTP/1.1 400 Bad Request\r\nContent-Length: " << content.length() << "\r\n\r\n" << content;
|
||||||
};
|
};
|
||||||
|
|
||||||
thread server_thread([&server](){
|
thread server_thread([&server](){
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@
|
||||||
#include <boost/property_tree/json_parser.hpp>
|
#include <boost/property_tree/json_parser.hpp>
|
||||||
|
|
||||||
//Added for the default_resource example
|
//Added for the default_resource example
|
||||||
#include<fstream>
|
#include <fstream>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
//Added for the json-example:
|
//Added for the json-example:
|
||||||
|
|
@ -81,53 +82,50 @@ int main() {
|
||||||
//Default file: index.html
|
//Default file: index.html
|
||||||
//Can for instance be used to retrieve an HTML 5 client that uses REST-resources on this server
|
//Can for instance be used to retrieve an HTML 5 client that uses REST-resources on this server
|
||||||
server.default_resource["GET"]=[](HttpsServer::Response& response, shared_ptr<HttpsServer::Request> request) {
|
server.default_resource["GET"]=[](HttpsServer::Response& response, shared_ptr<HttpsServer::Request> request) {
|
||||||
string filename="web";
|
boost::filesystem::path web_root_path("web");
|
||||||
|
if(!boost::filesystem::exists(web_root_path))
|
||||||
string path=request->path;
|
cerr << "Could not find web root." << endl;
|
||||||
|
|
||||||
//Replace all ".." with "." (so we can't leave the web-directory)
|
|
||||||
size_t pos;
|
|
||||||
while((pos=path.find(".."))!=string::npos) {
|
|
||||||
path.erase(pos, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
filename+=path;
|
|
||||||
ifstream ifs;
|
|
||||||
//A simple platform-independent file-or-directory check do not exist, but this works in most of the cases:
|
|
||||||
if(filename.find('.')==string::npos) {
|
|
||||||
if(filename[filename.length()-1]!='/')
|
|
||||||
filename+='/';
|
|
||||||
filename+="index.html";
|
|
||||||
}
|
|
||||||
ifs.open(filename, ifstream::in);
|
|
||||||
|
|
||||||
if(ifs) {
|
|
||||||
ifs.seekg(0, ios::end);
|
|
||||||
size_t length=ifs.tellg();
|
|
||||||
|
|
||||||
ifs.seekg(0, ios::beg);
|
|
||||||
|
|
||||||
response << "HTTP/1.1 200 OK\r\nContent-Length: " << length << "\r\n\r\n";
|
|
||||||
|
|
||||||
//read and send 128 KB at a time if file-size>buffer_size
|
|
||||||
size_t buffer_size=131072;
|
|
||||||
if(length>buffer_size) {
|
|
||||||
vector<char> buffer(buffer_size);
|
|
||||||
size_t read_length;
|
|
||||||
while((read_length=ifs.read(&buffer[0], buffer_size).gcount())>0) {
|
|
||||||
response.stream.write(&buffer[0], read_length);
|
|
||||||
response << HttpsServer::flush;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
response << ifs.rdbuf();
|
|
||||||
|
|
||||||
ifs.close();
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
string content="Could not open file "+filename;
|
auto path=web_root_path;
|
||||||
response << "HTTP/1.1 400 Bad Request\r\nContent-Length: " << content.length() << "\r\n\r\n" << content;
|
path+=request->path;
|
||||||
|
if(boost::filesystem::exists(path)) {
|
||||||
|
if(boost::filesystem::canonical(web_root_path)<=boost::filesystem::canonical(path)) {
|
||||||
|
if(boost::filesystem::is_directory(path))
|
||||||
|
path+="/index.html";
|
||||||
|
if(boost::filesystem::exists(path) && boost::filesystem::is_regular_file(path)) {
|
||||||
|
ifstream ifs;
|
||||||
|
ifs.open(path.string(), ifstream::in);
|
||||||
|
|
||||||
|
if(ifs) {
|
||||||
|
ifs.seekg(0, ios::end);
|
||||||
|
size_t length=ifs.tellg();
|
||||||
|
|
||||||
|
ifs.seekg(0, ios::beg);
|
||||||
|
|
||||||
|
response << "HTTP/1.1 200 OK\r\nContent-Length: " << length << "\r\n\r\n";
|
||||||
|
|
||||||
|
//read and send 128 KB at a time if file-size>buffer_size
|
||||||
|
size_t buffer_size=131072;
|
||||||
|
if(length>buffer_size) {
|
||||||
|
vector<char> buffer(buffer_size);
|
||||||
|
size_t read_length;
|
||||||
|
while((read_length=ifs.read(&buffer[0], buffer_size).gcount())>0) {
|
||||||
|
response.stream.write(&buffer[0], read_length);
|
||||||
|
response << HttpsServer::flush;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
response << ifs.rdbuf();
|
||||||
|
|
||||||
|
ifs.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
string content="Could not open path "+request->path;
|
||||||
|
response << "HTTP/1.1 400 Bad Request\r\nContent-Length: " << content.length() << "\r\n\r\n" << content;
|
||||||
};
|
};
|
||||||
|
|
||||||
thread server_thread([&server](){
|
thread server_thread([&server](){
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue