Added Context struct.

This commit is contained in:
yhirose 2012-09-24 07:57:09 -04:00
parent 3464386f17
commit 277d7c0854
2 changed files with 66 additions and 33 deletions

View file

@ -14,17 +14,17 @@ int main(void)
Server svr; Server svr;
svr.post("/", [](const Request& /*req*/, Response& res) { svr.get("/", [](Context& cxt) {
res.body_ = "<html><head></head><body><ul></ul></body></html>"; cxt.response.body = "<html><head></head><body><ul></ul></body></html>";
}); });
svr.post("/item", [](const Request& req, Response& res) { svr.post("/item", [](Context& cxt) {
res.body_ = req.pattern_; cxt.response.body = cxt.request.pattern;
}); });
svr.get("/item/:name", [](const Request& req, Response& res) { svr.get("/item/:name", [](Context& cxt) {
try { try {
res.body_ = req.params_.at("name"); cxt.response.body = cxt.request.params.at("name");
} catch (...) { } catch (...) {
// Error... // Error...
} }

View file

@ -37,27 +37,32 @@ typedef int socket_t;
namespace httpsvrkit namespace httpsvrkit
{ {
// HTTP request typedef std::map<std::string, std::string> Map;
class Request { typedef std::multimap<std::string, std::string> MultiMap;
public:
std::map<std::string, std::string> headers_;
std::string body_;
std::string pattern_; // HTTP request
std::map<std::string, std::string> params_; struct Request {
Map headers;
std::string body;
std::string pattern;
Map params;
}; };
// HTTP response // HTTP response
class Response { struct Response {
public: MultiMap headers;
std::multimap<std::string, std::string> headers_; std::string body;
std::string body_; };
struct Context {
const Request request;
Response response;
}; };
// HTTP server // HTTP server
class Server { class Server {
public: public:
typedef std::function<void (const Request&, Response& res)> Handler; typedef std::function<void (Context& context)> Handler;
Server(); Server();
~Server(); ~Server();
@ -71,8 +76,6 @@ public:
private: private:
void process_request(int fd); void process_request(int fd);
const size_t BUFSIZ_REQUESTLINE = 2048;
socket_t sock_; socket_t sock_;
std::multimap<std::string, Handler> handlers_; std::multimap<std::string, Handler> handlers_;
}; };
@ -200,18 +203,41 @@ inline void Server::stop()
sock_ = -1; 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; std::cmatch m;
if (std::regex_match(s, m, re)) { if (std::regex_match(buf, m, re)) {
cmd = std::string(m[1]); method = std::string(m[1]);
url = std::string(m[2]); url = std::string(m[2]);
return true; return true;
} }
return false; 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) inline void write_plain_text(int fd, const char* s)
{ {
fdopen_b(fd, "w", [=](FILE* fp) { 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) inline void Server::process_request(int fd)
{ {
fdopen_b(fd, "r", [=](FILE* fp) { fdopen_b(fd, "r", [=](FILE* fp) {
// Parse request line // Read and parse request line
char request_line[BUFSIZ_REQUESTLINE]; std::string method, url;
fgets(request_line, BUFSIZ_REQUESTLINE, fp); if (!read_request_line(fp, method, url)) {
std::string cmd, url;
if (!parse_request_line(request_line, cmd, url)) {
write_error(fd, 400); write_error(fd, 400);
return; return;
} }
// Read headers
Map headers;
read_headers(fp, headers);
// Write content // Write content
char content[BUFSIZ]; char buf[BUFSIZ];
sprintf(content, "cmd: %s, url: %s\n", cmd.c_str(), url.c_str()); std::string content;
write_plain_text(fd, 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());
}); });
} }