f32a8adff104cc4f90d4267be27678c680d67fcb
[anna.git] / example / http / xmlSender / main.cpp
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 /*
10    Envia una peticion de interseccion sobre HTTP/XML para ihttp_server
11
12    El cliente de esta aplicacion es: ihttp_server.p => Transporte: http::Transport.
13 */
14 #include <iostream>
15
16 #include <string.h>
17
18 #include <anna/core/core.hpp>
19 #include <anna/comm/comm.hpp>
20
21 #include <anna/app/functions.hpp>
22
23 #include <anna/xml/DocumentFile.hpp>
24 #include <anna/xml/DocumentMemory.hpp>
25
26 #include <anna/io/TextReader.hpp>
27
28 #include <anna/http/Request.hpp>
29 #include <anna/http/Response.hpp>
30 #include <anna/http/Handler.hpp>
31 #include <anna/http/Transport.hpp>
32 #include <anna/http/functions.hpp>
33
34 class MyHandler : public http::Handler {
35 public:
36    MyHandler () : http::Handler ("ihttp_client::MyHandler") {;}
37
38 private:
39    http::Response a_httpResponse;
40
41    void evRequest (ClientSocket&, const http::Request&) throw (RuntimeException) {;}
42    void evResponse (ClientSocket&, const http::Response&) throw (RuntimeException);
43 };
44
45 class MyCommunicator : public Communicator {
46 public:
47    MyCommunicator () : Communicator (), a_httpRequest ()
48    {
49       a_httpRequest.setMethod (http::Method::Type::Get);
50       a_httpRequest.setURI ("ihttp_client");
51    }
52
53 private:
54    MyHandler a_httpHandler;
55    http::Request a_httpRequest;
56
57    void eventReceiveMessage (ClientSocket &, const Message&) throw (RuntimeException);
58    void eventBreakConnection (Server* server) throw ();
59    void eventStartup () throw (RuntimeException);
60 };
61
62 class IHTTPClient : public anna::comm::Application {
63 public:
64    IHTTPClient ();
65
66    Server* getServer () const throw () { return a_server; }
67
68 private:
69    MyCommunicator a_communicator;
70    Server* a_server;
71
72    void initialize () throw (RuntimeException);
73    void run () throw (RuntimeException);
74 };
75
76 using namespace std;
77
78 bool st_xmlResponse (false);
79
80 int main (int argc, const char** argv)
81 {
82    CommandLine& commandLine (CommandLine::instantiate ());
83    IHTTPClient app;
84
85    http::functions::initialize ();
86
87    try {
88       commandLine.initialize (argv, argc);
89       commandLine.verify ();
90
91       Logger::setLevel (Logger::Debug);
92       Logger::initialize ("ihttp_client", new TraceWriter ("file.trace", 4096000));
93
94       app.start ();
95    }
96    catch (Exception& ex) {
97       cout << ex.asString () << endl;
98    }
99
100    return 0;
101 }
102
103 IHTTPClient::IHTTPClient () :
104    Application ("ihttp_client", "IHTTPClient", "2.0.0")
105 {
106    CommandLine& commandLine (CommandLine::instantiate ());
107
108    commandLine.add ("p", CommandLine::Argument::Mandatory, "Puerto en el que el servidor atiende respuestas.");
109    commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccion IP Puerto en el que el servidor atiende respuestas.");
110    commandLine.add ("xml", CommandLine::Argument::Optional, "Documento XML que contiene la peticion");
111    commandLine.add ("nocheck", CommandLine::Argument::Optional, "Indicador para que no comprueba la validaded del HTML", false);
112    commandLine.add ("version", CommandLine::Argument::Optional, "Indica la version HTTP usada para enviar");
113    commandLine.add ("uri", CommandLine::Argument::Optional, "URI a usar");
114    commandLine.add ("m", CommandLine::Argument::Optional, "Metodo HTTP a usar");
115    commandLine.add ("xmlresponse", CommandLine::Argument::Optional, "Visualiza la respuesta como un documento XML", false);
116    commandLine.add ("overquota", CommandLine::Argument::Optional, "Numero de bytes a recibir sin identificar el protocolo");
117    commandLine.add ("c", CommandLine::Argument::Optional, "Valor de la cookie");
118 }
119
120 void IHTTPClient::initialize () 
121    throw (RuntimeException)
122 {
123    CommandLine& cl (CommandLine::instantiate ());
124
125    Network& network = Network::instantiate ();
126
127    Host* host = network.find_host ("host000");
128    host->assign (network.find (Device::asAddress (cl.getValue ("a"))));
129
130    comm::TransportFactory& ttff = http::Transport::getFactory ();
131    if (cl.exists ("overquota") == true) 
132       ttff.setOverQuotaSize (cl.getIntegerValue ("overquota"));
133
134    a_server = host->createServer ("http_server", cl.getIntegerValue ("p"), false, &ttff);
135 }
136
137 void IHTTPClient::run ()
138    throw (RuntimeException)
139 {
140    a_communicator.accept ();
141 }
142
143 void MyCommunicator::eventStartup ()
144    throw (RuntimeException)
145 {
146    CommandLine& cl (CommandLine::instantiate ());
147
148    const char* filename = (cl.exists ("xml")) ? cl.getValue ("xml"): NULL;
149
150    if (filename == NULL) {
151       a_httpRequest.clearBody ();
152    }
153    else {
154       if (cl.exists ("nocheck") == false) {
155          xml::DocumentFile xmlDocument;
156          xmlDocument.initialize (filename);
157          a_httpRequest.setBody (xmlDocument.getContent ());
158       }
159       else {
160          io::TextReader reader;
161          reader.open (filename);
162          DataBlock body (true);
163          const char* line;
164    
165          while ((line = reader.fetch ()) != NULL)
166             body.append (line, anna_strlen (line));
167    
168          http::Header* header = a_httpRequest.createHeader (http::Header::Type::Connection);
169          header->setValue ("   Keep-Alive    ");
170    
171          a_httpRequest.setBody (body);
172       }
173    }
174
175    if (cl.exists ("version"))
176       a_httpRequest.setVersion (cl.getValue ("version"));
177
178    if (cl.exists ("uri"))
179       a_httpRequest.setURI (cl.getValue ("uri"));
180
181    if (cl.exists ("xmlresponse"))
182       st_xmlResponse = true;
183
184    if (cl.exists ("m")) {
185       http::Method::Type::_v type = http::Method::Type::asEnum (cl.getValue ("m"));
186
187       if (type == http::Method::Type::None) {
188          string msg ("Metodo HTTP no reconocido. ");
189          msg += http::Method::Type::asList ();
190          throw RuntimeException (msg, ANNA_FILE_LOCATION);
191       }
192
193       a_httpRequest.setMethod (type);
194    }
195
196    if (cl.exists ("c") == true) {
197       http::Header* header = a_httpRequest.createHeader ("Cookie");
198       header->setValue (cl.getValue ("c"));
199       cout << "Con cookie: " << cl.getValue ("c") << " | " << header->asString () << endl << endl;
200    }
201
202    // Header requeridos por la plataforma MovilForum para enviar mensajes WapPush
203    a_httpRequest.createHeader (http::Header::Type::ContentType)->setValue ("text/xml; charset=\"iso-8859-1\"");
204    a_httpRequest.createHeader (http::Header::Type::UserAgent)->setValue ("ANNA.http 1.x");
205
206    string host = anna::functions::asString ("%s:%d", cl.getValue ("a"), cl.getIntegerValue ("p"));
207    a_httpRequest.createHeader (http::Header::Type::Host)->setValue (host);
208    a_httpRequest.createHeader (http::Header::Type::Authorization)->setValue (" Basic VGlkTGNtOlQxZExjbQ==");
209    
210    static_cast <IHTTPClient&> (anna::comm::functions::getApp ()).getServer ()->send (a_httpRequest);
211 }
212
213 void MyCommunicator::eventReceiveMessage (ClientSocket& clientSocket, const Message& message)
214    throw (RuntimeException)
215 {
216    LOGMETHOD (TraceMethod tm ("MyCommunicator", "eventReceiveMessage", ANNA_FILE_LOCATION));
217
218    if (clientSocket.support (http::Transport::className ()) == false)
219       return;
220
221    a_httpHandler.apply (clientSocket, message);
222 }
223
224 void MyCommunicator::eventBreakConnection (Server* server) 
225    throw ()
226 {
227    cout << "Perdida conexion con " << server->asString () << endl;
228    requestStop ();
229 }
230
231 void MyHandler::evResponse (ClientSocket& clientSocket, const http::Response& response)
232    throw (RuntimeException)
233 {
234    const DataBlock& body = response.getBody ();
235    
236    cout << "HTTP StatusCode: " << response.getStatusCode () << endl;
237    cout << "HTTP Text: " << response.getReasonPhrase () << endl;
238
239    if (st_xmlResponse == false)
240       cout << "Resultado: \n" << anna::functions::asString (body, 24) << endl << endl;
241    else {
242       try {
243          xml::DocumentMemory xmlDoc;
244          xmlDoc.initialize (response.getBody ());
245          cout << xmlDoc.getContentAsCString () << endl << endl;
246       }
247       catch (RuntimeException& ex) {
248          ex.trace ();
249       }
250    }
251
252    app::functions::component <Communicator> (ANNA_FILE_LOCATION)->requestStop ();
253 }
254