diff options
author | Jon Bergli Heier <snakebite@jvnv.net> | 2010-12-28 00:43:12 +0100 |
---|---|---|
committer | Jon Bergli Heier <snakebite@jvnv.net> | 2010-12-28 00:43:12 +0100 |
commit | 1d05994fe1d9488193f01b47e92dcf11920c8f02 (patch) | |
tree | f4040712f6914b78004895ae6192cf2162ea0804 | |
parent | 1a8f351248c38445189a397035e8a2cb3182ea6a (diff) |
Misc changes in HTTP code.
-rw-r--r-- | http.cpp | 29 | ||||
-rw-r--r-- | http.h | 13 | ||||
-rw-r--r-- | httpd.cpp | 14 | ||||
-rw-r--r-- | music.cpp | 23 | ||||
-rw-r--r-- | music.h | 8 |
5 files changed, 61 insertions, 26 deletions
@@ -7,7 +7,7 @@ #include <vector> HTTPRequest::HTTPRequest(std::istream& is) { - std::string line, firstline; + std::string firstline; std::getline(is, firstline); std::vector<std::string> splitvec; @@ -29,18 +29,35 @@ HTTPRequest::HTTPRequest(std::istream& is) { } } -HTTPResponse::HTTPResponse() { +HTTPResponse::HTTPResponse(boost::asio::ip::tcp::socket& socket_) : socket(socket_){ httpver = "1.1"; + headers_written = false; } void HTTPResponse::add_header(std::string key, std::string value) { headers[key] = value; } -void HTTPResponse::write_headers(std::ostream& os) { - os << boost::format("HTTP/%s %d %s\r\n") % httpver % code % status; +void HTTPResponse::write_headers() { + write(boost::str(boost::format("HTTP/%s %d %s\r\n") % httpver % code % status)); for(HTTPHeaders::iterator it = headers.begin(); it != headers.end(); it++) { - os << boost::format("%s: %s\r\n") % it->first % it->second; + write(boost::str(boost::format("%s: %s\r\n") % it->first % it->second)); } - os << "\r\n"; + write("\r\n"); +} + +void HTTPResponse::write(char *data, unsigned int len) { + write(std::string(data, len)); +} + +void HTTPResponse::write(std::string str) { + if(!headers_written) { + // make sure to set headers_written before calling write_headers + headers_written = true; + write_headers(); + } + boost::asio::streambuf b; + std::ostream os(&b); + os << str; + boost::asio::write(socket, b); } @@ -1,6 +1,8 @@ #ifndef HTTP_H #define HTTP_H +#include <boost/asio.hpp> + #include <iostream> #include <string> #include <map> @@ -15,13 +17,18 @@ class HTTPRequest { }; class HTTPResponse { - public: + private: HTTPHeaders headers; + boost::asio::ip::tcp::socket& socket; + void write_headers(); + bool headers_written; + public: int code; std::string httpver, status; - HTTPResponse(); + HTTPResponse(boost::asio::ip::tcp::socket& socket_); void add_header(std::string key, std::string value); - void write_headers(std::ostream& os); + void write(char *data, unsigned int len); + void write(std::string str); }; #endif @@ -18,29 +18,23 @@ void HTTPConnection::handle_write(const boost::system::error_code& error, size_t void HTTPConnection::handle_read(const boost::system::error_code& error, size_t bytes_transferred) { std::istream is(&buf); - HTTPRequest req(is); - boost::asio::streambuf b; - std::ostream os(&b); + boost::asio::streambuf hdr_buf, data_buf; + std::ostream hdr_os(&hdr_buf), data_os(&data_buf); - HTTPResponse res; + HTTPResponse res(socket); MusicListing *ml = music::find(req.path); if(ml) { res.code = 200; res.status = "OK"; - res.add_header("content-type", "text/html"); - res.write_headers(os); - ml->render(os); + ml->render(res); } else { res.code = 404; res.status = "Not Found"; - res.write_headers(os); } - - boost::asio::write(socket, b); } HTTPConnection::pointer HTTPConnection::create(boost::asio::io_service& io_service) { @@ -2,6 +2,7 @@ #include <boost/format.hpp> #include <boost/algorithm/string/predicate.hpp> +#include <boost/filesystem/fstream.hpp> namespace music { @@ -40,14 +41,16 @@ MusicListing *find(std::string path) { }; // namespace music -void MusicDirectory::render(std::ostream& os) { +void MusicDirectory::render(HTTPResponse& res) { + res.add_header("content-type", "text/html"); + for(MusicDirectories::iterator it = directories.begin(); it != directories.end(); it++) { std::string rel_path = it->path.string().substr(music::root_directory->path.string().size()); - os << boost::format("<a href=\"%s\">%s</a><br />") % rel_path % rel_path; + res.write(boost::str(boost::format("<a href=\"%s\">%s</a><br />") % rel_path % rel_path)); } for(MusicTracks::iterator it = tracks.begin(); it != tracks.end(); it++) { std::string rel_path = it->path.string().substr(music::root_directory->path.string().size()); - os << boost::format("<a href=\"%s\">%s</a><br />") % rel_path % rel_path; + res.write(boost::str(boost::format("<a href=\"%s\">%s</a><br />") % rel_path % rel_path)); } } @@ -72,5 +75,17 @@ MusicDirectory::MusicDirectory(const fs::path root) { } } -void MusicTrack::render(std::ostream& os) { +void MusicTrack::render(HTTPResponse& res) { + res.add_header("content-type", "application/octet-stream"); + + fs::ifstream is(path, std::ios::binary | std::ios::in); + is.seekg(0, std::ios::end); + res.add_header("content-length", boost::str(boost::format("%d") % is.tellg())); + is.seekg(0, std::ios::beg); + + char data[0x1000]; + while(is.good()) { + is.read(data, 0x1000); + res.write(data, is.gcount()); + } } @@ -1,6 +1,8 @@ #ifndef MUSIC_H #define MUSIC_H +#include "http.h" + #include <boost/filesystem.hpp> #include <vector> #include <iostream> @@ -10,13 +12,13 @@ namespace fs = boost::filesystem; class MusicListing { public: fs::path path; - virtual void render(std::ostream& os) = 0; + virtual void render(HTTPResponse& res) = 0; }; class MusicTrack : public MusicListing { public: MusicTrack(const fs::path path); - virtual void render(std::ostream& os); + virtual void render(HTTPResponse& res); }; class MusicDirectory; @@ -29,7 +31,7 @@ class MusicDirectory : public MusicListing { MusicTracks tracks; MusicDirectory(const fs::path root); - virtual void render(std::ostream& os); + virtual void render(HTTPResponse& res); }; namespace music { |