]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // |
b32b8144 | 2 | // http_client.cpp |
7c673cae FG |
3 | // ~~~~~~~~~~~~~~~ |
4 | // | |
b32b8144 | 5 | // Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
7c673cae FG |
6 | // |
7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 | // | |
10 | ||
11 | #include <iostream> | |
12 | #include <istream> | |
13 | #include <ostream> | |
14 | #include <string> | |
15 | #include <boost/asio/ip/tcp.hpp> | |
16 | ||
17 | using boost::asio::ip::tcp; | |
18 | ||
19 | int main(int argc, char* argv[]) | |
20 | { | |
21 | try | |
22 | { | |
23 | if (argc != 3) | |
24 | { | |
25 | std::cout << "Usage: http_client <server> <path>\n"; | |
26 | std::cout << "Example:\n"; | |
27 | std::cout << " http_client www.boost.org /LICENSE_1_0.txt\n"; | |
28 | return 1; | |
29 | } | |
30 | ||
31 | boost::asio::ip::tcp::iostream s; | |
32 | ||
33 | // The entire sequence of I/O operations must complete within 60 seconds. | |
34 | // If an expiry occurs, the socket is automatically closed and the stream | |
35 | // becomes bad. | |
b32b8144 | 36 | s.expires_after(boost::posix_time::seconds(60)); |
7c673cae FG |
37 | |
38 | // Establish a connection to the server. | |
39 | s.connect(argv[1], "http"); | |
40 | if (!s) | |
41 | { | |
42 | std::cout << "Unable to connect: " << s.error().message() << "\n"; | |
43 | return 1; | |
44 | } | |
45 | ||
46 | // Send the request. We specify the "Connection: close" header so that the | |
47 | // server will close the socket after transmitting the response. This will | |
48 | // allow us to treat all data up until the EOF as the content. | |
49 | s << "GET " << argv[2] << " HTTP/1.0\r\n"; | |
50 | s << "Host: " << argv[1] << "\r\n"; | |
51 | s << "Accept: */*\r\n"; | |
52 | s << "Connection: close\r\n\r\n"; | |
53 | ||
54 | // By default, the stream is tied with itself. This means that the stream | |
55 | // automatically flush the buffered output before attempting a read. It is | |
56 | // not necessary not explicitly flush the stream at this point. | |
57 | ||
58 | // Check that response is OK. | |
59 | std::string http_version; | |
60 | s >> http_version; | |
61 | unsigned int status_code; | |
62 | s >> status_code; | |
63 | std::string status_message; | |
64 | std::getline(s, status_message); | |
65 | if (!s || http_version.substr(0, 5) != "HTTP/") | |
66 | { | |
67 | std::cout << "Invalid response\n"; | |
68 | return 1; | |
69 | } | |
70 | if (status_code != 200) | |
71 | { | |
72 | std::cout << "Response returned with status code " << status_code << "\n"; | |
73 | return 1; | |
74 | } | |
75 | ||
76 | // Process the response headers, which are terminated by a blank line. | |
77 | std::string header; | |
78 | while (std::getline(s, header) && header != "\r") | |
79 | std::cout << header << "\n"; | |
80 | std::cout << "\n"; | |
81 | ||
82 | // Write the remaining data to output. | |
83 | std::cout << s.rdbuf(); | |
84 | } | |
85 | catch (std::exception& e) | |
86 | { | |
87 | std::cout << "Exception: " << e.what() << "\n"; | |
88 | } | |
89 | ||
90 | return 0; | |
91 | } |