Skip to content

Instantly share code, notes, and snippets.

@mnacharov
Forked from anonymous/gist:06e0bd519490c8f03404
Last active October 2, 2015 10:37
Show Gist options
  • Save mnacharov/44902e9eef53498f819a to your computer and use it in GitHub Desktop.
Save mnacharov/44902e9eef53498f819a to your computer and use it in GitHub Desktop.
# coding=utf8
# 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 — обязательно
# * в случае, если не хватает каких-то данных, следует опираться на здравый смысл
#
# Если задача кажется слишом простой, можно добавить следующее:
# * параметры командной строки (порт, хост, сайт, отличный от хабра и т.п.)
# * после старта локального сервера автоматически запускается браузер с открытой
# обработанной™ главной страницей
from HTMLParser import HTMLParser
from StringIO import StringIO
import argparse
import mimetypes
import re
from urlparse import urljoin
from flask import Flask, request, Response
import requests
mimetypes.init()
app = Flask(__name__)
class TrademarkHTMLParser(HTMLParser):
def __init__(self, length, symbol):
self.result = StringIO()
self._length = length
self._symbol = symbol
# чтобы не менять контент скриптов и стилей
self._replace = True
HTMLParser.__init__(self)
def handle_starttag(self, tag, attrs):
if tag in ('script', 'style'):
self._replace = False
self.result.write(u'<{0} {1}>'.format(tag, u' '.join((u'{0}="{1}"'.format(key, val) if val else key for key, val in attrs)) if attrs else ''))
def handle_endtag(self, tag):
if tag in ('script', 'style'):
self._replace = True
self.result.write('</{0}>'.format(tag))
def handle_data(self, data):
if self._replace:
data = re.sub(ur'(?<=[\s>«(,.])([a-zA-Zа-яА-Я]{%d})(?=[<»),.\s])' % self._length,
ur'\1' + self._symbol, data)
self.result.write(data)
def handle_decl(self, data):
self.result.write('<!{}>'.format(data))
class ContentChanger(object):
length = 6
reverse = False
site = 'http://habrahabr.ru/'
symbol = '™'
def __init__(self, reverse_url=None):
self._url = reverse_url
def get_content(self, path):
return requests.get(urljoin(self.site, path)).content
def change_content(self, content):
if content.strip().startswith('<!DOCTYPE'):
content = content.decode('utf8')
if self.reverse:
# пускаем всё через нас
content = content.replace(self.site, self._url)
# добавляем ™
parser = TrademarkHTMLParser(self.length, self.symbol)
parser.feed(content)
return parser.result.getvalue()
return content
def serve(self, path):
content_type = mimetypes.types_map.get('.' + path.rsplit('.', 1)[-1], 'text/html')
return Response(self.change_content(self.get_content(path)), content_type=content_type)
@app.route("/", defaults={"path": ""})
@app.route("/<path:path>")
def hello(path):
return ContentChanger(request.host_url).serve(path)
def main():
parser = argparse.ArgumentParser(description=u'Запускает трейдмарк прокси-сервер для сайта')
parser.add_argument('host', metavar='host', nargs='?', type=str, default='127.0.0.1',
help=u'Хост на котором будет запущен прокси', )
parser.add_argument('port', metavar='port', nargs='?', type=int, default=8232,
help=u'Номер порта на котором будет запущен прокси')
parser.add_argument('--site', '-S', metavar='site', type=str, default='http://habrahabr.ru/',
help=u'Сайт который будет показан')
parser.add_argument('--length', '-L', metavar='length', type=int, default=6,
help=u'Длина слова для которого добавлить symbol')
parser.add_argument('--symbol', '-Y', metavar='symbol', type=unicode, default=u'™',
help=u'Симвод который будет добавлен')
parser.add_argument('-D', '--deep', dest='deep', action='store_const', const=True, default=False,
help=u'Оставаться в пределах прокси при переходе по ссылкам')
parser.add_argument('-R', '--run', dest='browser', action='store_const', const=True, default=False,
help=u'Открыть браузер')
args = parser.parse_args()
ContentChanger.length = args.length
ContentChanger.reverse = args.deep
ContentChanger.site = args.site
ContentChanger.symbol = args.symbol
if args.browser:
import webbrowser
webbrowser.open_new_tab('http://{}:{}'.format(args.host, args.port))
app.run(args.host, args.port)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment