#include "StringUtils.h" #include namespace VWeb { HttpMethod StringToHTTPMethod(std::string &method) { static std::unordered_map s_StringToMethodMap{ {"get", HttpMethod::GET}, {"head", HttpMethod::HEAD}, {"options", HttpMethod::OPTIONS}, {"post", HttpMethod::POST}, {"put", HttpMethod::PUT}, {"patch", HttpMethod::PATCH}, {"delete", HttpMethod::DELETE}, {"fallback", HttpMethod::FALLBACK}, }; String::ToLowerCase(method); if (s_StringToMethodMap.contains(method)) return s_StringToMethodMap[method]; return s_StringToMethodMap["fallback"]; } bool ParseRequest(Ref &request) { std::istringstream resp(request->Body); std::string line; std::string::size_type index; while (std::getline(resp, line) && line != "\r") { index = line.find(':', 0); if (index != std::string::npos) { auto key = line.substr(0, index); String::Trim(key); request->Header(key).Add(String::TrimCopy(line.substr(index + 1))); } else if (line.find("HTTP")) { auto headers = String::Split(line, " "); if (headers.size() != 3) return false; request->Method = StringToHTTPMethod(headers[0]); request->URI = String::UrlDecode(headers[1]); } else { return false; } } return true; } struct RequestJob : public WorkerJob { Ref MRequest{}; Ref MRouter{}; Ref MMiddleWareHandler{}; RequestHandler *MRequestHandler{nullptr}; void Execute() override { if (!ParseRequest(MRequest)) { fprintf(stderr, "[Request] >> Request failed to parse\n"); SocketUtils::Close(MRequest->ID); return; } MRequest->CookieData = CreateRef(); MRequest->SessionData = CreateRef(); MMiddleWareHandler->HandlePre(MRequest); auto response = MRouter->HandleRoute(MRequest); MMiddleWareHandler->HandlePost(MRequest, response); auto content = response->GetResponse(); MRequestHandler->AddSendResponse( {0, (ssize_t)content.size(), MRequest->ID, content}); MMiddleWareHandler->Shutdown(MRequest, response); } }; RequestHandler::RequestHandler(const Ref &manager) : m_SocketManager(manager), m_MiddleWare(CreateRef()) { m_MiddleWare = CreateRef(); } void RequestHandler::InitThreads(int count) { m_Pool.SetThreadCount(count); m_Pool.Create(); } void RequestHandler::AddRequest(Ref &request) { if (m_Router) { auto job = CreateRef(); job->MRequest = request; job->MMiddleWareHandler = m_MiddleWare; job->MRequestHandler = this; job->MRouter = m_Router; m_Pool.Dispatch(job); } } void RequestHandler::Stop() { m_Pool.Stop(); } void RequestHandler::SetRouter(Ref &router) { m_Router = router; } void RequestHandler::AddSendResponse(SendData sendData) { auto id = sendData.SocketID; m_Server->m_OutRequest.Add(id, sendData); if (!m_SocketManager->SetSendListen(id)) { SocketUtils::Close(id); m_Server->m_OutRequest.Remove(id); } } } // namespace VWeb