прокси на питоне (помогите найти ошибку)

Модератор: Модераторы разделов

Аватара пользователя
nadge
Сообщения: 1519
ОС: ArchLinux, Ubuntu 10.10

прокси на питоне

Сообщение nadge »

Пишу маленький прокси-сервер на питоне:

Код:

#! /usr/bin/env python # -*- coding: utf-8 -*- from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer from SocketServer import ThreadingMixIn import urllib2, sys, re class ProxyHandler( BaseHTTPRequestHandler ): def do_HEAD( self ): print "HEAD" def do_POST( self ): print "HEAD" def do_GET( self ): cut_headers = ( 'host', 'proxy-connection', 'accept-encoding' ) # cut_headers = ( 'cache-control', 'host', 'proxy-connection', 'pragma', 'accept-encoding' ) headers_get = [] for x in self.headers.dict.keys(): if x not in cut_headers: headers_get.append( ( x, self.headers.dict[x] ), ) opener = urllib2.build_opener() opener.addheaders = ( headers_get ) msg = opener.open( self.requestline.split()[1] ) msg_body = msg.read() msg.close() self.send_response( 200 ) for x in msg.headers.dict.keys(): self.send_header( x, msg.headers.dict[x] ) self.end_headers() self.wfile.write( msg_body ) pass class ThreadedHTTPServer( ThreadingMixIn, HTTPServer ): daemon_threads = True if __name__ == '__main__': proxy = ThreadedHTTPServer( ( 'localhost', 19277 ), ProxyHandler ) try: proxy.serve_forever() except KeyboardInterrupt: pass proxy.server_close() pass


Это впринципе работает, но не везде. В частности, браузеры (опера, хром) прекрасно открывают главную страницу яндекса и гугла, но не открывают вконтакте и хабрахабр. В то же время, wget прекрасно справляется с этим.


Собственно, где ошибка?

Спасибо сказали:
bl00dl1nes
Сообщения: 115
ОС: ubuntu

Re: прокси на питоне

Сообщение bl00dl1nes »

работает неплохо, в том числе и вконтакте с хабром, только отображает пустой фон при получении ответов типа 404, 302 (получил при попытке посещения локалхоста и этого сайта. так же при последнем такой еррор: HTTPError: HTTP Error 302: The HTTP server returned a redirect error that would lead to an infinite loop. The last 30x error message was: Moved Temporarily )
Firefox 3.6.13

p.s. Так же при попытке отправить сообщение предложил сохранить index.php :)
Спасибо сказали:
frp
Сообщения: 1445
ОС: Debian Squeeze

Re: прокси на питоне

Сообщение frp »

bl00dl1nes писал(а):
08.01.2011 16:57
HTTPError: HTTP Error 302: The HTTP server returned a redirect error that would lead to an infinite loop.

Это обычно возникает при редиректе на самого себя.
Спасибо сказали:
Аватара пользователя
nadge
Сообщения: 1519
ОС: ArchLinux, Ubuntu 10.10

Re: прокси на питоне

Сообщение nadge »

Благодарю за тестирование и подсказки. После продолжительной отладки я решил переписать функцию с нуля, использую httplib вместо urllib2.

Теперь работает контакт, карты гугла и яндекса, ну и другие сайты, которые успел потестировать. НО, не работает хабр. ОН нормально открывается, но там нет CSS разметки. Проверено в опере и midori.

Код:

#! /usr/bin/env python # -*- coding: utf-8 -*- from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer from SocketServer import ThreadingMixIn import urllib2, sys, re, httplib, urlparse class ProxyHandler( BaseHTTPRequestHandler ): def do_HEAD( self ): print "HEAD" def do_POST( self ): print "POST" def do_GET( self ): requested_url = self.requestline.split()[1] parsed_url = urlparse.urlsplit( requested_url ) cutted_url = urlparse.urlunsplit( ( '', '', parsed_url.path, parsed_url.query, '' ) ) port = 80 if None == parsed_url.port else parsed_url.port req_headers = {} if 'accept' in self.headers.dict: req_headers['accept'] = self.headers.dict['accept'] if 'accept-charset' in self.headers.dict: req_headers['accept-charset'] = self.headers.dict['accept-charset'] if 'accept-language' in self.headers.dict: req_headers['accept-language'] = self.headers.dict['accept-language'] #if 'accept' in self.headers.dict: # req_headers['accept'] = self.headers.dict['accept'] req_headers['cache-control'] = 'no-cache' req_headers['pragma'] = 'no-cache' req_headers['user-agent'] = 'Mozilla/5.0' if 'referer' in self.headers.dict: req_headers['referer'] = self.headers.dict['referer'] if 'host' in self.headers.dict: req_headers['host'] = self.headers.dict['host'] for x in self.headers.dict.keys(): if len( x ) >= 6 and x[:6] == 'cookie': req_headers[x] = self.headers.dict[x] conn = httplib.HTTPConnection( parsed_url.hostname, port ) conn.request( 'GET', cutted_url, headers = req_headers ) response = conn.getresponse() #print requested_url + ' - ' + str( response.status ) if response.status not in ( 200, 302, 301, 204 ): print requested_url + ' - ' + str( response.status ) print self.headers.headers print response.msg.headers self.send_response( response.status ) self.end_headers() self.connection.close() conn.close() return self.send_response( response.status ) resp_headers = [] if 'content-type' in response.msg.dict: resp_headers.append( ( 'content-type', response.msg.dict['content-type'] ) ) if 'date' in response.msg.dict: resp_headers.append( ( 'date', response.msg.dict['date'] ) ) if 'set-cookie' in response.msg.dict: resp_headers.append( ( 'set-cookie', response.msg.dict['set-cookie'] ) ) if 'location' in response.msg.dict: resp_headers.append( ( 'location', response.msg.dict['location'] ) ) for x in resp_headers: self.send_header( x[0], x[1] ) self.end_headers() html = response.read() self.wfile.write( html ) self.connection.close() conn.close() pass class ThreadedHTTPServer( ThreadingMixIn, HTTPServer ): daemon_threads = True if __name__ == '__main__': proxy = ThreadedHTTPServer( ( 'localhost', 19277 ), ProxyHandler ) try: proxy.serve_forever() except KeyboardInterrupt: pass proxy.server_close() pass


З.Ы. Пока более-менее готов только GET запрос, к остальным сейчас приступлю.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Спасибо сказали:
Аватара пользователя
nadge
Сообщения: 1519
ОС: ArchLinux, Ubuntu 10.10

Re: прокси на питоне

Сообщение nadge »

После долгого копания в коде вроде бы все заработало...


З.Ы. Скрипт почти готов, функциональность близка к полноценному прокси. Думаю опубликовать его тут (под BSD) - авось кому пригодится.
Спасибо сказали: