}
HTTPRequest::HTTPRequest(const string& uri, const HTTPMethod& method,
- const string& query, const string& version):
- HTTPMessage(version), method(method), uri(uri), query(query) {
+ const string& query, const string& body, const string& version):
+ HTTPMessage(body, version), method(method), uri(uri), query(query) {
#ifdef DEBUG
cerr << __FILE__ << ": uri = " << uri << " | "
- << "method = " << ((method == GET) ? "GET" : "POST") << " | "
+ << "method = " << method_str() << " | "
<< "query = " << query << " | "
+ << "body.length = " << body.length() << " | "
<< "version = " << version << endl;
#endif // DEBUG
}
-/*
-HTTPRequest::HTTPRequest(const Serializable& body,
- const string& version):
- HTTPMessage(body, version) {
-#ifdef DEBUG
- cerr << __FILE__ << ": http_version = " << http_version
- << " | body = " << body.serialize() << endl;
-#endif // DEBUG
-}
-
-HTTPRequest::HTTPRequest(const string& uri,
- const HTTPRequest::HTTPMethod& method,
- string& query, string& version):
- HTTPMessage(body, version) {
-#ifdef DEBUG
- cerr << __FILE__ << ": http_version = " << http_version
- << " | body = " << body.serialize() << endl;
-#endif // DEBUG
+string HTTPRequest::method_str(void) const {
+ switch (method) {
+ case POST:
+ return "POST";
+ case GET:
+ default:
+ return "GET";
+ }
}
-*/
-istream& operator>>(istream& is, HTTPRequest& req) {
+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, BUFSIZ);
+ if (!is.getline(buf, BUFSIZ)) {
+ // No hay más líneas.
+ throw ios::failure("socket closed");
+ }
#ifdef DEBUG
- cerr << "Recibiendo linea: " << buf << endl;
+ cerr << __FILE__ << ":\tRecibiendo linea: " << buf << endl;
#endif // DEBUG
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.
string::size_type pos = line.find_first_of(String::SPACE_CHARS);
String met = line.substr(0, pos);
- if (met.to_upper() == "GET") {
+ met.to_upper();
+ if (met == "GET") {
req.method = HTTPRequest::GET;
- } else if (met.to_upper() == "POST") {
+ } 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);
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 != 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") {
+ 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.to_upper() == "HTTP/1.1") {
+ } 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 = line.find("?");
#ifdef DEBUG
cerr << __FILE__ << ": operator<<()" << endl;
#endif // DEBUG
- os << req.method << " " << req.uri;
+ os << req.method_str() << " " << req.uri;
if (req.query.length()) {
os << "?" << req.query;
}
- // TODO ver que este bien el \r\l
- os << " HTTP/" << req.version << "\n\r" << static_cast<const HTTPMessage&>(req);
+ os << " HTTP/" << req.version << "\r\n"
+ << static_cast<const HTTPMessage&>(req);
return os;
}