Merge pull request #2254 from esohns/fstat_size_64_bits
[ACE_TAO.git] / ACE / protocols / examples / INet / HTTP_Simple_exec.cpp
blob12fb301c9638488cd0602514201f6b4e50ac40a4
1 #include "ace/Get_Opt.h"
2 #include <memory>
3 #include "ace/OS_NS_errno.h"
4 #include "ace/INet/HTTP_URL.h"
5 #include "ace/INet/HTTP_ClientRequestHandler.h"
6 #if defined (ACE_HAS_SSL) && ACE_HAS_SSL == 1
7 # include "ace/INet/SSL_CallbackManager.h"
8 # include "ace/INet/HTTPS_Context.h"
9 #endif
10 #include "ace/INet/INet_Log.h"
11 #include <iostream>
12 #include <fstream>
14 ACE_CString proxy_hostname;
15 u_short proxy_port = ACE::HTTP::URL::HTTP_PROXY_PORT;
16 ACE_CString url;
17 ACE_CString outfile;
18 #if defined (ACE_HAS_SSL) && ACE_HAS_SSL == 1
19 int ssl_mode = ACE_SSL_Context::SSLv23;
20 bool verify_peer = true;
21 bool ignore_verify = false;
22 ACE_CString certificate;
23 ACE_CString private_key;
24 ACE_CString ca_location;
25 #endif
27 void
28 usage ()
30 std::cout << "usage: http_simple_wget [options] <url>\n";
31 std::cout << "Executes an HTTP GET request and sends the result to STDOUT or file\n";
32 std::cout << "\t-H <hostname> \t\tproxy host to connect to\n";
33 std::cout << "\t-p <port> \t\tproxy port to connect to\n";
34 std::cout << "\t-o <filename> \t\tfile to write output to\n";
35 #if defined (ACE_HAS_SSL) && ACE_HAS_SSL == 1
36 std::cout << "\t-n \t\tno peer certificate verification\n";
37 std::cout << "\t-i \t\tignore peer certificate verification failures\n";
38 std::cout << "\t-c <filename> \t\tcertificate file (PEM format)\n";
39 std::cout << "\t-k <filename> \t\tprivate key file (PEM format); requires -c\n";
40 std::cout << "\t-C <path> \t\ttrusted CA file or directory\n";
41 #endif
44 bool
45 parse_args (int argc, ACE_TCHAR *argv [])
47 #if defined (ACE_HAS_SSL) && ACE_HAS_SSL == 1
48 ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("H:p:o:hv:nic:k:C:"), 0, 0, ACE_Get_Opt::RETURN_IN_ORDER);
49 #else
50 ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("H:p:o:h"), 0, 0, ACE_Get_Opt::RETURN_IN_ORDER);
51 #endif
53 int c;
54 ACE_CString s;
55 while ((c = get_opt ()) != EOF)
57 switch (c)
59 case 1:
60 url = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ());
61 break;
62 case 'H':
63 proxy_hostname = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ());
64 break;
66 case 'p':
67 proxy_port = (u_short)ACE_OS::atoi (ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ()));
68 break;
70 case 'o':
71 outfile = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ());
72 break;
74 #if defined (ACE_HAS_SSL) && ACE_HAS_SSL == 1
75 case 'n':
76 verify_peer = false;
77 break;
79 case 'i':
80 ignore_verify = true;
81 break;
83 case 'c':
84 certificate = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ());
85 break;
87 case 'k':
88 private_key = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ());
89 break;
91 case 'C':
92 ca_location = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ());
93 break;
94 #endif
95 case 'h':
96 default:
97 usage ();
98 return false;
102 return true;
105 class My_HTTP_RequestHandler
106 : public ACE::HTTP::ClientRequestHandler
108 public:
109 My_HTTP_RequestHandler () : in_length_ (0), read_length_ (0) {}
110 virtual ~My_HTTP_RequestHandler () {}
112 protected:
113 virtual void handle_request_error (const ACE::HTTP::URL& url)
115 std::cout << "ERROR" << std::endl;
116 std::cerr << "Failed to handle request for " << url.to_string ().c_str () << std::endl;
119 virtual void handle_connection_error (const ACE::HTTP::URL& url)
121 std::cout << "ERROR" << std::endl;
122 std::cerr << "Failed to set up connection for " << url.to_string ().c_str () << std::endl;
125 virtual void after_read (const char_type* /*buffer*/, int length_read)
127 if (this->read_length_ == 0)
129 this->in_length_ = this->response ().get_content_length ();
131 this->read_length_ += length_read;
132 std::cout << "\r [" << this->read_length_ << '/';
133 if (this->in_length_ != ACE::HTTP::Response::UNKNOWN_CONTENT_LENGTH)
135 std::cout << this->in_length_ << "] " << ((this->read_length_ * 100) / this->in_length_) << "%";
137 else
138 std::cout << "???]";
139 std::cout.flush ();
142 virtual void on_eof ()
144 ACE::HTTP::ClientRequestHandler::on_eof ();
145 std::cout << std::endl;
146 this->read_length_ = 0;
149 private:
150 int in_length_;
151 int read_length_;
155 ACE_TMAIN (int argc, ACE_TCHAR *argv [])
157 std::unique_ptr<std::ofstream> fout;
158 std::ostream* sout = &std::cout;
160 if (!parse_args (argc, argv))
162 return 1;
165 #if defined (ACE_HAS_SSL) && ACE_HAS_SSL == 1
166 ACE::HTTPS::Context::set_default_ssl_mode (ssl_mode);
167 ACE::HTTPS::Context::set_default_verify_mode (verify_peer);
168 ACE::HTTPS::Context::instance ().use_default_ca ();
169 if (!private_key.empty ())
171 if (certificate.empty ())
173 std::cerr << "ERROR: private key file [" << private_key << "] requires certificate file to be specified." << std::endl;
174 return 1;
176 if (!ACE::HTTPS::Context::instance ().set_key_files (private_key.c_str (), certificate.c_str ()))
178 std::cerr << "ERROR: failed to set private key [" << private_key << "]." << std::endl;
179 return 1;
182 if (!ca_location.empty ())
184 INET_DEBUG (6, (LM_INFO, DLINFO ACE_TEXT ("loading trusted CA [%C]\n"), ca_location.c_str ()));
185 if (!ACE::HTTPS::Context::instance ().load_trusted_ca (ca_location.c_str ()))
187 std::cerr << "ERROR: failed to load trusted CA from [" << ca_location << "]." << std::endl;
188 return 1;
190 INET_DEBUG (6, (LM_INFO, DLINFO ACE_TEXT ("loaded [%d] trusted CA\n"), ACE::HTTPS::Context::instance ().has_trusted_ca ()));
192 if (ignore_verify)
193 ACE::INet::SSL_CallbackManager::instance ()->set_certificate_callback (new ACE::INet::SSL_CertificateAcceptor);
194 #endif
196 std::cout << "Starting..." << std::endl;
198 if (!url.empty ())
200 if (!outfile.empty ())
202 fout.reset (new std::ofstream (outfile.c_str (), std::ios_base::binary|std::ios_base::out));
204 if (!*fout)
206 std::cerr << "Failed to open output file : " << outfile.c_str () << std::endl;
207 return 1;
210 sout = fout.get ();
213 std::cout << "Parsing url [" << url.c_str () << "]" << std::endl;
215 std::unique_ptr<ACE::INet::URL_Base> url_safe (ACE::INet::URL_Base::create_from_string (url));
217 if (url_safe.get () == 0 || url != url_safe->to_string ())
219 std::cerr << "Failed parsing url [" << url << "]" << std::endl;
220 std::cerr << "\tresult = " << (url_safe.get () == 0 ? "(null)" : url_safe->to_string ().c_str ()) << std::endl;
221 return 1;
224 ACE::HTTP::URL& http_url = *dynamic_cast<ACE::HTTP::URL*> (url_safe.get ());
226 if (!proxy_hostname.empty ())
228 std::cout << "Setting proxy: " << proxy_hostname.c_str () << ':' << proxy_port << std::endl;
229 http_url.set_proxy (proxy_hostname, proxy_port);
232 std::cout << "Opening url...";
233 My_HTTP_RequestHandler my_rh;
234 ACE::INet::URLStream urlin = http_url.open (my_rh);
235 if (urlin)
237 std::cout << "Received response "
238 << (int)my_rh.response ().get_status ().get_status ()
239 << " "
240 << my_rh.response ().get_status ().get_reason ().c_str ()
241 << std::endl;
242 if (my_rh.response ().get_status ().is_ok ())
244 std::cout << "Length: ";
245 if (my_rh.response ().get_content_length () != ACE::HTTP::Response::UNKNOWN_CONTENT_LENGTH)
246 std::cout << my_rh.response ().get_content_length () << " [";
247 else
248 std::cout << "(unknown) [";
249 if (my_rh.response ().get_content_type () != ACE::HTTP::Response::UNKNOWN_CONTENT_TYPE)
250 std::cout << my_rh.response ().get_content_type ().c_str ();
251 else
252 std::cout << "(unknown)";
253 std::cout << "]" << std::endl;
256 std::cout << "Saving to: ";
257 if (!outfile.empty ())
258 std::cout << '\'' << outfile.c_str () << '\'' << std::endl;
259 else
260 std::cout << "(stdout)" << std::endl;
262 (*sout) << urlin->rdbuf ();
263 sout->flush ();
266 else
268 std::cerr << "ERROR: No URL specified!" << std::endl;
269 usage ();
270 return 1;
273 std::cout << "Done" << std::endl;
275 return 0;