鉴于:
我怎么能使用Pyramid和Twisted?
我可以想象制作一个扭曲的协议来获取原始的HTML请求。但后来我无法看到如何将其解析为金字塔请求对象。所有记录的金字塔工具似乎都希望在某些时候有一些wsgi接口。
我可以使用waitress code来解析请求并将其转换为WSGI env然后将env传递给金字塔但是这是很多问题,我确信我甚至无法想象在路上
我知道twisted包含一个WSGI服务器,但它暗示了应用程序代码中的同步性,这不符合我的目的。我希望能够在扭曲的异步协议中使用请求和响应对象,渲染器,路由器和其他金字塔工具,以及异步,非阻塞的应用程序代码。因此我不想使用WSGI。
与您在Python甚至其他语言中找到的任何其他异步工具包相比,Twisted API冗长,繁重且不直观。因此批评它的人体工程学。我可以使用它,但是在我的团队中训练新手来做这件事的成本很高。我希望降低它。
实际上,它包含了我想要使用的大量功能。
为了详细说明我的需求,我正在构建一个使用crossbar.io和cyclone的工具,让我的团队对当前的工具有一个更友好的WAMP / HTTP框架。但是旋风并不像金字塔那么完整,我希望金字塔组件能够解耦,以至于WSGI范式没有得到强制执行,所以我可以利用他们所做的巨大工作。我需要的只是一个入口点:获取HTML的地方,并将其解析为请求对象,并在某处获取响应对象,并将HTML返回给客户端。我希望我不必为此手动编写协议,http很棘手,我确信我会在很多方面弄错。
一个精度:我不希望使用完整的金字塔框架,只是在这里和那里的一些组件,如生根,cookie解析,CSRF保护等。我不会使用他们的视图系统,因为它假设一个同步API。
查看Pyramid,我可以看到它希望解析整个请求并将其转换为请求对象。它还将响应作为对象返回。因此,将扭曲和金字塔钩在一起的问题的一部分是:
替代方案可以是使用比金字塔更简单的东西,如werkzeug用于胶水。
答案 0 :(得分:1)
Twisted Web允许您在收到HTTP请求主体时(无论内容类型,HTML或其他方式)逐步解释它们 - 但它并不能轻松完成。我们似乎从来没有在改善这种情况方面取得很大进展。a very old ticket在它得到解决之前,可能没有比我即将给出的答案更好的答案。我认为,这种增量的HTTP请求正文是你在这里寻找的(因为你说你希望请求是一个很大的HTML块")。
增量请求正文处理的挂钩是Request.handleContentChunk
。您可以在我对Python server for streaming request body content的回答中看到其用法的完整演示。
这可以在到达服务器时为您提供数据。如果要使用Pyramid,则必须构建使用此数据的Pyramid请求。 Pyramid请求对象的大部分初始化应该是直截了当的(例如,使用请求标头填充environ字典 - 您可以从Request.requestHeaders
获取这些内容)。稍微棘手的部分是初始化Pyramid请求对象body
- 它应该是一个类文件对象,提供对请求体的同步访问。
一方面,如果在完全接收请求主体之前发送请求,则可以避免在内存中缓冲整个请求主体的成本。另一方面,如果您让应用程序代码开始读取请求主体,那么您必须处理它尝试读取超出实际到达服务器的数据点的情况。这可以处理。期望body
类文件对象呈现阻塞接口。所有你需要做的就是阻止,直到数据可用。
这是我的意思的简短(不完整,并不意味着实际工作)草图:
# XXX Note: Queue is not actually thread-safe. Use a safer primitive.
from Queue import Queue
class Body(object):
def __init__(self):
self._buffer = Queue()
self._pending = b""
self._eof = False
def read(self, how_many):
if self._eof:
return b""
if self._pending == b"":
data = self._buffer.get()
if data is None:
self._eof = True
return b""
else:
self._pending = data
if self._pending is None:
result = self._pending[:how_many]
self._pending = self._pending[how_many:]
return result
def _add_data(self, data):
self._buffer.put(data)
您可以创建此类型的实例,使用它初始化Pyramid请求对象的body
属性,然后在Twisted Request类中调用_add_data
handleContentChunk
{ {1}}回调。
您还可以将其实现为Twisted自己的WSGI服务器的增强功能。为简单起见,Twisted的WSGI服务器在将请求分派给WSGI应用程序之前会读取整个请求主体 - 但它并不是必须的。如果这是WSGI唯一的问题那么它可以更好地提高WSGI实现的质量并保持界面,而不是实现改进和跨接口的步骤(将你更紧密地绑在Twisted和Pyramid上) - 不必要地)。
问题的后半部分,逐步生成响应主体,不应该是一个问题。 Twisted的WSGI容器将在WSGI应用程序对象产生响应数据时写出响应数据。或者,如果您使用twisted.web.resource
而不是WSGI界面,则可以随时拨打request.write
任意时间(直到您致电request.finish
)。唯一的诀窍是,如果你想这样做,必须从NOT_DONE_YET
方法返回render
。