#include "request.h" constexpr static const char* GET("GET"); constexpr static const char* REQUEST_METHOD("REQUEST_METHOD"); constexpr static const char* SCRIPT_FILENAME("SCRIPT_FILENAME"); constexpr static const char* SERVER_NAME("SERVER_NAME"); // constexpr static const char* REQUEST_URI("REQUEST_URI"); // // constexpr static const char* DOCUMENT_URI("DOCUMENT_URI"); // constexpr static const char* DOCUMENT_ROOT("DOCUMENT_ROOT"); // // constexpr static const char* SCRIPT_NAME("SCRIPT_NAME"); Request::Request (): state(State::initial), raw() {} Request::~Request() { terminate(); } void Request::terminate() { switch (state) { case State::accepted: case State::responded: FCGX_Finish_r(&raw); break; default: break; } } bool Request::isGet() const { if (state != State::accepted) throw std::runtime_error("An attempt to read request type on a wrong request state"); std::string_view method(FCGX_GetParam(REQUEST_METHOD, raw.envp)); return method == GET; } bool Request::wait(int socketDescriptor) { if (state != State::initial) throw std::runtime_error("An attempt to wait for new incomming request on a wrong request state"); FCGX_Request* request = &raw; FCGX_InitRequest(request, socketDescriptor, 0); int rc = FCGX_Accept_r(request); bool result = rc == 0; if (result) state = State::accepted; return result; } OStream Request::getOutputStream() { if (state != State::accepted) throw std::runtime_error("An attempt to request output stream on a wrong request state"); return OStream(raw.out); } OStream Request::getErrorStream() { if (state != State::accepted) throw std::runtime_error("An attempt to request error stream on a wrong request state"); return OStream(raw.err); } std::string Request::getPath(const std::string& serverName) const { if (state != State::accepted) throw std::runtime_error("An attempt to request path on a wrong request state"); std::string path; std::string_view scriptFileName(FCGX_GetParam(SCRIPT_FILENAME, raw.envp)); std::string::size_type snLocation = scriptFileName.find(serverName); if (snLocation != std::string::npos) { if (snLocation + serverName.size() < scriptFileName.size()) path = scriptFileName.substr(snLocation + serverName.size() + 1); } if (!path.empty()) { while (path.back() == '/') path.erase(path.end() - 1); } return path; } std::string Request::getServerName() const { if (state != State::accepted) throw std::runtime_error("An attempt to request server name on a wrong request state"); return FCGX_GetParam(SERVER_NAME, raw.envp);; } void Request::printEnvironment(std::ostream& out) { char **envp = raw.envp; for (int i = 0; envp[i] != nullptr; ++i) { out << envp[i] << "\n"; } } void Request::printEnvironment(nlohmann::json& out) { if (!out.is_object()) return; char **envp = raw.envp; for (int i = 0; envp[i] != nullptr; ++i) { std::string_view value(envp[i]); std::string::size_type pos = value.find('='); if (pos != std::string::npos) out[std::string(value.substr(0, pos))] = std::string(value.substr(pos + 1, value.size())); } }