This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# habraproxy.py — это простейший http-прокси-сервер, запускаемый локально | |
# (порт на ваше усмотрение), который показывает содержимое страниц Хабра. | |
# С одним исключением: после каждого слова из шести букв должен стоять | |
# значок «™». Примерно так: | |
# | |
# http://habrahabr.ru/company/yandex/blog/258673/ | |
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
# Сейчас на фоне уязвимости Logjam все в индустрии в очередной раз обсуждают | |
# проблемы и особенности TLS. Я хочу воспользоваться этой возможностью, чтобы | |
# поговорить об одной из них, а именно — о настройке ciphersiutes. | |
# | |
# http://127.0.0.1:8232/company/yandex/blog/258673/ | |
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
# Сейчас™ на фоне уязвимости Logjam™ все в индустрии в очередной раз | |
# обсуждают проблемы и особенности TLS. Я хочу воспользоваться этой | |
# возможностью, чтобы поговорить об одной из них, а именно™ — о | |
# настройке ciphersiutes. | |
# | |
# Условия: | |
# * Python 2.x | |
# * можно использовать любые общедоступные библиотеки, которые сочтёте | |
# нужным | |
# * чем меньше кода, тем лучше. PEP8 — обязательно | |
# * в случае, если не хватает каких-то данных, следует опираться на здравый | |
# смысл | |
# | |
# Если задача кажется слишом простой, можно добавить следующее: | |
# * параметры командной строки (порт, хост, сайт, отличный от хабра и т.п.) | |
# * после старта локального сервера автоматически запускается браузер с | |
# открытой обработанной™ главной страницей | |
# $ cat requirements.txt | |
# backports-abc==0.4 | |
# backports.ssl-match-hostname==3.5.0.1 | |
# beautifulsoup4==4.4.1 | |
# certifi==2016.2.28 | |
# singledispatch==3.4.0.3 | |
# six==1.10.0 | |
# tornado==4.3 | |
# wheel==0.24.0 | |
# $ cat habraproxy.py | |
# -*- coding: utf-8 -*- | |
import argparse | |
import webbrowser | |
import re | |
from bs4 import BeautifulSoup, Comment | |
from tornado import httpclient | |
import tornado.ioloop | |
import tornado.web | |
class MainHandler(tornado.web.RequestHandler): | |
def initialize(self, site, live, host, port): | |
self.site = site | |
self.live = live | |
self.host = host | |
self.port = port | |
def get_html(self, path): | |
html = False | |
url = '{0}/{1}'.format(self.site, path) | |
url = re.sub('/+', '/', url).replace(':/', '://') | |
http_client = httpclient.HTTPClient() | |
try: | |
response = http_client.fetch(url) | |
html = response.body | |
except httpclient.HTTPError as e: | |
print('Error: ' + str(e)) | |
except Exception as e: | |
print('Error: ' + str(e)) | |
http_client.close() | |
return html | |
def transform_text(self, soup): | |
for el in soup.find_all(text=True): | |
if el.parent.name in ['[document]', | |
'head', 'title', | |
'style', 'script']: | |
continue | |
elif isinstance(el, Comment): | |
continue | |
el.replaceWith(re.sub(ur'\b(\w{6})\b', ur'\1™', el, flags=re.U)) | |
def rewrite_links(self, soup): | |
if self.live == 'y': | |
for el in soup.find_all('a'): | |
if el.get('href'): | |
el['href'] = el['href'].replace( | |
self.site, | |
'http://{0}:{1}'.format(self.host, self.port) | |
) | |
def get(self, path): | |
html = self.get_html(path) | |
if html: | |
soup = BeautifulSoup(html, 'html.parser') | |
self.transform_text(soup) | |
self.rewrite_links(soup) | |
self.write(soup.prettify()) | |
def make_app(args): | |
return tornado.web.Application([ | |
(r'/(.*)', MainHandler, dict( | |
site=args.site, live=args.live, host=args.host, port=args.port | |
)), | |
]) | |
def start_proxy(args): | |
app = make_app(args) | |
app.listen(args.port, address=args.host) | |
tornado.ioloop.IOLoop.current().start() | |
def start_browser(args): | |
webbrowser.open('http://{0}:{1}'.format(args.host, args.port)) | |
def init_args(): | |
parser = argparse.ArgumentParser(description='Light Proxy.') | |
parser.add_argument('--host', dest='host', type=str, | |
default='localhost', | |
help='Host (eq: localhost).') | |
parser.add_argument('--port', dest='port', type=int, | |
default=8000, | |
help='Port (eq: 8000).') | |
parser.add_argument('--site', dest='site', type=str, | |
default='https://habrahabr.ru', | |
help='Site (eq: https://habrahabr.ru).') | |
parser.add_argument('--live', dest='live', type=str, | |
default='y', | |
help='Live mode (rewrite links to open with proxy) ' | |
'Y/n.') | |
args = parser.parse_args() | |
return args | |
def main(): | |
args = init_args() | |
start_browser(args) | |
start_proxy(args) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment