我正在尝试为javascript写下一个简单的本地代理:因为我需要从网页中的javascript中加载一些东西,我在python中编写了这个简单的守护进程:
import string,cgi,time
from os import curdir, sep
import urllib
import urllib2
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
class MyHandler(BaseHTTPRequestHandler):
def fetchurl(self, url, post, useragent, cookies):
headers={"User-Agent":useragent, "Cookie":cookies}
url=urllib.quote_plus(url, ":/?.&-=")
if post:
req = urllib2.Request(url,post,headers)
else:
req=urllib2.Request(url, None, headers)
try:
response=urllib2.urlopen(req)
except urllib2.URLError, e:
print "URLERROR: "+str(e)
return False
except urllib2.HTTPError, e:
print "HTTPERROR: "+str(e)
return False
else:
return response.read()
def do_GET(self):
if self.path != "/":
[callback, url, post, useragent, cookies]=self.path[1:].split("%7C")
print "callback = "+callback
print "url = "+url
print "post = "+post
print "useragent = "+useragent
print "cookies = "+cookies
if useragent=="":
useragent="pyjproxy v. 1.0"
load=self.fetchurl(url, post, useragent, cookies)
pack=load.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r").replace("\t", "\\t").replace(" </script>", "</scr\"+\"ipt>")
response=callback+"(\""+pack+"\");"
if load:
self.send_response(200)
self.send_header('Content-type', 'text/javascript')
self.end_headers()
self.wfile.write(response)
self.wfile.close()
return
else:
self.send_error(404,'File Not Found: %s' % self.path)
return
else:
embedscript="function pyjload(datadict){ if(!datadict[\"url\"] || !datadict[\"callback\"]){return false;} if(!datadict[\"post\"]) datadict[\"post\"]=\"\"; if(!datadict[\"useragent\"]) datadict[\"useragent\"]=\"\"; if(!datadict[\"cookies\"]) datadict[\"cookies\"]=\"\"; var oHead = document.getElementsByTagName('head').item(0); var oScript= document.createElement(\"script\"); oScript.type = \"text/javascript\"; oScript.src=\"http://localhost:1180/\"+datadict[\"callback\"]+\"%7C\"+datadict[\"url\"]+\"%7C\"+datadict[\"post\"]+\"%7C\"+datadict[\"useragent\"]+\"%7C\"+datadict[\"cookies\"]; oHead.appendChild( oScript);}"
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(embedscript)
self.wfile.close()
return
def main():
try:
server = HTTPServer(('127.0.0.1', 1180), MyHandler)
print 'started httpserver...'
server.serve_forever()
except KeyboardInterrupt:
print '^C received, shutting down server'
server.socket.close()
if __name__ == '__main__':
main()
我在像这样的网页中使用:
<!DOCTYPE HTML>
<html><head>
<script>
function miocallback(htmlsource)
{
alert(htmlsource);
}
</script>
<script type="text/javascript" src="http://localhost:1180"></script>
</head><body>
<a onclick="pyjload({'url':'http://www.google.it','callback':'miocallback'});"> Take the Red Pill</a>
</body></html>
现在,在Firefox和Chrome上看起来总是有效。然而,在Opera和Internet Explorer上,我注意到有时它不起作用,或者它会挂起很长时间......我想知道怎么了?我做错了什么吗?
感谢您的帮助! 马特奥
答案 0 :(得分:8)
您必须了解(现代)浏览器尝试使用不同的技术优化其浏览速度,这就是您在不同浏览器上获得不同结果的原因。
在您的情况下,导致您遇到麻烦的技术是并发HTTP / 1.1会话设置:为了更好地利用您的带宽,您的浏览器可以同时启动多个HTTP / 1.1会话。这允许同时检索多个资源(例如图像)。
但是, BaseHTTPServer没有线程:只要您的浏览器尝试打开另一个连接,它就会无法执行此操作,因为BaseHTTPServer已被第一个仍处于打开状态的会话阻止。请求永远不会到达服务器并进入超时状态。这也意味着只有一个用户可以在给定时间访问您的服务。不方便?是的,但帮助就在这里:
线程! ..和python让这个很容易:
使用来自socketserver的MixIn从HTTPServer派生一个新类。
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from SocketServer import ThreadingMixIn
import threading
class Handler(BaseHTTPRequestHandler):
def do_HEAD(self):
pass
def do_GET(self):
pass
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
""" This class allows to handle requests in separated threads.
No further content needed, don't touch this. """
if __name__ == '__main__':
server = ThreadedHTTPServer(('localhost', 80), Handler)
print 'Starting server on port 80...'
server.serve_forever()
从现在开始,BaseHTTPServer已经过线程化,可以同时为多个连接(以及请求)提供服务,从而解决您的问题。
除了ThreadingMixIn之外,您还可以使用ForkingMixIn来生成另一个进程而不是另一个进程。
一切顺利,
的Creo
答案 1 :(得分:0)
请注意,Python basehttpserver是一个非常基本的HTTP服务器,但这不是你的第一个问题。
如果您将两个脚本放在</body>
标记之前的文档末尾,会发生什么?这有帮助吗?