Remove dynamic exceptions
[anna.git] / include / anna / http / Message.hpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite                           //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
7
8
9 #ifndef anna_http_Message_hpp
10 #define anna_http_Message_hpp
11
12 #include <anna/core/util/Recycler.hpp>
13
14 #include <anna/comm/Message.hpp>
15
16 #include <anna/http/Header.hpp>
17 #include <anna/http/Version.hpp>
18
19 namespace anna {
20
21 namespace http {
22
23 namespace parser {
24 class Abstract;
25 }
26
27 /**
28    Clase base de los mensajes HTTP segun la RFC 2616.
29 */
30 class Message : public comm::Message {
31 public:
32   typedef Recycler <Header>::iterator header_iterator;
33   typedef Recycler <Header>::const_iterator const_header_iterator;
34
35   /**
36    * Para poder acceder a todos los métodos de anna::comm::Message;;setBody cuando
37    * se invocan desde un anna::http::Message (o heredados).
38    */
39   using comm::Message::setBody;
40
41   /**
42      Tipos de mensaje HTTP.
43      \see Message
44   */
45   struct Type {
46     enum _v {
47       Request, /**< Peticion HTTP */
48       Response /**< Respuesta HTTP */
49     };
50   };
51
52   /**
53      Devuelve el tipo de este mensaje HTTP.
54      \return el tipo de este mensaje HTTP.
55   */
56   Type::_v getType() const { return a_type; }
57
58   /**
59      Devuelve la version del protocolo HTTP usada en el mensaje.
60      \return la version del protocolo HTTP usada en el mensaje.
61   */
62   const std::string& getVersion() const { return a_version; }
63
64   /*
65    * Devuelve el enumerado que identifica la versión HTTP usada en el mensaje.
66    * \return el enumerado que identifica la versión HTTP usada en el mensaje.
67    */
68   Version::_v getVersionAsEnum() const { return Version::asEnum(a_version); }
69
70   /**
71    * Devuelve los parámetros extras que pueden haber estado contenidos en los bloques
72    * de datos, en caso de que el mensaje se haya recibido como un "Transfer-Encoding: chunked".
73    * \return Los parámetros extras que pueden haber estado contenidos en los bloques
74    */
75   const std::string& getExtraParameters() const { return a_extraParameters;  }
76
77   /**
78      Establece la version a codificar en el mensaje.
79      \param version Texto con la version HTTP a usar, HTTP/1.1, por ejemplo.
80   */
81   void setVersion(const std::string& version) { a_version = version; }
82
83   /**
84    * Establece la versión a codificar en el mensaje.
85    * \param version Identificador de la versión.
86    */
87   void setVersion(const Version::_v version) { a_version = Version::asCString(version); }
88
89   /**
90    * Establece el cuerpo de este mensaje con el contenido del documento XML correspondiente al
91    * nodo XML recibido como parámetro.
92    *
93    * También establece la cabecera \em Content-Type.
94    *
95    * \param node Nodo XML que contiene el documento XML.
96    */
97   comm::Message* setBody(const xml::Node* node) noexcept(false);
98
99   /**
100      Crea una nueva cabecera en este mensaje.
101      \param type Tipo de cabecera a crear.
102      \return La instancia de la nueva cabecera.
103   */
104   Header* createHeader(const Header::Type::_v type)
105   noexcept(false) {
106     return a_headers.create()->initialize(type);
107   }
108
109   /**
110      Crea una nueva cabecera en este mensaje.
111      \param name Nombre de la cabecera a crear.
112      \return La instancia de la nueva cabecera.
113   */
114   Header* createHeader(const std::string& name)
115   noexcept(false) {
116     return a_headers.create()->initialize(name);
117   }
118
119   /**
120      Devuelve la instancia de la primera cabecera que coincide con el tipo
121      recibido como parametro. Puede ser NULL si el mensaje no contiene ninguna
122      cabecera del tipo solicitado.
123      \param type Tipo de cabecera buscado.
124      \return La primera cabecera que coincide con el tipo recibido como parametro.
125   */
126   const Header* find(const Header::Type::_v type) const {
127     return const_cast <Message*>(this)->find(type);
128   }
129
130   /**
131      Devuelve la instancia de la primera cabecera que coincide con el tipo
132      recibido como parametro. Puede ser NULL si el mensaje no contiene ninguna
133      cabecera del tipo solicitado.
134      \param type Tipo de cabecera buscado.
135      \return La primera cabecera que coincide con el tipo recibido como parametro.
136   */
137   Header* find(const Header::Type::_v type) ;
138
139   /**
140      Devuelve la instancia de la primera cabecera de tipo Header::Category::Extension cuyo
141      nombre coincide con el recibido como parametro. Puede ser NULL.
142      \param name Nombre de la extension buscada.
143      \return La primera cabecera que coincide con el tipo recibido como parametro.
144   */
145   Header* find(const char* name) ;
146
147   /**
148      Inicializa el contenido de este mensaje. Libera las cabeceras y el cuerpo del mensaje.
149   */
150   void clear() { a_headers.clear(); clearBody(); a_extraParameters.clear();}
151
152   /**
153      Devuelve un iterador al comienzo de la lista de cabeceras.
154      \return un iterador al comienzo de la lista de cabeceras.
155   */
156   header_iterator header_begin() { return a_headers.begin(); }
157
158   /**
159      Devuelve un iterador al final de la lista de cabeceras.
160      \return un iterador al final de la lista de cabeceras.
161   */
162   header_iterator header_end() { return a_headers.end(); }
163
164   /**
165      Devuelve un iterador al comienzo de la lista de cabeceras.
166      \return un iterador al comienzo de la lista de cabeceras.
167   */
168   const_header_iterator header_begin() const { return a_headers.begin(); }
169
170   /**
171      Devuelve un iterador al final de la lista de cabeceras.
172      \return un iterador al final de la lista de cabeceras.
173   */
174   const_header_iterator header_end() const { return a_headers.end(); }
175
176   /**
177      Codifica este mensaje.
178      \return El bloque de datos que contiene el mensaje codificado.
179   */
180   const DataBlock& code() noexcept(false);
181
182   /**
183      Devuelve una cadena con toda la informacion relevante de este objeto.
184      \return una cadena con toda la informacion relevante de este objeto.
185   */
186   virtual std::string asString() const  = 0;
187
188   /**
189      Devuelve la instancia de la cabecera a la que referencia el iterator
190      recibido como parametro.
191      \return la instancia de la cabecera a la que referencia el iterator
192      recibido como parametro.
193   */
194   static Header* header(header_iterator& ii) { return Recycler<Header>::data(ii); }
195
196   /**
197      Devuelve la instancia de la cabecera a la que referencia el iterator
198      recibido como parametro.
199      \return la instancia de la cabecera a la que referencia el iterator
200      recibido como parametro.
201   */
202   static const Header* header(const_header_iterator& ii) { return Recycler<Header>::data(ii); }
203
204 protected:
205   /**
206      Constructor.
207      \param type Tipo de mensaje.
208   */
209   Message(const Type::_v type) : comm::Message(StatusCodeBuffer::Reserve),
210     a_type(type), a_version("HTTP/1.1")
211   {;}
212
213 private:
214   const Type::_v a_type;
215   std::string a_version;
216   Recycler <Header> a_headers;
217   std::string a_extraParameters;
218
219   void codeLine(const std::string& line) noexcept(false);
220
221   void appendExtraParameter(const std::string& extraParameter) {
222     a_extraParameters += ' ';
223     a_extraParameters += extraParameter;
224   }
225
226   virtual std::string codeStartLine() const noexcept(false) = 0;
227
228   friend class parser::Abstract;
229 };
230
231
232 }
233 }
234
235 #endif