| | #include "ug_http_client.h" |
| | #include "moses/Util.h" |
| | #include <iostream> |
| |
|
| | namespace Moses |
| | { |
| | using boost::asio::ip::tcp; |
| |
|
| | std::string http_client::content() const { return m_content.str(); } |
| |
|
| | http_client:: |
| | http_client(boost::asio::io_service& io_service, |
| | std::string const& server, |
| | std::string const& port, |
| | std::string const& path) |
| | : resolver_(io_service), socket_(io_service) |
| | { |
| | init(server, port, path); |
| | } |
| | |
| | http_client:: |
| | http_client(boost::asio::io_service& io_service, std::string url, std::ostream* log) |
| | : resolver_(io_service), socket_(io_service) |
| | { |
| | std::string server; |
| | std::string path = "/"; |
| | std::string port = "http"; |
| | size_t p = url.find("://"), q; |
| | if (p < url.size()) |
| | { |
| | port = url.substr(0,p); |
| | url.erase(0, p+3); |
| | } |
| | p = std::min(url.find_first_of(":/"), url.size()); |
| | q = std::min(url.find("/"), url.size()); |
| | if (p < url.size() && url[p] == ':') |
| | port = url.substr(p+1,q-p-1); |
| | server = url.substr(0,p); |
| | if (q < url.size()) |
| | path = url.substr(q); |
| | #if 1 |
| | if (log) |
| | { |
| | *log << HERE << std::endl; |
| | |
| | *log << "SERVER " << server << std::endl; |
| | *log << "PORT " << port << "" << std::endl; |
| | *log << "PATH " << path << std::endl; |
| | } |
| | #endif |
| | init(server, port, path); |
| | } |
| |
|
| | void |
| | http_client:: |
| | init(std::string const& server, std::string const& port, std::string const& path) |
| | { |
| | |
| | |
| | |
| | |
| |
|
| | std::ostream request_stream(&request_); |
| | request_stream << "GET " << path << " HTTP/1.0\r\n"; |
| | request_stream << "Host: " << server << "\r\n"; |
| | request_stream << "Accept: */*\r\n"; |
| | request_stream << "Connection: close\r\n\r\n"; |
| | |
| | |
| | |
| | tcp::resolver::query query(server, port.c_str()); |
| | resolver_.async_resolve(query, |
| | boost::bind(&http_client::handle_resolve, this, |
| | boost::asio::placeholders::error, |
| | boost::asio::placeholders::iterator)); |
| | |
| | } |
| |
|
| | void |
| | http_client:: |
| | handle_resolve(const boost::system::error_code& err, |
| | tcp::resolver::iterator endpoint_iterator) |
| | { |
| | if (!err) |
| | { |
| | |
| | |
| | tcp::endpoint endpoint = *endpoint_iterator; |
| | socket_.async_connect(endpoint, |
| | boost::bind(&http_client::handle_connect, this, |
| | boost::asio::placeholders::error, ++endpoint_iterator)); |
| | } |
| | else |
| | { |
| | m_error << "Error: " << err.message() << "\n"; |
| | } |
| | } |
| |
|
| | void |
| | http_client:: |
| | handle_connect(const boost::system::error_code& err, |
| | tcp::resolver::iterator endpoint_iterator) |
| | { |
| | if (!err) |
| | { |
| | |
| | boost::asio::async_write(socket_, request_, |
| | boost::bind(&http_client::handle_write_request, this, |
| | boost::asio::placeholders::error)); |
| | } |
| | else if (endpoint_iterator != tcp::resolver::iterator()) |
| | { |
| | |
| | socket_.close(); |
| | tcp::endpoint endpoint = *endpoint_iterator; |
| | socket_.async_connect(endpoint, |
| | boost::bind(&http_client::handle_connect, this, |
| | boost::asio::placeholders::error, ++endpoint_iterator)); |
| | } |
| | else m_error << "Error: " << err.message() << "\n"; |
| | } |
| |
|
| | void |
| | http_client:: |
| | handle_write_request(const boost::system::error_code& err) |
| | { |
| | using namespace boost::asio; |
| | if (err) { m_error << "Error: " << err.message() << "\n"; return; } |
| | |
| | |
| | |
| | |
| | async_read_until(socket_, response_, "\r\n", |
| | boost::bind(&http_client::handle_read_status_line, |
| | this, placeholders::error)); |
| | } |
| |
|
| | void |
| | http_client:: |
| | handle_read_status_line(const boost::system::error_code& err) |
| | { |
| | if (err) { m_error << "Error: " << err << "\n"; return; } |
| |
|
| | using namespace boost::asio; |
| | |
| | std::istream response_stream(&response_); |
| | response_stream >> m_http_version >> m_status_code; |
| | std::getline(response_stream, m_status_message); |
| | if (!response_stream || m_http_version.substr(0, 5) != "HTTP/") |
| | m_error << "Invalid response\n"; |
| | else if (m_status_code != 200) |
| | m_error << "Response returned with status code " << m_status_code << "\n"; |
| | else |
| | async_read_until(socket_, response_, "\r\n\r\n", |
| | boost::bind(&http_client::handle_read_headers, this, |
| | placeholders::error)); |
| | } |
| |
|
| |
|
| | void |
| | http_client:: |
| | handle_read_headers(const boost::system::error_code& err) |
| | { |
| | if (err) { m_error << "Error: " << err << "\n"; return; } |
| | |
| | |
| | std::istream response_stream(&response_); |
| | std::string line; |
| | while (std::getline(response_stream, line) && line != "\r") |
| | m_header.push_back(line); |
| | |
| | |
| | if (response_.size() > 0) |
| | m_content << &response_; |
| | |
| | using namespace boost::asio; |
| | |
| | async_read(socket_, response_, transfer_at_least(1), |
| | boost::bind(&http_client::handle_read_content, this, |
| | placeholders::error)); |
| | } |
| |
|
| | void |
| | http_client:: |
| | handle_read_content(const boost::system::error_code& err) |
| | { |
| | using namespace boost::asio; |
| | if(!err) |
| | { |
| | |
| | |
| | m_content << &response_; |
| | async_read(socket_, response_, transfer_at_least(1), |
| | boost::bind(&http_client::handle_read_content, this, |
| | placeholders::error)); |
| | } |
| | else if (err != boost::asio::error::eof) |
| | { |
| | m_error << "Error: " << err << "\n"; |
| | } |
| | } |
| |
|
| | std::string |
| | uri_encode(std::string const& in) |
| | { |
| | char buf[3 * in.size() + 1]; |
| | size_t i = 0; |
| | for (unsigned char const* c = (unsigned char const*)in.c_str(); *c; ++c) |
| | { |
| | |
| | if (*c == ' ') buf[i++] = '+'; |
| | else if (*c == '.' || *c == '~' || *c == '_' || *c == '-') buf[i++] = *c; |
| | else if (*c < '0') i += sprintf(buf+i, "%%%02x", int(*c)); |
| | else if (*c <= '9') buf[i++] = *c; |
| | else if (*c < 'A') i += sprintf(buf+i, "%%%02x", int(*c)); |
| | else if (*c <= 'Z') buf[i++] = *c; |
| | else if (*c < 'a') i += sprintf(buf+i, "%%%02x", int(*c)); |
| | else if (*c <= 'z') buf[i++] = *c; |
| | else i += sprintf(buf+i, "%%%x", int(*c)); |
| | } |
| | buf[i] = 0; |
| | return std::string(buf); |
| | } |
| |
|
| | } |
| |
|