处理 POST 请求¶
所有之前的示例都集中在 GET
请求上。与 GET
请求不同,POST
请求可以有请求主体 - 请求头之后的额外数据;例如,表示 HTML 表单内容的数据。Twisted Web 通过 Request
对象将此数据提供给应用程序。
以下是一个 Web 服务器示例,它呈现一个静态 HTML 表单,然后在该表单被发布回服务器时生成一个动态页面。免责声明:虽然这对本示例来说很方便,但通常不建议让一个资源 POST
到自身;这与 Twisted Web 无关,而是 HTTP 本身的性质;如果你在真实应用程序中这样做,请确保你了解可能产生的负面影响。
像往常一样,我们从一些导入开始。除了 Twisted 导入之外,本示例还使用 html
模块来 转义用户输入内容 以便将其包含在输出中。
from twisted.web.server import Site
from twisted.web.resource import Resource
from twisted.internet import reactor, endpoints
import html
接下来,我们将定义一个资源,它将执行两件事。首先,它将使用静态 HTML 表单响应 GET
请求
class FormPage(Resource):
def render_GET(self, request):
return (b"<!DOCTYPE html><html><head><meta charset='utf-8'>"
b"<title></title></head><body>"
b"<form><input name='the-field' type='text'></form>")
这与 上一期 中使用的资源类似。但是,我们现在将添加一个方法来赋予它第二个行为;这个 render_POST
方法将允许它接受 POST
请求
...
def render_POST(self, request):
args = request.args[b"the-field"][0].decode("utf-8")
escapedArgs = html.escape(args)
return (b"<!DOCTYPE html><html><head><meta charset='utf-8'>"
b"<title></title></head><body>"
b"You submitted: " + escapedArgs.encode('utf-8'))
这里需要注意的主要事项是使用 request.args
。这是一个类似字典的对象,它提供对表单内容的访问。此字典中的键是表单中输入的名称。每个值都是一个包含字节对象的列表(因为可以有多个具有相同名称的输入),这就是为什么我们必须提取第一个元素才能传递给 html.escape
。只要使用 application/x-www-form-urlencoded
或 multipart/form-data
内容类型发出 POST
请求,request.args
就会从表单内容中填充(它也会被任何类型请求的查询参数填充)。
最后,这个示例只需要通常的站点创建和端口设置
root = Resource()
root.putChild(b"form", FormPage())
factory = Site(root)
endpoint = endpoints.TCP4ServerEndpoint(reactor, 8880)
endpoint.listen(factory)
reactor.run()
运行服务器并访问 http://localhost:8880/form ,提交表单,然后观察它生成一个包含你输入到单个字段中的值的页面。
以下是示例的完整源代码
from twisted.web.server import Site
from twisted.web.resource import Resource
from twisted.internet import reactor, endpoints
import html
class FormPage(Resource):
def render_GET(self, request):
return (b"<!DOCTYPE html><html><head><meta charset='utf-8'>"
b"<title></title></head><body>"
b"<form method='POST'><input name='the-field'></form>")
def render_POST(self, request):
args = request.args[b"the-field"][0].decode("utf-8")
escapedArgs = html.escape(args)
return (b"<!DOCTYPE html><html><head><meta charset='utf-8'>"
b"<title></title></head><body>"
b"You submitted: " + escapedArgs.encode('utf-8'))
root = Resource()
root.putChild(b"form", FormPage())
factory = Site(root)
endpoint = endpoints.TCP4ServerEndpoint(reactor, 8880)
endpoint.listen(factory)
reactor.run()