Skip to content

Instantly share code, notes, and snippets.

@itcrab
Forked from anonymous/habraproxy.py
Last active April 18, 2016 19:10
# -*- 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