2009-08-18 16 views
6

मैं पाइथन ftplib में एक एफ़टीपी क्लाइंट विकसित कर रहा हूं। मैं प्रॉक्सी समर्थन कैसे जोड़ूं (अधिकांश एफ़टीपी ऐप्स जो मैंने देखा है) है? मैं विशेष रूप से सॉक्स प्रॉक्सी के बारे में सोच रहा हूं, लेकिन अन्य प्रकार भी ... एफ़टीपी, HTTP (क्या एफ़टीपी प्रोग्राम के साथ HTTP प्रॉक्सी का उपयोग करना भी संभव है?)पायथन एफ़टीपी एप्लिकेशन में प्रॉक्सी

कोई विचार यह कैसे करना है?

उत्तर

1

मानक मॉड्यूल ftplib प्रॉक्सी का समर्थन नहीं करता है। ऐसा लगता है कि ftplib का अपना स्वयं का अनुकूलित संस्करण लिखना एकमात्र समाधान है।

6

this स्रोत के अनुसार।

प्रॉक्सी पर निर्भर करता है, लेकिन प्रॉक्सी पर ftp करने के लिए एक सामान्य विधि है, तो गंतव्य सर्वर के लिए उपयोगकर्ता नाम और पासवर्ड का उपयोग करें।

उदा।

Server address: proxyserver (or open proxyserver from with ftp) 
User:   [email protected] 
Password:  password 

अजगर कोड में: ftp.example.com के लिए

from ftplib import FTP 
site = FTP('my_proxy') 
site.set_debuglevel(1) 
msg = site.login('[email protected]', 'password') 
site.cwd('/pub') 
+0

ऊपर जवाब में लिंक है 404. मतलब हो सकता है यह एक: http : //mail.python.org/pipermail/python-list/2004- अक्टूबर/863602.html – AndrewR

+3

"अज्ञात ftp.download.com" भाग शुद्ध कथा है। किसी भी सर्वर द्वारा किसी भी सर्वर द्वारा लागू/समर्थित किसी भी आरएफसी या में इसका कुछ भी उल्लेख नहीं किया गया है, जहां तक ​​मुझे पता है। मूल रूप से, एफ़टीपी प्रोटोकॉल प्रॉक्सीइंग का समर्थन नहीं करता है। AFAIK, एफ़टीपी प्रॉक्सी करने का एकमात्र तरीका एक सॉक्स का उपयोग करके है, जिस स्थिति में क्लाइंट को सॉक्स से कनेक्ट करना होता है और बाद वाले को निर्देश दिया जाना चाहिए कि वास्तविक FTP सर्वर क्या है। –

+1

यह उत्तर मुझे एक असली बड़ा सिरदर्द हल करता है। धन्यवाद!!! – dgg32

4

आप urllib2 में ProxyHandler उपयोग कर सकते हैं।

ph = urllib2.ProxyHandler({ 'ftp' : proxy_server_url }) 
server= urllib2.build_opener(ph) 
+0

उदाहरण में "urlli2" का टाइपो संपादित नहीं किया जा सकता है क्योंकि "संपादन कम से कम 6 वर्ण होना चाहिए"। – HongboZhu

3

मैं एक ही समस्या थी और (नहीं URLlib2 के साथ अपने सभी स्क्रिप्ट के पुनर्लेखन के लिए) ftplib मॉड्यूल का उपयोग करने के लिए आवश्यक।

मैंने एक स्क्रिप्ट लिखने में कामयाब रहा है जो सॉकेट परत (ftplib द्वारा उपयोग किया जाता है) पर पारदर्शी HTTP सुरंग स्थापित करता है।

अब, मैं HTTP पर पारदर्शी रूप से कर सकता हूं! निर्मित सॉकेट पुस्तकालय पैच की जा रही निश्चित रूप से हर किसी के लिए एक विकल्प नहीं होगा http://code.activestate.com/recipes/577643-transparent-http-tunnel-for-python-sockets-to-be-u/

0

, लेकिन मेरे समाधान जब होस्ट नाम एक श्वेत सूची से मेल खाता है एक HTTP प्रॉक्सी का उपयोग करने के socket.create_connection() पैच करने के लिए किया गया था:

आप इसे वहाँ प्राप्त कर सकते हैं:

from base64 import b64encode 
from functools import wraps 
import socket 

_real_create_connection = socket.create_connection 
_proxied_hostnames = {} # hostname: (proxy_host, proxy_port, proxy_auth) 


