support http basic auth in http_connection passed in from the outside as opposed to part of the url
This commit is contained in:
parent
04c33d6fb2
commit
1b9b6f7292
|
@ -97,12 +97,13 @@ struct TORRENT_EXTRA_EXPORT http_connection
|
|||
int rate_limit() const
|
||||
{ return m_rate_limit; }
|
||||
|
||||
std::string sendbuffer;
|
||||
std::string m_sendbuffer;
|
||||
|
||||
void get(std::string const& url, time_duration timeout = seconds(30)
|
||||
, int prio = 0, proxy_settings const* ps = 0, int handle_redirects = 5
|
||||
, std::string const& user_agent = "", address const& bind_addr = address_v4::any()
|
||||
, int resolve_flags = 0
|
||||
, std::string const& user_agent = std::string()
|
||||
, address const& bind_addr = address_v4::any()
|
||||
, int resolve_flags = 0, std::string const& auth_ = std::string()
|
||||
#if TORRENT_USE_I2P
|
||||
, i2p_connection* i2p_conn = 0
|
||||
#endif
|
||||
|
@ -150,12 +151,13 @@ private:
|
|||
|
||||
std::vector<tcp::endpoint> m_endpoints;
|
||||
|
||||
socket_type m_sock;
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
asio::ssl::context* m_ssl_ctx;
|
||||
bool m_own_ssl_context;
|
||||
#endif
|
||||
|
||||
socket_type m_sock;
|
||||
#if TORRENT_USE_I2P
|
||||
i2p_connection* m_i2p_conn;
|
||||
#endif
|
||||
|
@ -185,6 +187,10 @@ private:
|
|||
// means do not bind
|
||||
address m_bind_addr;
|
||||
|
||||
// if username password was passed in, remember it in case we need to
|
||||
// re-issue the request for a redirect
|
||||
std::string m_auth;
|
||||
|
||||
int m_read_pos;
|
||||
|
||||
// the number of redirects to follow (in sequence)
|
||||
|
|
|
@ -61,16 +61,15 @@ http_connection::http_connection(io_service& ios
|
|||
, boost::asio::ssl::context* ssl_ctx
|
||||
#endif
|
||||
)
|
||||
:
|
||||
: m_sock(ios)
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
m_ssl_ctx(ssl_ctx),
|
||||
m_own_ssl_context(false),
|
||||
, m_ssl_ctx(ssl_ctx)
|
||||
, m_own_ssl_context(false)
|
||||
#endif
|
||||
m_sock(ios),
|
||||
#if TORRENT_USE_I2P
|
||||
m_i2p_conn(0),
|
||||
, m_i2p_conn(0)
|
||||
#endif
|
||||
m_resolver(resolver)
|
||||
, m_resolver(resolver)
|
||||
, m_handler(handler)
|
||||
, m_connect_handler(ch)
|
||||
, m_filter_handler(fh)
|
||||
|
@ -105,7 +104,7 @@ http_connection::~http_connection()
|
|||
|
||||
void http_connection::get(std::string const& url, time_duration timeout, int prio
|
||||
, proxy_settings const* ps, int handle_redirects, std::string const& user_agent
|
||||
, address const& bind_addr, int resolve_flags
|
||||
, address const& bind_addr, int resolve_flags, std::string const& auth_
|
||||
#if TORRENT_USE_I2P
|
||||
, i2p_connection* i2p_conn
|
||||
#endif
|
||||
|
@ -124,6 +123,10 @@ void http_connection::get(std::string const& url, time_duration timeout, int pri
|
|||
boost::tie(protocol, auth, hostname, port, path)
|
||||
= parse_url_components(url, ec);
|
||||
|
||||
if (auth.empty()) auth = auth_;
|
||||
|
||||
m_auth = auth;
|
||||
|
||||
int default_port = protocol == "https" ? 443 : 80;
|
||||
if (port == -1) port = default_port;
|
||||
|
||||
|
@ -204,7 +207,7 @@ void http_connection::get(std::string const& url, time_duration timeout, int pri
|
|||
|
||||
APPEND_FMT("Connection: close\r\n\r\n");
|
||||
|
||||
sendbuffer.assign(request);
|
||||
m_sendbuffer.assign(request);
|
||||
m_url = url;
|
||||
start(hostname, port, timeout, prio
|
||||
, ps, ssl, handle_redirects, bind_addr, m_resolve_flags
|
||||
|
@ -264,7 +267,7 @@ void http_connection::start(std::string const& hostname, int port
|
|||
#if defined TORRENT_ASIO_DEBUGGING
|
||||
add_outstanding_async("http_connection::on_write");
|
||||
#endif
|
||||
async_write(m_sock, asio::buffer(sendbuffer)
|
||||
async_write(m_sock, asio::buffer(m_sendbuffer)
|
||||
, boost::bind(&http_connection::on_write, me, _1));
|
||||
}
|
||||
else
|
||||
|
@ -602,7 +605,7 @@ void http_connection::on_connect(error_code const& e)
|
|||
#if defined TORRENT_ASIO_DEBUGGING
|
||||
add_outstanding_async("http_connection::on_write");
|
||||
#endif
|
||||
async_write(m_sock, asio::buffer(sendbuffer)
|
||||
async_write(m_sock, asio::buffer(m_sendbuffer)
|
||||
, boost::bind(&http_connection::on_write, shared_from_this(), _1));
|
||||
}
|
||||
else if (!m_endpoints.empty() && !m_abort)
|
||||
|
@ -674,7 +677,7 @@ void http_connection::on_write(error_code const& e)
|
|||
|
||||
if (m_abort) return;
|
||||
|
||||
std::string().swap(sendbuffer);
|
||||
std::string().swap(m_sendbuffer);
|
||||
m_recvbuffer.resize(4096);
|
||||
|
||||
int amount_to_read = m_recvbuffer.size() - m_read_pos;
|
||||
|
@ -792,7 +795,7 @@ void http_connection::on_read(error_code const& e
|
|||
|
||||
std::string url = resolve_redirect_location(m_url, location);
|
||||
get(url, m_completion_timeout, m_priority, &m_proxy, m_redirects - 1
|
||||
, m_user_agent, m_bind_addr, m_resolve_flags
|
||||
, m_user_agent, m_bind_addr, m_resolve_flags, m_auth
|
||||
#if TORRENT_USE_I2P
|
||||
, m_i2p_conn
|
||||
#endif
|
||||
|
|
|
@ -82,8 +82,6 @@ namespace libtorrent
|
|||
|
||||
void http_tracker_connection::start()
|
||||
{
|
||||
// TODO: 3 take tracker_req().auth into account. Use it when making the
|
||||
// request
|
||||
std::string url = tracker_req().url;
|
||||
|
||||
if (tracker_req().kind == tracker_request::scrape_request)
|
||||
|
@ -225,6 +223,7 @@ namespace libtorrent
|
|||
, tracker_req().event == tracker_request::stopped
|
||||
? resolver_interface::prefer_cache
|
||||
: resolver_interface::abort_on_shutdown
|
||||
, tracker_req().auth
|
||||
#if TORRENT_USE_I2P
|
||||
, tracker_req().i2pconn
|
||||
#endif
|
||||
|
|
|
@ -866,11 +866,6 @@ namespace libtorrent
|
|||
// the common pieces first, just to make
|
||||
// it more likely for all snubbed peers to
|
||||
// request blocks from the same piece
|
||||
// TODO: 3 this may cause a priority inversion! making a snubbed peer
|
||||
// open up a new piece may cause that piece to become the highest
|
||||
// priority. Unless there is some way to mark pieces as low-priority
|
||||
// this is probably not a good idea. We just want to make all snubbed
|
||||
// peers pick the same common piece.
|
||||
ret |= piece_picker::reverse;
|
||||
}
|
||||
|
||||
|
|
|
@ -4869,6 +4869,7 @@ namespace libtorrent
|
|||
alerts().post_alert(torrent_paused_alert(get_handle()));
|
||||
}
|
||||
|
||||
// TODO: 2 the tracker login feature should probably be deprecated
|
||||
std::string torrent::tracker_login() const
|
||||
{
|
||||
if (m_username.empty() && m_password.empty()) return "";
|
||||
|
|
|
@ -230,7 +230,7 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
// ir all endpoints were filtered by the IP filter, we can't connect
|
||||
// if all endpoints were filtered by the IP filter, we can't connect
|
||||
if (m_endpoints.empty())
|
||||
{
|
||||
fail(error_code(errors::banned_by_ip_filter));
|
||||
|
|
|
@ -669,7 +669,7 @@ void upnp::post(upnp::rootdevice const& d, char const* soap
|
|||
, int(strlen(soap)), d.service_namespace, soap_action
|
||||
, soap);
|
||||
|
||||
d.upnp_connection->sendbuffer = header;
|
||||
d.upnp_connection->m_sendbuffer = header;
|
||||
|
||||
char msg[1024];
|
||||
snprintf(msg, sizeof(msg), "sending: %s", header);
|
||||
|
|
|
@ -104,7 +104,8 @@ void reset_globals()
|
|||
}
|
||||
|
||||
void run_test(std::string const& url, int size, int status, int connected
|
||||
, boost::optional<error_code> ec, proxy_settings const& ps)
|
||||
, boost::optional<error_code> ec, proxy_settings const& ps
|
||||
, std::string const& auth = std::string())
|
||||
{
|
||||
reset_globals();
|
||||
|
||||
|
@ -118,7 +119,8 @@ void run_test(std::string const& url, int size, int status, int connected
|
|||
|
||||
boost::shared_ptr<http_connection> h(new http_connection(ios
|
||||
, res, &::http_handler, true, 1024*1024, &::http_connect_handler));
|
||||
h->get(url, seconds(1), 0, &ps);
|
||||
h->get(url, seconds(1), 0, &ps, 5, "test/user-agent", address_v4::any()
|
||||
, 0, auth);
|
||||
ios.reset();
|
||||
error_code e;
|
||||
ios.run(e);
|
||||
|
@ -166,6 +168,8 @@ void run_suite(std::string const& protocol, proxy_settings ps, int port)
|
|||
run_test(url_base + "test_file", 3216, 200, 1, error_code(), ps);
|
||||
run_test(url_base + "test_file.gz", 3216, 200, 1, error_code(), ps);
|
||||
run_test(url_base + "non-existing-file", -1, 404, 1, err(), ps);
|
||||
run_test(url_base + "password_protected", 3216, 200, 1, error_code(), ps
|
||||
, "testuser:testpass");
|
||||
|
||||
// only run the tests to handle NX_DOMAIN if we have a proper internet
|
||||
// connection that doesn't inject false DNS responses (like Comcast does)
|
||||
|
|
|
@ -4,6 +4,7 @@ import sys
|
|||
import os
|
||||
import ssl
|
||||
import gzip
|
||||
import base64
|
||||
|
||||
chunked_encoding = False
|
||||
keepalive = True
|
||||
|
@ -41,6 +42,21 @@ class http_handler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
|||
|
||||
file_path = os.path.normpath(s.path)
|
||||
|
||||
if s.path == '/password_protected':
|
||||
passed = False
|
||||
if 'Authorization' in s.headers:
|
||||
auth = s.headers['Authorization']
|
||||
passed = auth == 'Basic %s' % base64.b64encode('testuser:testpass')
|
||||
|
||||
if not passed:
|
||||
s.send_response(401)
|
||||
s.send_header("Connection", "close")
|
||||
s.end_headers()
|
||||
return
|
||||
|
||||
s.path = '/test_file'
|
||||
file_path = os.path.normpath('/test_file')
|
||||
|
||||
if s.path == '/redirect':
|
||||
s.send_response(301)
|
||||
s.send_header("Location", "/test_file")
|
||||
|
|
Loading…
Reference in New Issue