summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Bergli Heier <snakebite@jvnv.net>2010-12-27 20:48:35 +0100
committerJon Bergli Heier <snakebite@jvnv.net>2010-12-27 20:48:35 +0100
commit1a8f351248c38445189a397035e8a2cb3182ea6a (patch)
tree507c96dc5fc1e158f799cdeb13cfab382a7a0534
parent263097e22bdf0a56007644e4d19605371dc79a8f (diff)
Added HTTPRequest and HTTPResponse classes.
-rw-r--r--SConstruct1
-rw-r--r--http.cpp46
-rw-r--r--http.h27
-rw-r--r--httpd.cpp36
-rw-r--r--music.cpp9
-rw-r--r--music.h4
6 files changed, 95 insertions, 28 deletions
diff --git a/SConstruct b/SConstruct
index 23aacb8..07e2a04 100644
--- a/SConstruct
+++ b/SConstruct
@@ -5,6 +5,7 @@ env = Environment(CPPPATH = ['.'], CCFLAGS = ['-pthread'], LINKFLAGS = ['-pthrea
conf = Configure(env)
conf.CheckLib('boost_system')
conf.CheckLib('boost_filesystem')
+conf.CheckLib('boost_regex')
env = conf.Finish()
if GetOption('release'):
diff --git a/http.cpp b/http.cpp
new file mode 100644
index 0000000..8d69f93
--- /dev/null
+++ b/http.cpp
@@ -0,0 +1,46 @@
+#include "http.h"
+
+#include <boost/format.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/algorithm/string/regex.hpp>
+
+#include <vector>
+
+HTTPRequest::HTTPRequest(std::istream& is) {
+ std::string line, firstline;
+ std::getline(is, firstline);
+
+ std::vector<std::string> splitvec;
+ boost::algorithm::split(splitvec, firstline, boost::algorithm::is_space());
+
+ type = splitvec[0];
+ path = splitvec[1];
+ httpver = splitvec[2];
+ std::cout << boost::format("%s %s %s\n") % type % path % httpver;
+
+ while(is.good()) {
+ std::string line;
+ std::getline(is, line);
+ boost::trim(line);
+ if(!line.size()) continue;
+ std::vector<std::string> v;
+ boost::algorithm::split_regex(v, line, boost::regex(": "));
+ headers[v[0]] = v[1];
+ }
+}
+
+HTTPResponse::HTTPResponse() {
+ httpver = "1.1";
+}
+
+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;
+ for(HTTPHeaders::iterator it = headers.begin(); it != headers.end(); it++) {
+ os << boost::format("%s: %s\r\n") % it->first % it->second;
+ }
+ os << "\r\n";
+}
diff --git a/http.h b/http.h
new file mode 100644
index 0000000..f7aec59
--- /dev/null
+++ b/http.h
@@ -0,0 +1,27 @@
+#ifndef HTTP_H
+#define HTTP_H
+
+#include <iostream>
+#include <string>
+#include <map>
+
+typedef std::map<std::string, std::string> HTTPHeaders;
+
+class HTTPRequest {
+ public:
+ std::string type, path, httpver;
+ HTTPHeaders headers;
+ HTTPRequest(std::istream& is);
+};
+
+class HTTPResponse {
+ public:
+ HTTPHeaders headers;
+ int code;
+ std::string httpver, status;
+ HTTPResponse();
+ void add_header(std::string key, std::string value);
+ void write_headers(std::ostream& os);
+};
+
+#endif
diff --git a/httpd.cpp b/httpd.cpp
index 3d25a0e..8eac976 100644
--- a/httpd.cpp
+++ b/httpd.cpp
@@ -1,5 +1,6 @@
#include "httpd.h"
#include "music.h"
+#include "http.h"
#include <boost/bind.hpp>
#include <boost/algorithm/string/split.hpp>
@@ -17,42 +18,29 @@ 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);
- std::string line, firstline;
- std::getline(is, firstline);
- std::string type, path, httpver;
- std::vector<std::string> splitvec;
- boost::algorithm::split(splitvec, firstline, boost::algorithm::is_space());
-
- type = splitvec[0];
- path = splitvec[1];
- httpver = splitvec[2];
- std::cout << boost::format("%s %s %s\n") % type % path % httpver;
-
- if(boost::algorithm::ends_with(path, "/"))
- path = path.substr(0, path.size()-1);
+ HTTPRequest req(is);
boost::asio::streambuf b;
std::ostream os(&b);
- MusicListing *ml = music::find(path);
+ HTTPResponse res;
+
+ MusicListing *ml = music::find(req.path);
if(ml) {
- os << "HTTP/1.1 200 OK\r\n";
- os << "content-type: text/html\r\n";
- os << "\r\n";
+ res.code = 200;
+ res.status = "OK";
+ res.add_header("content-type", "text/html");
+ res.write_headers(os);
ml->render(os);
} else {
- os << "HTTP/1.1 404 Not Found\r\n";
- os << "\r\n";
+ res.code = 404;
+ res.status = "Not Found";
+ res.write_headers(os);
}
boost::asio::write(socket, b);
-
- while(is.good()) {
- std::getline(is, line);
- std::cout << line << std::endl;
- }
}
HTTPConnection::pointer HTTPConnection::create(boost::asio::io_service& io_service) {
diff --git a/music.cpp b/music.cpp
index 3f44bf5..5ff9ec9 100644
--- a/music.cpp
+++ b/music.cpp
@@ -1,6 +1,7 @@
#include "music.h"
#include <boost/format.hpp>
+#include <boost/algorithm/string/predicate.hpp>
namespace music {
@@ -10,7 +11,11 @@ void init(const fs::path root) {
root_directory = new MusicDirectory(root);
}
-MusicListing *find(const std::string path, MusicDirectory& root) {
+MusicListing *find(std::string path, MusicDirectory& root) {
+ // remove trailing slash
+ if(boost::algorithm::ends_with(path, "/"))
+ path = path.substr(0, path.size()-1);
+
fs::path full_path = root_directory->path / path;
if(root.path == full_path)
return &root;
@@ -29,7 +34,7 @@ MusicListing *find(const std::string path, MusicDirectory& root) {
return NULL;
}
-MusicListing *find(const std::string path) {
+MusicListing *find(std::string path) {
return find(path, *root_directory);
}
diff --git a/music.h b/music.h
index 4e790d8..0e51003 100644
--- a/music.h
+++ b/music.h
@@ -35,8 +35,8 @@ class MusicDirectory : public MusicListing {
namespace music {
extern MusicDirectory *root_directory;
void init(const fs::path root);
- MusicListing *find(const std::string path, MusicDirectory& root);
- MusicListing *find(const std::string path);
+ MusicListing *find(std::string path, MusicDirectory& root);
+ MusicListing *find(std::string path);
};
#endif