使用 WSGI(无框架)将用户重定向到 url
Redirect a user to url with WSGI (no framework)
我正在尝试使用 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'
你有两个问题,都在 visit()
之内。第一个是打字错误,第二个是没有遵守 WSGI specification
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
is deprecated - use urlparse.parse_qs() 代替。解决这个问题会给我们带来新的错误(我的地址是 127.0.0.1 因为我只是 运行 它脱离了本地主机):
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()
,在 return 行,揭示了问题。您 returning [1]
而不是 ['1']
。修复该错误会使一切正常。您会发现 PEP 333
中记录了此行为
The start_response callable must return a write(body_data) callable that takes one positional parameter: a string to be written as part of the HTTP response body.
最后,根据 this answer,您可能应该使用 '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']
我正在尝试使用 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'
你有两个问题,都在 visit()
之内。第一个是打字错误,第二个是没有遵守 WSGI specification
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
is deprecated - use urlparse.parse_qs() 代替。解决这个问题会给我们带来新的错误(我的地址是 127.0.0.1 因为我只是 运行 它脱离了本地主机):
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()
,在 return 行,揭示了问题。您 returning [1]
而不是 ['1']
。修复该错误会使一切正常。您会发现 PEP 333
The start_response callable must return a write(body_data) callable that takes one positional parameter: a string to be written as part of the HTTP response body.
最后,根据 this answer,您可能应该使用 '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']