From b952d85734dc3bb5b23c1033dcce025a32a4bcf0 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sun, 18 May 2008 04:48:06 +0000 Subject: [PATCH] fixed error handling and added support for relative http redirects (which aren't allowed by the standard) --- include/libtorrent/http_connection.hpp | 1 + src/http_connection.cpp | 36 +++++++++++++++++++++++--- test/setup_transfer.cpp | 9 ++++--- test/test_http_connection.cpp | 1 + 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/include/libtorrent/http_connection.hpp b/include/libtorrent/http_connection.hpp index ae090c0a3..faf0194e4 100644 --- a/include/libtorrent/http_connection.hpp +++ b/include/libtorrent/http_connection.hpp @@ -158,6 +158,7 @@ private: bool m_called; std::string m_hostname; std::string m_port; + std::string m_url; // the current download limit, in bytes per second // 0 is unlimited. diff --git a/src/http_connection.cpp b/src/http_connection.cpp index d2449fcbb..4bd29a5b0 100644 --- a/src/http_connection.cpp +++ b/src/http_connection.cpp @@ -114,6 +114,7 @@ void http_connection::get(std::string const& url, time_duration timeout, int pri "\r\n"; sendbuffer = headers.str(); + m_url = url; start(hostname, boost::lexical_cast(port), timeout, prio , ps, ssl, handle_redirects, bind_addr); } @@ -417,17 +418,44 @@ void http_connection::on_read(error_code const& e if (code >= 300 && code < 400) { // attempt a redirect - std::string const& url = m_parser.header("location"); - if (url.empty()) + std::string const& location = m_parser.header("location"); + if (location.empty()) { // missing location header - callback(e); + callback(asio::error::fault); + close(); return; } error_code ec; m_sock.close(ec); - get(url, m_timeout, m_priority, &m_proxy, m_redirects - 1); + using boost::tuples::ignore; + char const* error; + boost::tie(ignore, ignore, ignore, ignore, ignore, error) + = parse_url_components(location); + if (error == 0) + { + get(location, m_timeout, m_priority, &m_proxy, m_redirects - 1); + } + else + { + // some broken web servers send out relative paths + // in the location header. + std::string url = m_url; + // remove the leaf filename + std::size_t i = url.find_last_of('/'); + if (i == std::string::npos) + { + url += '/'; + } + else + { + url.resize(i + 1); + } + url += location; + + get(url, m_timeout, m_priority, &m_proxy, m_redirects - 1); + } return; } diff --git a/test/setup_transfer.cpp b/test/setup_transfer.cpp index f68508f45..018130f7c 100644 --- a/test/setup_transfer.cpp +++ b/test/setup_transfer.cpp @@ -97,10 +97,11 @@ void start_web_server(int port, bool ssl) "server.range-requests = \"enable\"\n" "server.port = " << port << "\n" "server.pid-file = \"./lighty" << port << ".pid\"\n" - "url.redirect = (\"^/redirect$\" => \"" - << (ssl?"https":"http") << "://127.0.0.1:" << port << "/test_file\", " - "\"^/infinite_redirect$\" => \"" - << (ssl?"https":"http") << "://127.0.0.1:" << port << "/infinite_redirect\")\n" + "url.redirect = (" + "\"^/redirect$\" => \"" << (ssl?"https":"http") << "://127.0.0.1:" << port << "/test_file\"" + ", \"^/infinite_redirect$\" => \"" << (ssl?"https":"http") << "://127.0.0.1:" << port << "/infinite_redirect\"" + ", \"^/relative/redirect$\" => \"../test_file\"" + ")\n" "$HTTP[\"url\"] == \"/test_file.gz\" {\n" " setenv.add-response-header = ( \"Content-Encoding\" => \"gzip\" )\n" "# mimetype.assign = ()\n" diff --git a/test/test_http_connection.cpp b/test/test_http_connection.cpp index 781d7a3d8..f6c9c8a12 100644 --- a/test/test_http_connection.cpp +++ b/test/test_http_connection.cpp @@ -104,6 +104,7 @@ void run_suite(std::string const& protocol, proxy_settings const& ps) << " proxy **********************\n" << std::endl; typedef boost::optional err; + run_test(protocol + "://127.0.0.1:8001/relative/redirect", 3216, 200, 2, error_code(), ps); run_test(protocol + "://127.0.0.1:8001/redirect", 3216, 200, 2, error_code(), ps); run_test(protocol + "://127.0.0.1:8001/infinite_redirect", 0, 301, 6, error_code(), ps); run_test(protocol + "://127.0.0.1:8001/test_file", 3216, 200, 1, error_code(), ps);