Add --socks-proxy parameter to use SOCKS proxy
This allows the user to specify a socks proxy to tunnel the connection through. This feature requires that PySocks is available. If the user tries to use a SOCKS proxy without PySocks available an error is printed and the process is aborted.
This commit is contained in:
parent
725d1c58aa
commit
8e30e9ed17
@ -52,6 +52,7 @@ from .utils import (
|
|||||||
locked_file,
|
locked_file,
|
||||||
make_HTTPS_handler,
|
make_HTTPS_handler,
|
||||||
MaxDownloadsReached,
|
MaxDownloadsReached,
|
||||||
|
OptionalDependencyNotFound,
|
||||||
PagedList,
|
PagedList,
|
||||||
parse_filesize,
|
parse_filesize,
|
||||||
PerRequestProxyHandler,
|
PerRequestProxyHandler,
|
||||||
@ -1953,11 +1954,39 @@ class YoutubeDL(object):
|
|||||||
proxies['https'] = proxies['http']
|
proxies['https'] = proxies['http']
|
||||||
proxy_handler = PerRequestProxyHandler(proxies)
|
proxy_handler = PerRequestProxyHandler(proxies)
|
||||||
|
|
||||||
|
socks_handler = None
|
||||||
|
opts_socks = self.params.get('socksproxy')
|
||||||
|
if opts_socks is not None and opts_socks:
|
||||||
|
# Try to import the dependencies for this feature
|
||||||
|
try:
|
||||||
|
import socks
|
||||||
|
except ImportError:
|
||||||
|
raise OptionalDependencyNotFound(module_name='socks',
|
||||||
|
feature_name='--socks-proxy')
|
||||||
|
try:
|
||||||
|
from sockshandler import SocksiPyHandler
|
||||||
|
except ImportError:
|
||||||
|
raise OptionalDependencyNotFound(module_name='sockshandler',
|
||||||
|
feature_name='--socks-proxy')
|
||||||
|
|
||||||
|
pair = opts_socks.split(':')
|
||||||
|
if len(pair) == 2:
|
||||||
|
socks_handler = SocksiPyHandler(socks.PROXY_TYPE_SOCKS5,
|
||||||
|
pair[0],
|
||||||
|
int(pair[1]))
|
||||||
|
else:
|
||||||
|
socks_handler = SocksiPyHandler(socks.PROXY_TYPE_SOCKS5,
|
||||||
|
'localhost',
|
||||||
|
int(pair[0]))
|
||||||
|
|
||||||
debuglevel = 1 if self.params.get('debug_printtraffic') else 0
|
debuglevel = 1 if self.params.get('debug_printtraffic') else 0
|
||||||
https_handler = make_HTTPS_handler(self.params, debuglevel=debuglevel)
|
https_handler = make_HTTPS_handler(self.params, debuglevel=debuglevel)
|
||||||
ydlh = YoutubeDLHandler(self.params, debuglevel=debuglevel)
|
ydlh = YoutubeDLHandler(self.params, debuglevel=debuglevel)
|
||||||
opener = compat_urllib_request.build_opener(
|
proxy_list = []
|
||||||
proxy_handler, https_handler, cookie_processor, ydlh)
|
if socks_handler:
|
||||||
|
proxy_list.append(socks_handler)
|
||||||
|
proxy_list += [proxy_handler, https_handler, cookie_processor, ydlh]
|
||||||
|
opener = compat_urllib_request.build_opener(*proxy_list)
|
||||||
|
|
||||||
# Delete the default user-agent header, which would otherwise apply in
|
# Delete the default user-agent header, which would otherwise apply in
|
||||||
# cases where our custom HTTP handler doesn't come into play
|
# cases where our custom HTTP handler doesn't come into play
|
||||||
|
@ -29,6 +29,7 @@ from .utils import (
|
|||||||
DownloadError,
|
DownloadError,
|
||||||
match_filter_func,
|
match_filter_func,
|
||||||
MaxDownloadsReached,
|
MaxDownloadsReached,
|
||||||
|
OptionalDependencyNotFound,
|
||||||
preferredencoding,
|
preferredencoding,
|
||||||
read_batch_urls,
|
read_batch_urls,
|
||||||
SameFileError,
|
SameFileError,
|
||||||
@ -346,6 +347,7 @@ def _real_main(argv=None):
|
|||||||
'nocheckcertificate': opts.no_check_certificate,
|
'nocheckcertificate': opts.no_check_certificate,
|
||||||
'prefer_insecure': opts.prefer_insecure,
|
'prefer_insecure': opts.prefer_insecure,
|
||||||
'proxy': opts.proxy,
|
'proxy': opts.proxy,
|
||||||
|
'socksproxy': opts.socksproxy,
|
||||||
'socket_timeout': opts.socket_timeout,
|
'socket_timeout': opts.socket_timeout,
|
||||||
'bidi_workaround': opts.bidi_workaround,
|
'bidi_workaround': opts.bidi_workaround,
|
||||||
'debug_printtraffic': opts.debug_printtraffic,
|
'debug_printtraffic': opts.debug_printtraffic,
|
||||||
@ -414,5 +416,7 @@ def main(argv=None):
|
|||||||
sys.exit('ERROR: fixed output name but more than one file to download')
|
sys.exit('ERROR: fixed output name but more than one file to download')
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
sys.exit('\nERROR: Interrupted by user')
|
sys.exit('\nERROR: Interrupted by user')
|
||||||
|
except OptionalDependencyNotFound as e:
|
||||||
|
sys.exit(str(e))
|
||||||
|
|
||||||
__all__ = ['main', 'YoutubeDL', 'gen_extractors', 'list_extractors']
|
__all__ = ['main', 'YoutubeDL', 'gen_extractors', 'list_extractors']
|
||||||
|
@ -181,6 +181,11 @@ def parseOpts(overrideArguments=None):
|
|||||||
'--proxy', dest='proxy',
|
'--proxy', dest='proxy',
|
||||||
default=None, metavar='URL',
|
default=None, metavar='URL',
|
||||||
help='Use the specified HTTP/HTTPS proxy. Pass in an empty string (--proxy "") for direct connection')
|
help='Use the specified HTTP/HTTPS proxy. Pass in an empty string (--proxy "") for direct connection')
|
||||||
|
network.add_option(
|
||||||
|
'--socks-proxy', dest='socksproxy', default=None, metavar='URL',
|
||||||
|
help=('Use the specified socks proxy. Pass in an empty string '
|
||||||
|
'(--socks-proxy "") for direct connection. This feature requires'
|
||||||
|
'the pysocks library.'))
|
||||||
network.add_option(
|
network.add_option(
|
||||||
'--socket-timeout',
|
'--socket-timeout',
|
||||||
dest='socket_timeout', type=float, default=None, metavar='SECONDS',
|
dest='socket_timeout', type=float, default=None, metavar='SECONDS',
|
||||||
|
@ -586,6 +586,23 @@ class ContentTooShortError(Exception):
|
|||||||
self.expected = expected
|
self.expected = expected
|
||||||
|
|
||||||
|
|
||||||
|
class OptionalDependencyNotFound(Exception):
|
||||||
|
"""Optional dependency not found
|
||||||
|
|
||||||
|
This exception may be raised by YoutubeDL, when the user tries to use a
|
||||||
|
feature that requires an optional dependency which could not be found.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, module_name, feature_name):
|
||||||
|
self.module_name = str(module_name)
|
||||||
|
self.feature_name = str(feature_name)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return ("Unable to use '{feature}', because it depends on '{module}' "
|
||||||
|
"which was not found.").format(
|
||||||
|
feature=self.feature_name, module=self.module_name)
|
||||||
|
|
||||||
|
|
||||||
def _create_http_connection(ydl_handler, http_class, is_https, *args, **kwargs):
|
def _create_http_connection(ydl_handler, http_class, is_https, *args, **kwargs):
|
||||||
# Working around python 2 bug (see http://bugs.python.org/issue17849) by limiting
|
# Working around python 2 bug (see http://bugs.python.org/issue17849) by limiting
|
||||||
# expected HTTP responses to meet HTTP/1.0 or later (see also
|
# expected HTTP responses to meet HTTP/1.0 or later (see also
|
||||||
|
Loading…
x
Reference in New Issue
Block a user