First commit
[anna.git] / include / anna / http / Message.hpp
1 // ANNA - Anna is Not 'N' Anymore
2 //
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
4 //
5 // https://bitbucket.org/testillano/anna
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
11 //     * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //     * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 //     * Neither the name of Google Inc. nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 // Authors: eduardo.ramos.testillano@gmail.com
34 //          cisco.tierra@gmail.com
35
36
37 #ifndef anna_http_Message_hpp
38 #define anna_http_Message_hpp
39
40 #include <anna/core/util/Recycler.hpp>
41
42 #include <anna/comm/Message.hpp>
43
44 #include <anna/http/Header.hpp>
45 #include <anna/http/Version.hpp>
46
47 namespace anna {
48
49 namespace http {
50
51 namespace parser {
52 class Abstract;
53 }
54
55 /**
56    Clase base de los mensajes HTTP segun la RFC 2616.
57 */
58 class Message : public comm::Message {
59 public:
60   typedef Recycler <Header>::iterator header_iterator;
61   typedef Recycler <Header>::const_iterator const_header_iterator;
62
63   /**
64    * Para poder acceder a todos los métodos de anna::comm::Message;;setBody cuando
65    * se invocan desde un anna::http::Message (o heredados).
66    */
67   using comm::Message::setBody;
68
69   /**
70      Tipos de mensaje HTTP.
71      \see Message
72   */
73   struct Type {
74     enum _v {
75       Request, /**< Peticion HTTP */
76       Response /**< Respuesta HTTP */
77     };
78   };
79
80   /**
81      Devuelve el tipo de este mensaje HTTP.
82      \return el tipo de este mensaje HTTP.
83   */
84   Type::_v getType() const throw() { return a_type; }
85
86   /**
87      Devuelve la version del protocolo HTTP usada en el mensaje.
88      \return la version del protocolo HTTP usada en el mensaje.
89   */
90   const std::string& getVersion() const throw() { return a_version; }
91
92   /*
93    * Devuelve el enumerado que identifica la versión HTTP usada en el mensaje.
94    * \return el enumerado que identifica la versión HTTP usada en el mensaje.
95    */
96   Version::_v getVersionAsEnum() const throw() { return Version::asEnum(a_version); }
97
98   /**
99    * Devuelve los parámetros extras que pueden haber estado contenidos en los bloques
100    * de datos, en caso de que el mensaje se haya recibido como un "Transfer-Encoding: chunked".
101    * \return Los parámetros extras que pueden haber estado contenidos en los bloques
102    */
103   const std::string& getExtraParameters() const throw() { return a_extraParameters;  }
104
105   /**
106      Establece la version a codificar en el mensaje.
107      \param version Texto con la version HTTP a usar, HTTP/1.1, por ejemplo.
108   */
109   void setVersion(const std::string& version) throw() { a_version = version; }
110
111   /**
112    * Establece la versión a codificar en el mensaje.
113    * \param version Identificador de la versión.
114    */
115   void setVersion(const Version::_v version) throw() { a_version = Version::asCString(version); }
116
117   /**
118    * Establece el cuerpo de este mensaje con el contenido del documento XML correspondiente al
119    * nodo XML recibido como parámetro.
120    *
121    * También establece la cabecera \em Content-Type.
122    *
123    * \param node Nodo XML que contiene el documento XML.
124    */
125   comm::Message* setBody(const xml::Node* node) throw(RuntimeException);
126
127   /**
128      Crea una nueva cabecera en este mensaje.
129      \param type Tipo de cabecera a crear.
130      \return La instancia de la nueva cabecera.
131   */
132   Header* createHeader(const Header::Type::_v type)
133   throw(RuntimeException) {
134     return a_headers.create()->initialize(type);
135   }
136
137   /**
138      Crea una nueva cabecera en este mensaje.
139      \param name Nombre de la cabecera a crear.
140      \return La instancia de la nueva cabecera.
141   */
142   Header* createHeader(const std::string& name)
143   throw(RuntimeException) {
144     return a_headers.create()->initialize(name);
145   }
146
147   /**
148      Devuelve la instancia de la primera cabecera que coincide con el tipo
149      recibido como parametro. Puede ser NULL si el mensaje no contiene ninguna
150      cabecera del tipo solicitado.
151      \param type Tipo de cabecera buscado.
152      \return La primera cabecera que coincide con el tipo recibido como parametro.
153   */
154   const Header* find(const Header::Type::_v type) const throw() {
155     return const_cast <Message*>(this)->find(type);
156   }
157
158   /**
159      Devuelve la instancia de la primera cabecera que coincide con el tipo
160      recibido como parametro. Puede ser NULL si el mensaje no contiene ninguna
161      cabecera del tipo solicitado.
162      \param type Tipo de cabecera buscado.
163      \return La primera cabecera que coincide con el tipo recibido como parametro.
164   */
165   Header* find(const Header::Type::_v type) throw();
166
167   /**
168      Devuelve la instancia de la primera cabecera de tipo Header::Category::Extension cuyo
169      nombre coincide con el recibido como parametro. Puede ser NULL.
170      \param name Nombre de la extension buscada.
171      \return La primera cabecera que coincide con el tipo recibido como parametro.
172   */
173   Header* find(const char* name) throw();
174
175   /**
176      Inicializa el contenido de este mensaje. Libera las cabeceras y el cuerpo del mensaje.
177   */
178   void clear() throw() { a_headers.clear(); clearBody(); a_extraParameters.clear();}
179
180   /**
181      Devuelve un iterador al comienzo de la lista de cabeceras.
182      \return un iterador al comienzo de la lista de cabeceras.
183   */
184   header_iterator header_begin() throw() { return a_headers.begin(); }
185
186   /**
187      Devuelve un iterador al final de la lista de cabeceras.
188      \return un iterador al final de la lista de cabeceras.
189   */
190   header_iterator header_end() throw() { return a_headers.end(); }
191
192   /**
193      Devuelve un iterador al comienzo de la lista de cabeceras.
194      \return un iterador al comienzo de la lista de cabeceras.
195   */
196   const_header_iterator header_begin() const throw() { return a_headers.begin(); }
197
198   /**
199      Devuelve un iterador al final de la lista de cabeceras.
200      \return un iterador al final de la lista de cabeceras.
201   */
202   const_header_iterator header_end() const throw() { return a_headers.end(); }
203
204   /**
205      Codifica este mensaje.
206      \return El bloque de datos que contiene el mensaje codificado.
207   */
208   const DataBlock& code() throw(anna::RuntimeException);
209
210   /**
211      Devuelve una cadena con toda la informacion relevante de este objeto.
212      \return una cadena con toda la informacion relevante de este objeto.
213   */
214   virtual std::string asString() const throw() = 0;
215
216   /**
217      Devuelve la instancia de la cabecera a la que referencia el iterator
218      recibido como parametro.
219      \return la instancia de la cabecera a la que referencia el iterator
220      recibido como parametro.
221   */
222   static Header* header(header_iterator& ii) throw() { return Recycler<Header>::data(ii); }
223
224   /**
225      Devuelve la instancia de la cabecera a la que referencia el iterator
226      recibido como parametro.
227      \return la instancia de la cabecera a la que referencia el iterator
228      recibido como parametro.
229   */
230   static const Header* header(const_header_iterator& ii) throw() { return Recycler<Header>::data(ii); }
231
232 protected:
233   /**
234      Constructor.
235      \param type Tipo de mensaje.
236   */
237   Message(const Type::_v type) : comm::Message(StatusCodeBuffer::Reserve),
238     a_type(type), a_version("HTTP/1.1")
239   {;}
240
241 private:
242   const Type::_v a_type;
243   std::string a_version;
244   Recycler <Header> a_headers;
245   std::string a_extraParameters;
246
247   void codeLine(const std::string& line) throw(RuntimeException);
248
249   void appendExtraParameter(const std::string& extraParameter) throw() {
250     a_extraParameters += ' ';
251     a_extraParameters += extraParameter;
252   }
253
254   virtual std::string codeStartLine() const throw(anna::RuntimeException) = 0;
255
256   friend class parser::Abstract;
257 };
258
259
260 }
261 }
262
263 #endif