X-Git-Url: https://git.llucax.com/z.facultad/75.42/plaqui.git/blobdiff_plain/cd6078479123cd2cfe62df2d838633c143649edf..f29a7129de56edca96ea8ef58576898c1e52ed6f:/Server/src/httprequest.cpp?ds=inline diff --git a/Server/src/httprequest.cpp b/Server/src/httprequest.cpp index 4c28a51..d62b785 100644 --- a/Server/src/httprequest.cpp +++ b/Server/src/httprequest.cpp @@ -31,121 +31,133 @@ # include #endif // DEBUG -PlaQui::Server::HTTPRequest::~HTTPRequest(void) { -#ifdef DEBUG - std::cerr << __FILE__ << ": destructor." << std::endl; -#endif // DEBUG -} +using namespace std; -PlaQui::Server::HTTPRequest::HTTPRequest(const std::string& version): - PlaQui::Server::HTTPMessage(version) { -#ifdef DEBUG - std::cerr << __FILE__ << ": http_version = " << http_version << std::endl; -#endif // DEBUG -} +namespace PlaQui { -PlaQui::Server::HTTPRequest::HTTPRequest(const Serializable& body, - const std::string& version): - PlaQui::Server::HTTPMessage(body, version) { +namespace Server { + +HTTPRequest::~HTTPRequest(void) { #ifdef DEBUG - std::cerr << __FILE__ << ": http_version = " << http_version - << " | body = " << body.serialize() << std::endl; + cerr << __FILE__ << ": destructor." << endl; #endif // DEBUG } -PlaQui::Server::HTTPRequest::HTTPRequest(const std::string& uri, - const PlaQui::Server::HTTPRequest::HTTPMethod& method, - std::string& query, std::string& version): - PlaQui::Server::HTTPMessage(body, version) { +HTTPRequest::HTTPRequest(const string& uri, const HTTPMethod& method, + const string& query, const string& body, const string& version): + HTTPMessage(body, version), method(method), uri(uri), query(query) { #ifdef DEBUG - std::cerr << __FILE__ << ": http_version = " << http_version - << " | body = " << body.serialize() << std::endl; + cerr << __FILE__ << ": uri = " << uri << " | " + << "method = " << method_str() << " | " + << "query = " << query << " | " + << "body.length = " << body.length() << " | " + << "version = " << version << endl; #endif // DEBUG } -void PlaQui::Server::HTTPRequest::serialize(std::ostream& os) { -#ifdef DEBUG - std::cerr << __FILE__ << ": serialize()" << std::endl; -#endif // DEBUG - os << method << " " << uri; - if (query_string.length()) { - os << "?" << query; - } - os << "HTTP/" << version << "\r\l" << std::flush; // TODO ver que este bien el \r\l - HTTPMessage::serilize(os); - if (headers.size()) { - headers.serilize(os); - } - os << "\r\l" << std::flush; - if (body.size()) { - body.serilize(os); +string HTTPRequest::method_str(void) const { + switch (method) { + case POST: + return "POST"; + case GET: + default: + return "GET"; } } -void PlaQui::Server::HTTPRequest::unserialize(std::istream& is) { - const unsigned BUFFER_SIZE = 4096; - char buf[BUFFER_SIZE]; +istream& operator>>(istream& is, HTTPRequest& req) + throw(HTTPError, ios::failure) { +#ifdef DEBUG + cerr << __FILE__ << ": operator>>()" << endl; +#endif // DEBUG + char buf[BUFSIZ]; // Obtengo primera línea (request) - is.getline(buf, BUFFER_SIZE); + if (!is.getline(buf, BUFSIZ)) { + // No hay más líneas. + throw ios::failure("socket closed"); + } #ifdef DEBUG - std::cerr << "Recibiendo linea: " << buf << std::endl; + cerr << __FILE__ << ":\tRecibiendo linea: " << buf << endl; #endif // DEBUG - String line = buf; + String line(buf); // Si es la primera línea, es el request. if (line.length() < 3) { - // FIXME - poner excepciones lindas. - throw "HTTP/1.1 501 Method Not Implemented"; + throw HTTPError(HTTPMessage::BAD_REQUEST, line + + ": No tiene un método conocido."); } // Averiguo método. - std::string::size_type pos = line.find_first_of(String::SPACE_CHARS); + string::size_type pos = line.find_first_of(String::SPACE_CHARS); String met = line.substr(0, pos); - if (met.to_upper() == "GET") { - method = GET; - } else if (met.to_upper() == "POST") { - method = POST; + met.to_upper(); + if (met == "GET") { + req.method = HTTPRequest::GET; + } else if (met == "POST") { + req.method = HTTPRequest::POST; } else { - // FIXME - poner excepciones lindas. - throw "HTTP/1.1 501 Method Not Implemented"; + throw HTTPError(HTTPMessage::NOT_IMPLEMENTED, met + + ": No es un método soportado."); } // Si tiene sólo el método, no es válido. line = line.substr(pos + 1); - iine.trim(); + line.trim(); if (!line.length()) { - // FIXME - poner excepciones lindas. - throw "HTTP/1.1 400 Bad Request"; + throw HTTPError(HTTPMessage::BAD_REQUEST, "Falta URI."); } // Si tiene más espacios, tengo la URI y el protocolo (o un error). pos = line.find_first_of(String::SPACE_CHARS); - if (pos != std::string::npos) { + if (pos != string::npos) { // Si el resto es un protocolo válido, agrego más variables. String protocol = line.substr(pos + 1); - protocol = protocol.trim(); - if (protocol.to_upper() == "HTTP/1.0") { - version = "1.0"; - } else if (protocol.to_upper() == "HTTP/1.1") { - version = "1.1"; + protocol = protocol.trim().to_upper(); + if (protocol.substr(0, 5) != "HTTP/") { + throw HTTPError(HTTPMessage::BAD_REQUEST, + protocol + ": Protocolo desconocido"); + } + if (protocol.substr(5) == "1.0") { + req.version = "1.0"; + } else if (protocol.substr(5) == "1.1") { + req.version = "1.1"; // Si no es un error. } else { - // FIXME - poner excepciones lindas. - throw "HTTP/1.1 400 Bad Request"; + throw HTTPError(HTTPMessage::HTTP_VERSION_NOT_SUPPORTED, + protocol.substr(5) + ": Versión HTTP no soportada."); } line = line.substr(0, pos); } // Agrego la URI y sus derivados. if (!line.length() || (line[0] != '/')) { // FIXME || request.find_first_not_of(";/?:@&=+$,")) { - // FIXME - poner excepciones lindas. - throw "HTTP/1.1 400 Bad Request"; + throw HTTPError(HTTPMessage::BAD_REQUEST, + line + ": La URI no comienza con /."); } // Si tiene un query string. - pos = request.find("?"); - if (pos != std::string::npos) { - query = line.substr(pos + 1); + pos = line.find("?"); + if (pos != string::npos) { + req.query = line.substr(pos + 1); } else { - query = ""; + req.query = ""; } - uri = line.substr(0, pos); - // Fin de request, obtengo cabeceras y cuerpo. - HTTPMessage::unserialize(is); + req.uri = line.substr(0, pos); + // Fin de request, obtengo el mensaje. + is >> static_cast(req); + //PlaQui::Server::operator>>(is, static_cast(req)); + return is; } +ostream& operator<<(ostream& os, const HTTPRequest& req) { +#ifdef DEBUG + cerr << __FILE__ << ": operator<<()" << endl; +#endif // DEBUG + os << req.method_str() << " " << req.uri; + if (req.query.length()) { + os << "?" << req.query; + } + os << " HTTP/" << req.version << "\r\n" + << static_cast(req); + return os; +} + +} // namespace Server + +} // namespace PlaQui +