See More

#include #include "http_server.h" void HttpServer::Init(const std::string &port) { m_port = port; s_server_option.enable_directory_listing = "yes"; s_server_option.document_root = s_web_dir.c_str(); // ÆäËûhttpÉèÖà // ¿ªÆô CORS£¬±¾ÏîÖ»Õë¶ÔÖ÷Ò³¼ÓÔØÓÐЧ // s_server_option.extra_headers = "Access-Control-Allow-Origin: *"; } bool HttpServer::Start() { mg_mgr_init(&m_mgr, NULL); mg_connection *connection = mg_bind(&m_mgr, m_port.c_str(), HttpServer::OnHttpWebsocketEvent); if (connection == NULL) return false; // for both http and websocket mg_set_protocol_http_websocket(connection); printf("starting http server at port: %s\n", m_port.c_str()); // loop while (true) mg_mgr_poll(&m_mgr, 500); // ms return true; } void HttpServer::OnHttpWebsocketEvent(mg_connection *connection, int event_type, void *event_data) { // Çø·ÖhttpºÍwebsocket if (event_type == MG_EV_HTTP_REQUEST) { http_message *http_req = (http_message *)event_data; HandleHttpEvent(connection, http_req); } else if (event_type == MG_EV_WEBSOCKET_HANDSHAKE_DONE || event_type == MG_EV_WEBSOCKET_FRAME || event_type == MG_EV_CLOSE) { websocket_message *ws_message = (struct websocket_message *)event_data; HandleWebsocketMessage(connection, event_type, ws_message); } } // ---- simple http ---- // static bool route_check(http_message *http_msg, char *route_prefix) { if (mg_vcmp(&http_msg->uri, route_prefix) == 0) return true; else return false; // TODO: »¹¿ÉÒÔÅÐ¶Ï GET, POST, PUT, DELTEµÈ·½·¨ //mg_vcmp(&http_msg->method, "GET"); //mg_vcmp(&http_msg->method, "POST"); //mg_vcmp(&http_msg->method, "PUT"); //mg_vcmp(&http_msg->method, "DELETE"); } void HttpServer::AddHandler(const std::string &url, ReqHandler req_handler) { if (s_handler_map.find(url) != s_handler_map.end()) return; s_handler_map.insert(std::make_pair(url, req_handler)); } void HttpServer::RemoveHandler(const std::string &url) { auto it = s_handler_map.find(url); if (it != s_handler_map.end()) s_handler_map.erase(it); } void HttpServer::SendHttpRsp(mg_connection *connection, std::string rsp) { // --- 먦ÆôCORS // ±ØÐëÏÈ·¢ËÍheader, ÔÝʱ»¹²»ÄÜÓÃHTTP/2.0 mg_printf(connection, "%s", "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"); // ÒÔjsonÐÎʽ·µ»Ø mg_printf_http_chunk(connection, "{ \"result\": %s }", rsp.c_str()); // ·¢ËͿհ××Ö·û¿ì£¬½áÊøµ±Ç°ÏìÓ¦ mg_send_http_chunk(connection, "", 0); // --- ¿ªÆôCORS /*mg_printf(connection, "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain\n" "Cache-Control: no-cache\n" "Content-Length: %d\n" "Access-Control-Allow-Origin: *\n\n" "%s\n", rsp.length(), rsp.c_str()); */ } void HttpServer::HandleHttpEvent(mg_connection *connection, http_message *http_req) { std::string req_str = std::string(http_req->message.p, http_req->message.len); printf("got request: %s\n", req_str.c_str()); // ÏȹýÂËÊÇ·ñÒÑ×¢²áµÄº¯Êý»Øµ÷ std::string url = std::string(http_req->uri.p, http_req->uri.len); std::string body = std::string(http_req->body.p, http_req->body.len); auto it = s_handler_map.find(url); if (it != s_handler_map.end()) { ReqHandler handle_func = it->second; handle_func(url, body, connection, &HttpServer::SendHttpRsp); } // ÆäËûÇëÇó if (route_check(http_req, "/")) // index page mg_serve_http(connection, http_req, s_server_option); else if (route_check(http_req, "/api/hello")) { // Ö±½Ó»Ø´« SendHttpRsp(connection, "welcome to httpserver"); } else if (route_check(http_req, "/api/sum")) { // ¼òµ¥postÇëÇ󣬼ӷ¨ÔËËã²âÊÔ char n1[100], n2[100]; double result; /* Get form variables */ mg_get_http_var(&http_req->body, "n1", n1, sizeof(n1)); mg_get_http_var(&http_req->body, "n2", n2, sizeof(n2)); /* Compute the result and send it back as a JSON object */ result = strtod(n1, NULL) + strtod(n2, NULL); SendHttpRsp(connection, std::to_string(result)); } else { mg_printf( connection, "%s", "HTTP/1.1 501 Not Implemented\r\n" "Content-Length: 0\r\n\r\n"); } } // ---- websocket ---- // int HttpServer::isWebsocket(const mg_connection *connection) { return connection->flags & MG_F_IS_WEBSOCKET; } void HttpServer::HandleWebsocketMessage(mg_connection *connection, int event_type, websocket_message *ws_msg) { if (event_type == MG_EV_WEBSOCKET_HANDSHAKE_DONE) { printf("client websocket connected\n"); // »ñÈ¡Á¬½Ó¿Í»§¶ËµÄIPºÍ¶Ë¿Ú char addr[32]; mg_sock_addr_to_str(&connection->sa, addr, sizeof(addr), MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT); printf("client addr: %s\n", addr); // Ìí¼Ó session s_websocket_session_set.insert(connection); SendWebsocketMsg(connection, "client websocket connected"); } else if (event_type == MG_EV_WEBSOCKET_FRAME) { mg_str received_msg = { (char *)ws_msg->data, ws_msg->size }; char buff[1024] = {0}; strncpy(buff, received_msg.p, received_msg.len); // must use strncpy, specifiy memory pointer and length // do sth to process request printf("received msg: %s\n", buff); SendWebsocketMsg(connection, "send your msg back: " + std::string(buff)); //BroadcastWebsocketMsg("broadcast msg: " + std::string(buff)); } else if (event_type == MG_EV_CLOSE) { if (isWebsocket(connection)) { printf("client websocket closed\n"); // ÒÆ³ýsession if (s_websocket_session_set.find(connection) != s_websocket_session_set.end()) s_websocket_session_set.erase(connection); } } } void HttpServer::SendWebsocketMsg(mg_connection *connection, std::string msg) { mg_send_websocket_frame(connection, WEBSOCKET_OP_TEXT, msg.c_str(), strlen(msg.c_str())); } void HttpServer::BroadcastWebsocketMsg(std::string msg) { for (mg_connection *connection : s_websocket_session_set) mg_send_websocket_frame(connection, WEBSOCKET_OP_TEXT, msg.c_str(), strlen(msg.c_str())); } bool HttpServer::Close() { mg_mgr_free(&m_mgr); return true; }