diff --git a/example/sample.cc b/example/sample.cc
index d8c30f5..01f41d2 100644
--- a/example/sample.cc
+++ b/example/sample.cc
@@ -14,17 +14,17 @@ int main(void)
Server svr;
- svr.post("/", [](const Request& /*req*/, Response& res) {
- res.body_ = "
";
+ svr.get("/", [](Context& cxt) {
+ cxt.response.body = "";
});
- svr.post("/item", [](const Request& req, Response& res) {
- res.body_ = req.pattern_;
+ svr.post("/item", [](Context& cxt) {
+ cxt.response.body = cxt.request.pattern;
});
- svr.get("/item/:name", [](const Request& req, Response& res) {
+ svr.get("/item/:name", [](Context& cxt) {
try {
- res.body_ = req.params_.at("name");
+ cxt.response.body = cxt.request.params.at("name");
} catch (...) {
// Error...
}
diff --git a/httpsvrkit.h b/httpsvrkit.h
index b9d297c..5a9893c 100644
--- a/httpsvrkit.h
+++ b/httpsvrkit.h
@@ -37,27 +37,32 @@ typedef int socket_t;
namespace httpsvrkit
{
-// HTTP request
-class Request {
-public:
- std::map headers_;
- std::string body_;
+typedef std::map Map;
+typedef std::multimap MultiMap;
- std::string pattern_;
- std::map params_;
+// HTTP request
+struct Request {
+ Map headers;
+ std::string body;
+ std::string pattern;
+ Map params;
};
// HTTP response
-class Response {
-public:
- std::multimap headers_;
- std::string body_;
+struct Response {
+ MultiMap headers;
+ std::string body;
+};
+
+struct Context {
+ const Request request;
+ Response response;
};
// HTTP server
class Server {
public:
- typedef std::function Handler;
+ typedef std::function Handler;
Server();
~Server();
@@ -71,8 +76,6 @@ public:
private:
void process_request(int fd);
- const size_t BUFSIZ_REQUESTLINE = 2048;
-
socket_t sock_;
std::multimap handlers_;
};
@@ -200,18 +203,41 @@ inline void Server::stop()
sock_ = -1;
}
-inline bool parse_request_line(const char* s, std::string& cmd, std::string& url)
+inline bool read_request_line(FILE* fp, std::string& method, std::string& url)
{
- std::regex re("(GET|POST) (.+) HTTP/1\\.1\r\n");
+ static std::regex re("(GET|POST) (.+) HTTP/1\\.1\r\n");
+
+ const size_t BUFSIZ_REQUESTLINE = 2048;
+ char buf[BUFSIZ_REQUESTLINE];
+ fgets(buf, BUFSIZ_REQUESTLINE, fp);
+
std::cmatch m;
- if (std::regex_match(s, m, re)) {
- cmd = std::string(m[1]);
+ if (std::regex_match(buf, m, re)) {
+ method = std::string(m[1]);
url = std::string(m[2]);
return true;
}
+
return false;
}
+inline void read_headers(FILE* fp, Map& headers)
+{
+ static std::regex re("(.+?): (.+?)\r\n");
+
+ const size_t BUFSIZ_HEADER = 2048;
+ char buf[BUFSIZ_HEADER];
+
+ while (fgets(buf, BUFSIZ_HEADER, fp) && strcmp(buf, "\r\n")) {
+ std::cmatch m;
+ if (std::regex_match(buf, m, re)) {
+ auto key = std::string(m[1]);
+ auto val = std::string(m[2]);
+ headers[key] = val;
+ }
+ }
+}
+
inline void write_plain_text(int fd, const char* s)
{
fdopen_b(fd, "w", [=](FILE* fp) {
@@ -254,20 +280,27 @@ inline void write_error(int fd, int code)
inline void Server::process_request(int fd)
{
fdopen_b(fd, "r", [=](FILE* fp) {
- // Parse request line
- char request_line[BUFSIZ_REQUESTLINE];
- fgets(request_line, BUFSIZ_REQUESTLINE, fp);
-
- std::string cmd, url;
- if (!parse_request_line(request_line, cmd, url)) {
+ // Read and parse request line
+ std::string method, url;
+ if (!read_request_line(fp, method, url)) {
write_error(fd, 400);
return;
}
+ // Read headers
+ Map headers;
+ read_headers(fp, headers);
+
// Write content
- char content[BUFSIZ];
- sprintf(content, "cmd: %s, url: %s\n", cmd.c_str(), url.c_str());
- write_plain_text(fd, content);
+ char buf[BUFSIZ];
+ std::string content;
+ sprintf(buf, "Method: %s, URL: %s\n", method.c_str(), url.c_str());
+ content += buf;
+ for (const auto& x : headers) {
+ sprintf(buf, "%s: %s\n", x.first.c_str(), x.second.c_str());
+ content += buf;
+ }
+ write_plain_text(fd, content.c_str());
});
}