私は、署名されたリクエストをReSTful Webサービスに送信し、XMLを受信し、それをHTMLに変換し、AJAX経由でクライアントに配信するブラウザ(と呼びましょうthebrowser
)を備えたZope/Ploneサーバーを持っています(したがって、クライアントの観点から) 、すべてが私のサーバー上で行われます)。ほとんどの場合、これは機能しますが、特定の要求では機能しません。その理由はわかりません。失敗したリクエストには数秒かかり、データの長さは約 100 kB ですが、ここでは分やメガバイトについて話しているわけではありません。
奇妙なことに、ZServerHTTPResponse
オブジェクトはまったく問題ないように見えますが、Web クライアント側 (Firefox、Firebug) には空の文字列として到着します!
ツールチェーンは次のようになります。
スキンには、次のものがありScript (Python)
ます。
## Script (Python) "theservice"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=
##title=
##
thebrowser = context.getBrowser('thebrowser')
return thebrowser.get(thedict={'path':'/'.join(traverse_subpath)})
これにより、機能するように要求され/theservice/some/sub/path
ます。some/sub/path
キーに入れられpath
ます。
のget
メソッドは引数をthebrowser
取り、path
一般的な処理 (署名されたリクエストをhttps://remote.service.somewhere/some/sub/pathに送信する) を実行し、XML レスポンスを に従って正しい変換メソッドに送りpath
、 jquery アコーディオンなどで使用されます。
ブラウザthebrowser
は次のようになります (わかりやすくするためにエラー処理などは削除されています)。
def transformer(func):
"""
decorator function for generic processing
"""
def f2(self, txt, req=None, auth_tup=None):
global HTML_HEAD, HTML_TAIL
ham = func(self, txt, auth_tup=auth_tup)
res = list(HTML_HEAD)
res.extend(ham)
res.extend(HTML_TAIL)
return u''.join(res)
f2.__name__ = func.__name__
return f2
class Browser(BrowserView):
def get(self, propagate=True, thedict=None):
"""
send a request to the remote ReSTful service
and transform the received XML text to HTML
pretty URL:
/theservice/path/as/sub/path
"""
context = self.context
request = context.request
response = request.response
if thedict is None:
thedict = request.form
path = thedict['path']
# ... set the 'pseudonym', 'theurl' variables ...
auth_tuples = self._auth_tuples(pseudonym)
code = None
text = None
fo = urlopen(theurl)
code = fo.code
headers = fo.info().headers
# set the headers explicitly; might be unnecessary:
for line in headers:
name, text = line.split(':', 1) # found: ': '
handle_header(response, name, text)
raw = fo.read().strip()
text = unicode(raw, 'utf-8') # -> unicode
fo.close()
text = self.transform(path, text, response, theurl, auth_tuples)
response.setBody(text)
return response
# -------------------------------------------------------- get
def transform(self, path, txt, response, theurl=None, auth_tup=None):
"""
Choose a transformer function, apply it to the given text,
and return the HTML text generated
"""
transformer = self.getTransformer(path) # not included here
html = transformer(self, # e.g. tf_xy; see below
txt.decode('utf-8'),
theurl or path,
auth_tup=auth_tup)
if html is not None:
response.setHeader('Content-Type', 'text/html; charset=utf-8')
return html
return txt.encode('utf-8')
@transformer
def tf_xy(self, txt, auth_tup=None):
"""
transform function for path xy
"""
root = ElementTree.fromstring(txt)
res = []
for child in root.getchildren():
if child.tag == 'foo':
res.append(''.join(('<p>', child.text, '</p>'))) # example
# ...
return res
メソッドに別のデコレーターを適用して結果をログに記録すると、オブジェクトget
に関する次の情報が得られます。ZServerHTTPResponse
headers = {'connection': 'close',
'content-length': '110626',
'content-type': 'text/html; charset=utf-8',
'date': 'Wed, 17 Apr 2013 09:04:13 GMT',
'status': '200 OK',
'transfer-encoding': 'chunked'}
accumulated_headers = 'Set-Cookie: JSESSIONID=471108159E6EF40EB9F2F7305E77EB69; Path=/; Secure\r\n'
body = '<!DOCTYPE html><html><head><meta h(... 110575 bytes total ...)iv></body></html>'
errmsg = 'OK'
status = 200
...これは私にはかなり合理的に見えます。いずれにせよ、一部のリクエスト (おそらく応答が大きい、または処理時間が最も長いリクエスト) では、クライアント ブラウザに空の文字列が表示されます。
バージョン: Zope 2.10.13、Python 2.4.6 (64bit)、Plone 3.3 (はい、Plone 4 に切り替えますが、時間がかかります...)
更新:ElementTree
コンパイルされたバージョンを使用するようにインポートを
修正したときに、問題が解決したと思いました:
try:
from celementtree import fromstring # modern Python versions
except ImportError:
try:
from cElementTree import fromstring # Python 2.4
except ImportError:
from elementtree import fromstring # emergency fallback
残念ながら、これは私にとってはうまくいきましたが、顧客にとってはうまくいきませんでした。
Zope サイトは、通常の RewriteRule がアクティブな Apache VirtualHost で提供されます。
RewriteRule ^/(.*) http://localhost:8082/VirtualHostBase/http/%{HTTP_HOST}:80/theportalroot/VirtualHostRoot/$1 [L,P]
Firebug によると、content-length ヘッダーは存在しません (これは Apache によって取り除かれているのでしょうか?!)。完全な応答ヘッダーは次のとおりです。
Connection Keep-Alive
Content-Encoding gzip
Content-Type text/html; charset=utf-8
Date Thu, 18 Apr 2013 12:31:41 GMT
Keep-Alive timeout=15, max=99
Server Zope/(Zope 2.10.7-final, python 2.4.6, linux2) ZServer/1.1 Plone/3.2.2 ShellEx Server/4.0.0
Set-Cookie JSESSIONID=308B09957635CA02829AF5C362FB60E3; Path=/; Secure
Transfer-Encoding chunked
Vary Accept-Encoding
Zope から直接応答を取得しようとしていますが、これを行うには明らかに Zope ルートにアクセスする必要があり、そこで許可の問題があります。