9

我正在尝试使用 python 的 WSGI 开发一个小型 Web 应用程序。例如,如果用户选择 Google,他们将被重定向到 google.com,如果他们选择 Facebook,他们将被重定向到 facebook.com,等等。

from wsgiref.simple_server import make_server
from cgi import parse_qs, escape

main_html = """
<html>
<head><title> Welcome to redirection test page </title> </head>
<body>
    <form method="get" action='/visit'>
        <input type=radio name='site' value=google> Google
        <input type=radio name='site' value=facebook> Facebook
        <input type=submit value=submit>
    </form>
</body>
</html>
"""


def main(environ, start_response):

    response_body = main_html
    print type(response_body)   
    status = '200 OK'

    response_headers = [
                        ('Content-Type','text/html'),
                        ('Content-Length', str(len(response_body)))
                       ]


    start_response(status, response_headers)
    return [response_body]


def visit(environ, start_response):
    qs = parse_qs(environ['QUERY_STRING'])
    dest = qs.ge('site')[0]
    if dest == 'google':
        start_response('301 Moved Permanently', [('Location','http://google.com')])
    else:
        start_response('301 Moved Permanently', [('Location','http://facebook.com')])

    return [1]


def app(environ, start_response):
    if environ['PATH_INFO'] == '/':
        return main(environ, start_response)
    elif environ['PATH_INFO'] == '/visit':
        return visit(environ, start_response)

httpd =  make_server('192.168.48.128',8052, app)
print 'Serving on port 8052'
httpd.serve_forever()

但是,当我运行此代码时,出现以下错误:

Traceback (most recent call last):
  File "/usr/lib/python2.7/wsgiref/handlers.py", line 86, in run
    self.finish_response()
  File "/usr/lib/python2.7/wsgiref/handlers.py", line 131, in finish_response
    self.close()
  File "/usr/lib/python2.7/wsgiref/simple_server.py", line 33, in close
    self.status.split(' ',1)[0], self.bytes_sent
AttributeError: 'NoneType' object has no attribute 'split'
4

1 回答 1

9

你有两个问题,都在visit(). 第一个是错字,第二个是没有遵守WSGI 规范

def visit(environ, start_response):
    qs = parse_qs(environ['QUERY_STRING'])
    dest = qs.ge('site')[0]
    if dest == 'google':
        start_response('301 Moved Permanently', [('Location','http://google.com')])
    else:
        start_response('301 Moved Permanently', [('Location','http://facebook.com')])

    return [1]

看线dest = qs.ge('site')[0]qs只是一本字典,没有方法ge,只是get。此外,cgi.parse_qs已弃用- 改用urlparse.parse_qs()。修复它会给我们带来一个新错误(我的地址是 127.0.0.1,因为我刚刚从 localhost 运行它):

127.0.0.1 - - [05/Feb/2015 16:45:17] "GET /visit?site=facebook HTTP/1.1" 302 0 
Traceback (most recent call last):
  File "C:\Python27\lib\wsgiref\handlers.py", line 86, in run
    self.finish_response()
  File "C:\Python27\lib\wsgiref\handlers.py", line 128, in finish_response
    self.write(data)
  File "C:\Python27\lib\wsgiref\handlers.py", line 204, in write
    assert type(data) is StringType, "write() argument must be string"
AssertionError: write() argument must be string

这告诉我们某些东西应该是一个字符串,但不是。再次查看visit(),在返回线,揭示了问题。您正在返回[1]而不是['1']. 修复该错误使一切正常。你会发现这种行为记录在PEP 333

start_response 可调用对象必须返回一个 write(body_data) 可调用对象,它采用一个位置参数:作为 HTTP 响应正文的一部分写入的字符串。

最后,根据这个答案,您可能应该使用'302 Found'状态而不是'301 Moved Permanently'重定向,但它可以使用任何一种方式。

用这个替换函数应该可以解决你的问题:

def visit(environ, start_response):
    qs = parse_qs(environ['QUERY_STRING'])
    dest = qs.get('site')[0]
    if dest == 'google':
        start_response('302 Found', [('Location','http://google.com')])
    else:
        start_response('302 Found', [('Location','http://facebook.com')])

    return ['1']
于 2015-02-06T00:58:51.843 回答