Skip to content

Instantly share code, notes, and snippets.

@Xifax
Created September 21, 2015 09:25
Show Gist options
  • Save Xifax/66a243029bfd66d7aed7 to your computer and use it in GitHub Desktop.
Save Xifax/66a243029bfd66d7aed7 to your computer and use it in GitHub Desktop.
Habraproxy, решение задачки.
#!/usr/bin/env python
# coding: utf-8
# Author: Artiom Basenko
# Email: demi.log@gmail.com
# Python Version: 2.7.10
# 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 — обязательно
# * в случае, если не хватает каких-то данных, следует опираться на здравый смысл
#
# Если задача кажется слишом простой, можно добавить следующее:
# * параметры командной строки (порт, хост, сайт, отличный от хабра и т.п.)
# * после старта локального сервера автоматически запускается браузер с открытой
# обработанной™ главной страницей
import webbrowser
import urlparse
import sys
from threading import Timer
import click
import requests
from bs4 import BeautifulSoup
from bottle import route, run
TM_POSTFIX_HTML = u'™'
WORD_LENGTH = 6
class ProxyApp:
"""Simple configurable proxy bottle server."""
def __init__(self, url, port):
"""Set url, port and routes"""
self.url = url
self.port = port
# Setup routes
route('/')(self.root)
route('/<path:path>')(self.sub)
def trademark(self, response):
"""Trademark all the 6 letter words."""
if response.status_code == requests.codes.ok:
# Update hrefs to point to localhost:port
soup = BeautifulSoup(response.content, 'html.parser')
for a in soup.find_all('a'):
try:
domain = urlparse.urlparse(self.url).netloc
if domain in a['href']:
a['href'] = a['href'].replace(
domain, u'localhost:{0:d}'.format(self.port))
except KeyError:
pass
# Urgh...
encoding = response.encoding if response.encoding else 'utf-8'
contents = unicode(str(soup), encoding)
# Find all 6 letter words (try to ignore scripts and styles)
words = []
for div in soup.find_all('div'):
for word in div.text.split(u' '):
if len(word) == 6:
words.append(word)
# Trademark EVERYTHING
for word in set(words):
contents = contents.replace(word, word + TM_POSTFIX_HTML)
return contents
# On 404 and others
else:
return 'Cannot proxy that!'
def root(self):
"""Process base route."""
return self.trademark(requests.get(self.url))
def sub(self, path):
"""Process all the sub-routes."""
return self.trademark(
requests.get(urlparse.urljoin(self.url, path)))
def run(self):
"""Run bottle server."""
run(host='localhost', port=self.port)
@click.command()
@click.option('--url', default='http://habrahabr.ru',
prompt='Url to proxy', help='Url to process.')
@click.option('--port', default=8232,
prompt='Port to serve on', help='Port to listen on.')
@click.option('--browse', is_flag=True, default=False,
prompt='Launch default browser?', help='Should open browser.')
def serve(url, port, browse):
"""
Reverse-proxy provided url and modify page contents in an amusing manner."""
# Check if provided url is valid
if not urlparse.urlparse(url).netloc:
sys.exit('Invalid url. Please specify something like http://yada.yada')
# Launch browser?
if browse:
t = Timer(1.0, lambda: webbrowser.open_new_tab(
'http://localhost:{0:d}'.format(port)))
t.start()
# Run proxy server
ProxyApp(url, port).run()
if __name__ == '__main__':
serve()
bottle==0.12.8
click==5.1
requests==2.7.0
beautifulsoup4==4.4.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment