在RENDER_GET或RENDER_POST处理期间发布另一个Web查询 [英] Posting another web query during render_GET or render_POST processing

查看:12
本文介绍了在RENDER_GET或RENDER_POST处理期间发布另一个Web查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用Twisted编写的小型Web服务器。我想做的一件事是让它返回来自另一个Web服务器的结果作为加载页面的响应。也就是说,服务器A(通过http://A.com/resource)对Render_Get()的响应应该是服务器B(通过http://B.com/resource2)的不同URL的内容。服务器B返回的内容是动态的,所以我不能只缓存它。

现在,服务器A可以很好地呈现页面,但它不能呈现这个远程资源。我尝试过使用Agent(),但似乎无法从B获得响应,更不用说将其转发给A了。我知道,我必须在某个地方从Render_Get获取该请求,然后write()finish()。这是在cbBody回调中完成的,该回调会被调用,但无法访问原始请求来填充它。

以下是服务器A的资源处理程序的一段代码:

def render_GET(self,request):
    # try with canned content just to test the whole thing
    bmpServer = BMPServer(ServerBURL,
                          "xyzzy",
                          "plugh")
    d= bmpServer.postNotification({"a":123},request)
    print "Deferred", d
    return NOT_DONE_YET

这是服务器A上的另一个代码:

theRequest = None

def cbRequest(response,args):
    print "response called"
    print response
    print args
    print 'Response version:', response.version
    print 'Response code:', response.code
    print 'Response phrase:', response.phrase
    print 'Response headers:'
    print pformat(list(response.headers.getAllRawHeaders()))  
    d = readBody(response)
    d.addCallback(cbBody)
    return d

def cbBody(body):
    print "Response body:"
    print body
    theRequest.write(body)
    theRequest.finish()
    theRequest = None

def cbError(failure):
    print type(failure.value), failure # catch error here
    print failure.value.reasons[0].printTraceback()

class BMPServer(object):
    def __init__(self,url,arg1,arg2):
        self.url = url
        self.arg1 = arg1
        self.arg2 = arg2

    def postNotification(self,message,request):
        theRequest = request
        bmpMessage = {'arg1':self.token,
                      'arg2':self.appID,
                      'message':message}
        print "Sending request to %s"%self.url

        print "Create agent"
        agent = Agent(reactor)
        print "create request deferred"
        print "url = %s" % self.url
        d = agent.request('POST', self.url,
                          Headers({'User-Agent': ['Twisted Web Client Example']}),
                          MessageProducer(bmpMessage))
        print "adding callback"
        d.addCallbacks(cbRequest,cbError)
        print "returning deferred"
        return d

当我将其作为独立代码运行时(例如,在资源外部使用react()),它工作得很好。然而,当我尝试如上所示将其包括在内时,它似乎从未收到数据。我已运行Wireshark,以便可以看到从服务器B返回的响应,但数据从未显示在cbRequest()中。

例如,下面是我看到的输出:

Sending request to http://localhost:8888/postMGCMNotificationService
Create agent
create request deferred
url = http://serverB:8888/postService
Message producer: body = {"arg2": "plugh", "arg1": "xyzzy", "message": {"a": 1}}
adding callback
returning deferred
testAgent: returning deferred
<Deferred at 0x10b54d290>
Writing body now
response called
<twisted.web._newclient.Response object at 0x1080753d0>
Response version: ('HTTP', 1, 1)
Response code: 200
Response phrase: OK
Response headers:
Response body:
{"result": false}
^CUnhandled error in Deferred:
Unhandled Error
Traceback (most recent call last):
  File "/Library/Python/2.7/site-packages/Twisted-13.1.0_r39314-py2.7-macosx-10.8-intel.egg/twisted/web/_newclient.py", line 1151, in _bodyDataFinished_CONNECTED
    self._bodyProtocol.connectionLost(reason)
  File "/Library/Python/2.7/site-packages/Twisted-13.1.0_r39314-py2.7-macosx-10.8-intel.egg/twisted/web/client.py", line 1793, in connectionLost
    self.deferred.callback(b''.join(self.dataBuffer))
  File "/Library/Python/2.7/site-packages/Twisted-13.1.0_r39314-py2.7-macosx-10.8-intel.egg/twisted/internet/defer.py", line 382, in callback
    self._startRunCallbacks(result)
  File "/Library/Python/2.7/site-packages/Twisted-13.1.0_r39314-py2.7-macosx-10.8-intel.egg/twisted/internet/defer.py", line 490, in _startRunCallbacks
    self._runCallbacks()
--- <exception caught here> ---
  File "/Library/Python/2.7/site-packages/Twisted-13.1.0_r39314-py2.7-macosx-10.8-intel.egg/twisted/internet/defer.py", line 577, in _runCallbacks
    current.result = callback(current.result, *args, **kw)
  File "AServer.py", line 85, in cbBody
    print theRequest
exceptions.UnboundLocalError: local variable 'theRequest' referenced before assignment

再仔细看一下,似乎如果我能想出一种方法将请求传递到cbBody(),这一切都会很好。

推荐答案

可以将额外的参数传递给Deferred上的回调:

d.addCallback(f, x)

当d触发时,结果为f(result of d, x)。您可以通过这种方式传递任意数量的位置参数或关键字参数。有关详细信息,请参阅the API documentation for Deferred

这篇关于在RENDER_GET或RENDER_POST处理期间发布另一个Web查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