【问题标题】:Why does SimpleHTTPServer redirect to ?querystring/ when I request ?querystring?为什么 SimpleHTTPServer 在我请求 ?querystring 时重定向到 ?querystring/?
【发布时间】:2012-10-08 20:17:52
【问题描述】:

我喜欢使用 Python 的 SimpleHTTPServer 来本地开发各种需要通过 Ajax 调用等加载资源的 Web 应用程序。

当我在 URL 中使用查询字符串时,服务器总是会重定向到带有斜杠的相同 URL。

例如,/folder/?id=1 使用 HTTP 301 响应重定向到 /folder/?id=1/

我只是使用python -m SimpleHTTPServer 启动服务器。

知道如何摆脱重定向行为吗?这是 Python 2.7.2。

【问题讨论】:

  • SimpleHTTPServer 仅提供文件。使用其他东西来处理请求中的参数。

标签: python simplehttpserver webdev.webserver


【解决方案1】:

确保查询参数保持原样的正确方法是确保您直接向文件名发出请求,而不是让SimpleHTTPServer 重定向到您的index.html

例如http://localhost:8000/?param1=1 执行重定向(301)并将网址更改为http://localhost:8000/?param=1/,这与查询参数混淆。

但是http://localhost:8000/index.html?param1=1(使索引文件显式)加载正确。

所以只要不让SimpleHTTPServer 进行 url 重定向就可以解决问题。

【讨论】:

    【解决方案2】:

    好的。在 Morten 的帮助下,我想出了这个,这似乎就是我所需要的:只需忽略查询字符串(如果它们存在)并提供静态文件。

    import SimpleHTTPServer
    import SocketServer
    
    PORT = 8000
    
    
    class CustomHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    
        def __init__(self, req, client_addr, server):
            SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, req, client_addr, server)
    
        def do_GET(self):
            # cut off a query string
            if '?' in self.path:
                self.path = self.path.split('?')[0]
            SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
    
    
    class MyTCPServer(SocketServer.ThreadingTCPServer):
        allow_reuse_address = True
    
    if __name__ == '__main__':
        httpd = MyTCPServer(('localhost', PORT), CustomHandler)
        httpd.allow_reuse_address = True
        print "Serving at port", PORT
        httpd.serve_forever()
    

    【讨论】:

    • 这似乎不尊重 url 参数。它仍然在查询参数之后附加“/”。
    【解决方案3】:

    我不确定重定向是如何生成的...我尝试实现一个非常基本的 SimpleHTTPServer,但在使用查询字符串参数时我没有得到任何重定向。

    只需执行self.path.split("/") 之类的操作并在处理请求之前处理路径? 这段代码做你想做的事:

    import SocketServer
    import SimpleHTTPServer
    import os
    
    
    class CustomHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
        def folder(self):
            fid = self.uri[-1].split("?id=")[-1].rstrip()
            return "FOLDER ID: %s" % fid
    
        def get_static_content(self):
            # set default root to cwd
            root = os.getcwd()
            # look up routes and set root directory accordingly
            for pattern, rootdir in ROUTES:
                if path.startswith(pattern):
                    # found match!
                    path = path[len(pattern):]  # consume path up to pattern len
                    root = rootdir
                    break
            # normalize path and prepend root directory
            path = path.split('?',1)[0]
            path = path.split('#',1)[0]
            path = posixpath.normpath(urllib.unquote(path))
            words = path.split('/')
            words = filter(None, words)
            path = root
            for word in words:
                drive, word = os.path.splitdrive(word)
                head, word = os.path.split(word)
                if word in (os.curdir, os.pardir):
                    continue
                path = os.path.join(path, word)
                return path
    
        def do_GET(self):
            path = self.path
            self.uri = path.split("/")[1:]
    
            actions = {
                "folder": self.folder,
            }
            resource = self.uri[0]
            if not resource:
                return self.get_static_content()
            action = actions.get(resource)
            if action:
                print "action from looking up '%s' is:" % resource, action
                return self.wfile.write(action())
            SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
    
    
    class MyTCPServer(SocketServer.ThreadingTCPServer):
        allow_reuse_address = True
    
    httpd = MyTCPServer(('localhost', 8080), CustomHandler)
    httpd.allow_reuse_address = True
    print "serving at port", 8080
    httpd.serve_forever()
    

    试试看:

    HTTP GET /folder/?id=500x -> "FOLDER ID: 500x"

    编辑:

    好吧,如果你以前没有使用过 SimpleHTTPServer 的东西,你基本上实现了基本请求处理程序,实现 do_GET()、do_PUT()、do_POST() 等。

    然后我通常做的是解析请求字符串(使用 re),模式匹配,看看我是否可以找到请求处理程序,如果没有,如果可能,将请求作为静态内容请求处理。

    您说如果可能的话您想提供静态内容,那么您应该翻转这个模式匹配,首先查看请求是否与文件存储匹配,如果不匹配,则与处理程序匹配:)

    【讨论】:

    • 首先,谢谢!它表明可以防止重定向。然而,这个处理程序似乎不像我习惯的那样提供静态文件。我基本上想要的是能够提供任何可用作静态文件的路径,完全忽略查询字符串部分。
    • 只需在 do_GET() 方法中添加逻辑,我已经进行了更新
    • 你考虑过使用 web.py 吗?它真的很轻巧,只是上面代码的一小部分。
    • 我不会为此考虑 web.py,因为据我所知,它默认仅从 /static/ 提供静态文件。由于我只想提供静态文件,所以我没有费心。
    • 您通常可以调整诸如静态内容所在位置这样的小因素,所以我不排除框架只是这样:)
    猜你喜欢
    • 2023-03-12
    • 2012-04-21
    • 2011-11-01
    • 2011-12-27
    • 1970-01-01
    • 2013-02-08
    • 1970-01-01
    • 1970-01-01
    • 2015-03-27
    相关资源
    最近更新 更多