【问题标题】:Python basehttpserver not serving requests properlyPython basehttpserver 无法正确处理请求
【发布时间】:2012-01-14 06:54:39
【问题描述】:

我正在尝试为 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 上,我注意到有时它不起作用,或者它挂起很长时间......我想知道这是怎么回事?我是不是做错了什么?

感谢您的帮助! 马特奥

【问题讨论】:

    标签: python http web opera


    【解决方案1】:

    您必须了解(现代)浏览器会尝试使用不同的技术来优化其浏览速度,这就是您在不同浏览器上获得不同结果的原因。

    在您的情况下,给您带来麻烦的技术是并发 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 来生成另一个进程而不是另一个线程。

    一切顺利,

    克里奥

    【讨论】:

      【解决方案2】:

      请注意,Python basehttpserver 是一个非常基本的 HTTP 服务器,远非完美,但这不是您的第一个问题。

      如果将这两个脚本放在文档末尾的 &lt;/body&gt; 标记之前会发生什么?有帮助吗?

      【讨论】:

        猜你喜欢
        • 2012-09-20
        • 1970-01-01
        • 2018-11-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多