def register_proxy (host, proxy_host, proxy_port, proxy_username=None, proxy_password=None): 
    proxy_auth = None 
    if proxy_username is not None or proxy_password is not None: 
     proxy_auth = b64encode('{}:{}'.format(proxy_username or '', proxy_password or '')) 
    _proxied_hostnames[host] = (proxy_host, proxy_port, proxy_auth) 


@wraps(_real_create_connection) 
def create_connection (address, *args, **kwds): 
    host, port = address 
    if host not in _proxied_hostnames: 
     return _real_create_connection(address, *args, **kwds) 

    proxy_host, proxy_port, proxy_auth = _proxied_hostnames[host] 
    conn = _real_create_connection((proxy_host, proxy_port), *args, **kwds) 
    try: 
     conn.send('CONNECT {host}:{port} HTTP/1.1\r\nHost: {host}:{port}\r\n{auth_header}\r\n'.format(
      host=host, port=port, 
      auth_header=('Proxy-Authorization: basic {}\r\n'.format(proxy_auth) if proxy_auth else '') 
     )) 
     response = '' 
     while not response.endswith('\r\n\r\n'): 
      response += conn.recv(4096) 
     if response.split()[1] != '200': 
      raise socket.error('CONNECT failed: {}'.format(response.strip())) 
    except socket.error: 
     conn.close() 
     raise 

    return conn 


socket.create_connection = create_connection 

मैं भी ftplib.FTP का एक उपवर्ग कि hostPASV और EPSV एफ़टीपी आदेशों द्वारा दिया पर ध्यान नहीं देता बनाने के लिए किया था। उदाहरण उपयोग:

from ftplib import FTP 
import paramiko # For SFTP 
from proxied_socket import register_proxy 

class FTPIgnoreHost (FTP): 
    def makepasv (self): 
     # Ignore the host returned by PASV or EPSV commands (only use the port). 
     return self.host, FTP.makepasv(self)[1] 

register_proxy('ftp.example.com', 'proxy.example.com', 3128, 'proxy_username', 'proxy_password') 

ftp_connection = FTP('ftp.example.com', 'ftp_username', 'ftp_password') 

ssh = paramiko.SSHClient() 
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # If you don't care about security. 
ssh.connect('ftp.example.com', username='sftp_username', password='sftp_password') 
sftp_connection = ssh.open_sftp() 
0

यहाँ requests, एक विद्रूप प्रॉक्सी के साथ परीक्षण का उपयोग कर वैकल्पिक हल है कि सुरंग के संपर्क में रहें समर्थन नहीं करता है:

def ftp_fetch_file_through_http_proxy(host, user, password, remote_filepath, http_proxy, output_filepath): 
    """ 
    This function let us to make a FTP RETR query through a HTTP proxy that does NOT support CONNECT tunneling. 
    It is equivalent to: curl -x $HTTP_PROXY --user $USER:$PASSWORD ftp://$FTP_HOST/path/to/file 
    It returns the 'Last-Modified' HTTP header value from the response. 

    More precisely, this function sends the following HTTP request to $HTTP_PROXY: 
     GET ftp://$USER:[email protected]$FTP_HOST/path/to/file HTTP/1.1 
    Note that in doing so, the host in the request line does NOT match the host we send this packet to. 

    Python `requests` lib does not let us easily "cheat" like this. 
    In order to achieve what we want, we need: 
    - to mock urllib3.poolmanager.parse_url so that it returns a (host,port) pair indicating to send the request to the proxy 
    - to register a connection adapter to the 'ftp://' prefix. This is basically a HTTP adapter but it uses the FULL url of 
    the resource to build the request line, instead of only its relative path. 
    """ 
    url = 'ftp://{}:{}@{}/{}'.format(user, password, host, remote_filepath) 
    proxy_host, proxy_port = http_proxy.split(':') 

    def parse_url_mock(url): 
     return requests.packages.urllib3.util.url.parse_url(url)._replace(host=proxy_host, port=proxy_port, scheme='http') 

    with open(output_filepath, 'w+b') as output_file, patch('requests.packages.urllib3.poolmanager.parse_url', new=parse_url_mock): 
     session = requests.session() 
     session.mount('ftp://', FTPWrappedInFTPAdapter()) 
     response = session.get(url) 
     response.raise_for_status() 
     output_file.write(response.content) 
     return response.headers['last-modified'] 


class FTPWrappedInFTPAdapter(requests.adapters.HTTPAdapter): 
    def request_url(self, request, _): 
     return request.url 
संबंधित मुद्दे