summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Bergli Heier <snakebite@jvnv.net>2010-12-28 00:43:12 +0100
committerJon Bergli Heier <snakebite@jvnv.net>2010-12-28 00:43:12 +0100
commit1d05994fe1d9488193f01b47e92dcf11920c8f02 (patch)
treef4040712f6914b78004895ae6192cf2162ea0804
parent1a8f351248c38445189a397035e8a2cb3182ea6a (diff)
Misc changes in HTTP code.
-rw-r--r--http.cpp29
-rw-r--r--http.h13
-rw-r--r--httpd.cpp14
-rw-r--r--music.cpp23
-rw-r--r--music.h8
5 files changed, 61 insertions, 26 deletions
diff --git a/http.cpp b/http.cpp
index 8d69f93..dbe8145 100644
--- a/http.cpp
+++ b/http.cpp
@@ -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);
}
diff --git a/http.h b/http.h
index f7aec59..3ab66dc 100644
--- a/http.h
+++ b/http.h
@@ -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
diff --git a/httpd.cpp b/httpd.cpp
index 8eac976..6da58b1 100644
--- a/httpd.cpp
+++ b/httpd.cpp
@@ -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) {
diff --git a/music.cpp b/music.cpp
index 5ff9ec9..b36ba7b 100644
--- a/music.cpp
+++ b/music.cpp
@@ -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());
+ }
}
diff --git a/music.h b/music.h
index 0e51003..45c40fb 100644
--- a/music.h
+++ b/music.h
@@ -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 {