Response stream now subclass std::ostream. Also some cleanup of default_resource example.

This commit is contained in:
eidheim 2015-09-06 17:59:02 +02:00
commit c58b7a788e
3 changed files with 88 additions and 112 deletions

View file

@ -84,51 +84,47 @@ int main() {
server.default_resource["GET"]=[](HttpServer::Response& response, shared_ptr<HttpServer::Request> request) { server.default_resource["GET"]=[](HttpServer::Response& response, shared_ptr<HttpServer::Request> request) {
boost::filesystem::path web_root_path("web"); boost::filesystem::path web_root_path("web");
if(!boost::filesystem::exists(web_root_path)) if(!boost::filesystem::exists(web_root_path))
cerr << "Could not find web root." << endl; cerr << "Could not find web root." << endl;
else { else {
auto path=web_root_path; auto path=web_root_path;
path+=request->path; path+=request->path;
if(boost::filesystem::exists(path)) { if(boost::filesystem::exists(path)) {
if(boost::filesystem::canonical(web_root_path)<=boost::filesystem::canonical(path)) { if(boost::filesystem::canonical(web_root_path)<=boost::filesystem::canonical(path)) {
if(boost::filesystem::is_directory(path)) if(boost::filesystem::is_directory(path))
path+="/index.html"; path+="/index.html";
if(boost::filesystem::exists(path) && boost::filesystem::is_regular_file(path)) { if(boost::filesystem::exists(path) && boost::filesystem::is_regular_file(path)) {
ifstream ifs; ifstream ifs;
ifs.open(path.string(), ifstream::in | ios::binary); ifs.open(path.string(), ifstream::in | ios::binary);
if(ifs) { if(ifs) {
ifs.seekg(0, ios::end); ifs.seekg(0, ios::end);
size_t length=ifs.tellg(); size_t length=ifs.tellg();
ifs.seekg(0, ios::beg); 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\nContent-Length: " << length << "\r\n\r\n";
//read and send 128 KB at a time if file-size>buffer_size //read and send 128 KB at a time
size_t buffer_size=131072; size_t buffer_size=131072;
if(length>buffer_size) { vector<char> buffer;
vector<char> buffer; buffer.reserve(buffer_size);
buffer.reserve(buffer_size); size_t read_length;
size_t read_length; try {
try { while((read_length=ifs.read(&buffer[0], buffer_size).gcount())>0) {
while((read_length=ifs.read(&buffer[0], buffer_size).gcount())>0) { response.write(&buffer[0], read_length);
response.stream.write(&buffer[0], read_length); response.flush();
response << HttpServer::flush; }
} }
} catch(const exception &e) {
catch(const exception &e) { cerr << "Connection interrupted, closing file" << endl;
cerr << "Connection interrupted, closing file" << endl; }
}
}
else
response << ifs.rdbuf();
ifs.close(); ifs.close();
return; return;
}
}
} }
}
} }
}
} }
string content="Could not open path "+request->path; 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; response << "HTTP/1.1 400 Bad Request\r\nContent-Length: " << content.length() << "\r\n\r\n" << content;

View file

@ -84,51 +84,47 @@ int main() {
server.default_resource["GET"]=[](HttpsServer::Response& response, shared_ptr<HttpsServer::Request> request) { server.default_resource["GET"]=[](HttpsServer::Response& response, shared_ptr<HttpsServer::Request> request) {
boost::filesystem::path web_root_path("web"); boost::filesystem::path web_root_path("web");
if(!boost::filesystem::exists(web_root_path)) if(!boost::filesystem::exists(web_root_path))
cerr << "Could not find web root." << endl; cerr << "Could not find web root." << endl;
else { else {
auto path=web_root_path; auto path=web_root_path;
path+=request->path; path+=request->path;
if(boost::filesystem::exists(path)) { if(boost::filesystem::exists(path)) {
if(boost::filesystem::canonical(web_root_path)<=boost::filesystem::canonical(path)) { if(boost::filesystem::canonical(web_root_path)<=boost::filesystem::canonical(path)) {
if(boost::filesystem::is_directory(path)) if(boost::filesystem::is_directory(path))
path+="/index.html"; path+="/index.html";
if(boost::filesystem::exists(path) && boost::filesystem::is_regular_file(path)) { if(boost::filesystem::exists(path) && boost::filesystem::is_regular_file(path)) {
ifstream ifs; ifstream ifs;
ifs.open(path.string(), ifstream::in | ios::binary); ifs.open(path.string(), ifstream::in | ios::binary);
if(ifs) { if(ifs) {
ifs.seekg(0, ios::end); ifs.seekg(0, ios::end);
size_t length=ifs.tellg(); size_t length=ifs.tellg();
ifs.seekg(0, ios::beg); 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\nContent-Length: " << length << "\r\n\r\n";
//read and send 128 KB at a time if file-size>buffer_size //read and send 128 KB at a time
size_t buffer_size=131072; size_t buffer_size=131072;
if(length>buffer_size) { vector<char> buffer;
vector<char> buffer; buffer.reserve(buffer_size);
buffer.reserve(buffer_size); size_t read_length;
size_t read_length; try {
try { while((read_length=ifs.read(&buffer[0], buffer_size).gcount())>0) {
while((read_length=ifs.read(&buffer[0], buffer_size).gcount())>0) { response.write(&buffer[0], read_length);
response.stream.write(&buffer[0], read_length); response.flush();
response << HttpsServer::flush; }
} }
} catch(const exception &e) {
catch(const exception &e) { cerr << "Connection interrupted, closing file" << endl;
cerr << "Connection interrupted, closing file" << endl; }
}
}
else
response << ifs.rdbuf();
ifs.close(); ifs.close();
return; return;
}
}
} }
}
} }
}
} }
string content="Could not open path "+request->path; 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; response << "HTTP/1.1 400 Bad Request\r\nContent-Length: " << content.length() << "\r\n\r\n" << content;

View file

@ -14,7 +14,7 @@ namespace SimpleWeb {
template <class socket_type> template <class socket_type>
class ServerBase { class ServerBase {
public: public:
class Response { class Response : public std::ostream {
friend class ServerBase<socket_type>; friend class ServerBase<socket_type>;
private: private:
boost::asio::yield_context& yield; boost::asio::yield_context& yield;
@ -24,8 +24,12 @@ namespace SimpleWeb {
socket_type &socket; socket_type &socket;
Response(boost::asio::io_service& io_service, socket_type &socket, boost::asio::yield_context& yield): Response(boost::asio::io_service& io_service, socket_type &socket, boost::asio::yield_context& yield):
yield(yield), socket(socket), stream(&streambuf) {} std::ostream(&streambuf), yield(yield), socket(socket) {}
public:
size_t size() {
return streambuf.size();
}
void flush() { void flush() {
boost::system::error_code ec; boost::system::error_code ec;
boost::asio::async_write(socket, streambuf, yield[ec]); boost::asio::async_write(socket, streambuf, yield[ec]);
@ -33,28 +37,6 @@ namespace SimpleWeb {
if(ec) if(ec)
throw std::runtime_error(ec.message()); throw std::runtime_error(ec.message());
} }
public:
std::ostream stream;
size_t size() {
return streambuf.size();
}
template <class T>
Response& operator<<(const T& t) {
stream << t;
return *this;
}
Response& operator<<(std::ostream& (*manip)(std::ostream&)) {
stream << manip;
return *this;
}
Response& operator<<(Response& (*manip)(Response&)) {
return manip(*this);
}
}; };
static Response& flush(Response& r) { static Response& flush(Response& r) {
@ -307,11 +289,13 @@ namespace SimpleWeb {
return; return;
} }
try { if(response.size()>0) {
response.flush(); try {
} response.flush();
catch(const std::exception &e) { }
return; catch(const std::exception &e) {
return;
}
} }
if(timeout_content>0) if(timeout_content>0)
timer->cancel(); timer->cancel();