Response stream now subclass std::ostream. Also some cleanup of default_resource example.
This commit is contained in:
parent
4bc50785ac
commit
c58b7a788e
3 changed files with 88 additions and 112 deletions
|
|
@ -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";
|
||||||
|
|
||||||
|
//read and send 128 KB at a time
|
||||||
|
size_t buffer_size=131072;
|
||||||
|
vector<char> buffer;
|
||||||
|
buffer.reserve(buffer_size);
|
||||||
|
size_t read_length;
|
||||||
|
try {
|
||||||
|
while((read_length=ifs.read(&buffer[0], buffer_size).gcount())>0) {
|
||||||
|
response.write(&buffer[0], read_length);
|
||||||
|
response.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(const exception &e) {
|
||||||
|
cerr << "Connection interrupted, closing file" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
response << "HTTP/1.1 200 OK\r\nContent-Length: " << length << "\r\n\r\n";
|
ifs.close();
|
||||||
|
return;
|
||||||
//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.reserve(buffer_size);
|
|
||||||
size_t read_length;
|
|
||||||
try {
|
|
||||||
while((read_length=ifs.read(&buffer[0], buffer_size).gcount())>0) {
|
|
||||||
response.stream.write(&buffer[0], read_length);
|
|
||||||
response << HttpServer::flush;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(const exception &e) {
|
|
||||||
cerr << "Connection interrupted, closing file" << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
response << ifs.rdbuf();
|
|
||||||
|
|
||||||
ifs.close();
|
|
||||||
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;
|
||||||
|
|
|
||||||
|
|
@ -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";
|
||||||
|
|
||||||
|
//read and send 128 KB at a time
|
||||||
|
size_t buffer_size=131072;
|
||||||
|
vector<char> buffer;
|
||||||
|
buffer.reserve(buffer_size);
|
||||||
|
size_t read_length;
|
||||||
|
try {
|
||||||
|
while((read_length=ifs.read(&buffer[0], buffer_size).gcount())>0) {
|
||||||
|
response.write(&buffer[0], read_length);
|
||||||
|
response.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(const exception &e) {
|
||||||
|
cerr << "Connection interrupted, closing file" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
response << "HTTP/1.1 200 OK\r\nContent-Length: " << length << "\r\n\r\n";
|
ifs.close();
|
||||||
|
return;
|
||||||
//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.reserve(buffer_size);
|
|
||||||
size_t read_length;
|
|
||||||
try {
|
|
||||||
while((read_length=ifs.read(&buffer[0], buffer_size).gcount())>0) {
|
|
||||||
response.stream.write(&buffer[0], read_length);
|
|
||||||
response << HttpsServer::flush;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(const exception &e) {
|
|
||||||
cerr << "Connection interrupted, closing file" << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
response << ifs.rdbuf();
|
|
||||||
|
|
||||||
ifs.close();
|
|
||||||
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;
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue