Wie schreibt man einen web-proxy in Python
Ich versuche zu schreiben, ein web-proxy in python. Das Ziel ist der Besuch einer url wie: http://proxyurl/http://anothersite.com/
und sehen, dass er Inhalt http://anothersite.com
wie Sie normalerweise würde. Ich habe mich anständig weit durch den Missbrauch der Anfragen, die Bibliothek, aber das ist nicht wirklich die beabsichtigte Verwendung des Anfragen-framework. Ich habe geschrieben proxies mit twisted vor, aber ich bin mir nicht sicher, wie Sie dieses in das, was ich versuche zu tun. Hier ist, wo ich bin so weit...
import os
import urlparse
import requests
import tornado.ioloop
import tornado.web
from tornado import template
ROOT = os.path.dirname(os.path.abspath(__file__))
path = lambda *a: os.path.join(ROOT, *a)
loader = template.Loader(path(ROOT, 'templates'))
class ProxyHandler(tornado.web.RequestHandler):
def get(self, slug):
if slug.startswith("http://") or slug.startswith("https://"):
if self.get_argument("start", None) == "true":
parsed = urlparse.urlparse(slug)
self.set_cookie("scheme", value=parsed.scheme)
self.set_cookie("netloc", value=parsed.netloc)
self.set_cookie("urlpath", value=parsed.path)
#external resource
else:
response = requests.get(slug)
headers = response.headers
if 'content-type' in headers:
self.set_header('Content-type', headers['content-type'])
if 'length' in headers:
self.set_header('length', headers['length'])
for block in response.iter_content(1024):
self.write(block)
self.finish()
return
else:
#absolute
if slug.startswith('/'):
slug = "{scheme}://{netloc}{original_slug}".format(
scheme=self.get_cookie('scheme'),
netloc=self.get_cookie('netloc'),
original_slug=slug,
)
#relative
else:
slug = "{scheme}://{netloc}{path}{original_slug}".format(
scheme=self.get_cookie('scheme'),
netloc=self.get_cookie('netloc'),
path=self.get_cookie('urlpath'),
original_slug=slug,
)
response = requests.get(slug)
#get the headers
headers = response.headers
#get doctype
doctype = None
if '<!doctype' in response.content.lower()[:9]:
doctype = response.content[:response.content.find('>')+1]
if 'content-type' in headers:
self.set_header('Content-type', headers['content-type'])
if 'length' in headers:
self.set_header('length', headers['length'])
self.write(response.content)
application = tornado.web.Application([
(r"/(.+)", ProxyHandler),
])
if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
Nur ein Hinweis, ich ein cookie gesetzt, um die Erhaltung der Regelung, netloc und urlpath, wenn die dort anfangen=true in den querystring. Auf diese Weise wird jeder relativen oder einen absoluten link, dann hat der proxy verwendet die Cookies aus, beheben Sie die vollständige url.
Mit diesem code, wenn Sie gehen, um http://localhost:8888/http://espn.com/?start=true
Sie werden sehen, die Inhalte von ESPN. Jedoch, auf der folgenden Website, es funktioniert überhaupt nicht: http://www.bottegaveneta.com/us/shop/. Meine Frage ist, was ist der beste Weg, dies zu tun? Ist der Strom Weg, ich bin Umsetzung dieses robuste oder gibt es einige große Fallstricke, die es zu tun auf diese Weise? Wenn es richtig ist, warum sind gewisse Seiten wie die, die ich darauf hingewiesen, nicht zu arbeiten?
Danke für jede Hilfe.
- Bottega Veneta lässt Sie nicht auf Ressourcen zugreifen, direkt. E. g, versuchen Sie zu schlagen, bottegaveneta.com/us/shop/css/bottegaveneta/form.css — bekomme ich eine HTML-Seite 404.
- Ich vermute, es ist zu tun mit der HTTP-Referrer. Sie können versuchen, dass als gut.
- Oh, du meinst den referer? (en.wikipedia.org/wiki/HTTP_referer#Origin_of_the_term_referer)
- Anstatt herauszufinden, was die fehlenden header müssen Sie gehen durch eine defekte Seite zu einem Zeitpunkt, warum nicht einfach Durchlaufen alle Header außer eine Liste der diejenigen, die Sie nicht weitergeben wollen? Für HTTP/1.1, die Designer haben sich halb gewonnen die Schlacht für Sie: tools.ietf.org/html/rfc2616#section-13.5.1
- genial, ich hatte keine Ahnung, es fehlte ein r.
- Roodle kann ich diese nutzen, um proxy-server läuft auf einem anderen port?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich schrieb vor kurzem ein ähnliches web-Anwendung. Beachten Sie, dass dies ist die Art, wie ich es Tat. Ich sage nicht, Sie sollten es so machen. Dies sind nur einige der Fallstricke, die ich stieß:
Ändern von Attributwerten von der relativen zur absoluten
Es ist viel mehr beteiligt als nur das abrufen einer Seite und präsentiert es dem Kunden. Viele Male sind Sie nicht in der Lage, als proxy für die Webseite ohne Fehler.
Viele Webseiten setzen auf relative Pfade zu Ressourcen, um die Webseite anzuzeigen, die in einer gut strukturierten Art und Weise. Zum Beispiel, dieses Bild-tag:
Führt der client dabei eine Anfrage an:
Was nicht. Die "src " - Wert konvertiert werden sollen zu:
So, Sie brauchen, um zu analysieren das HTML-Dokument mit so etwas wie BeautifulSoup, Schleife über alle tags und überprüfen Sie die Attribute wie:
Und ändern Ihre Werte entsprechend, so dass der tag wird:
Diese Methode gilt, um mehr tags als nur das Bild ein. eine, Skript, link, li und Rahmen sind ein paar Sie sollten sich ebenso ändern.
HTML-Spielereien
Vorherige Methode sollte Euch weit, aber Sie sind noch nicht fertig.
Beide
Und
sind Beispiele für code, der schwierig zu erreichen, und ändern Sie mit BeautifulSoup.
Im ersten Beispiel gibt es einen css @Import, um eine relative uri. Die zweite betrifft die " url ()' - Methode von einem inline-CSS-Anweisung.
In meiner situation, ich landete schreiben schrecklich-code manuell zu ändern, diese Werte. Sie verwenden möchten, können Regex für diese, aber ich bin mir nicht sicher.
Leitet
Mit Python-Requests oder Urllib2 Sie leicht Folgen können, leitet automatisch. Denken Sie nur daran, zu retten, was die neuen (Basis -) uri ist; Sie benötigen es für die "änderung der Attribute Werte aus relativen zu absoluten" Betrieb.
Müssen Sie auch beschäftigen sich mit 'hardcoded' leitet. Wie diese:
Muss geändert werden:
Base-tag
Den base-tag gibt die Basis-URL/target für alle relativen URLs im Dokument. Werden Sie wahrscheinlich wollen, um den Wert zu ändern.
Endlich fertig?
NÖ. Einige websites verlassen sich stark auf javascript zu zeichnen, deren Inhalt auf dem Bildschirm. Diese Seiten sind am schwersten zu proxy. Ich habe darüber nachgedacht, mit so etwas wie PhantomJS oder Ghost zu Holen und bewerten Webseiten und präsentiert das Ergebnis an den client.
Vielleicht mein source code kann Ihnen helfen. Sie können es verwenden, wie Sie wollen.
<base>
- tag im Dokument-header zu reparieren, die relative URLs in einer fiel swoop. (Aber nicht, wenn es schon eins!)Wenn Sie möchten, um einen echten proxy, die Sie verwenden können:
tornado-proxy
oder
einfache proxy basiert auf Twisted
Aber ich denke, es wird nicht schwer sein, passen Sie den für Ihren Fall.
Ich denke, Sie brauchen nicht Ihre Letzte if-block. Dies scheint für mich arbeiten:
Können Sie das socket-Modul in der standard-Bibliothek und wenn Sie mit Linux epoll als gut.
Sehen Sie Beispiel-code eines einfachen asynchronen server hier: https://github.com/aychedee/octopus/blob/master/octopus/server.py
Anscheinend bin ich ziemlich spät bei der Beantwortung dieser, aber stolperte über es eine Weile zurück. Ich Schreibe sowas ähnliches wie Ihre Anforderungen selbst.
Ist es mehr eine HTTP-repeater, aber der erste der es die Aufgabe ist, den proxy selbst. Es ist noch nicht ganz abgeschlossen und es gibt keine read-me für es für jetzt -- aber die sind auf meiner todo-Liste.
Habe ich verwendet mitmproxy um dies zu erreichen. Es ist vielleicht nicht das eleganteste Stück code gibt, und ich habe eine Menge von hacks die hier und da erreichen die repeater-Funktionalität. Ich weiß mitmproxy standardmäßig hat Wege zur Erreichung der repeater-Ding leicht, aber es gab einige bestimmte Anforderungen, die in meinem Fall, wo ich konnte nicht Sie diese features angeboten, die von mitmproxy.
Können Sie finden das Projekt auf https://github.com/c0n71nu3/python_repeater/
Der repo wird noch update von mir und wenn es irgendwelche Entwicklungen.
Hoffentlich, es wäre in der Lage, um zu dienen einige Hilfe für Sie sein.
können Sie Benutzeranforderungen Modul。
Anfrage docs