wscalls: cache GET queries used in named calls (#22252)

This commit is contained in:
Frédéric Péters 2018-03-04 17:31:33 +01:00
parent 3b4d51a9d7
commit b874b30185
3 changed files with 45 additions and 3 deletions

View File

@ -3948,6 +3948,36 @@ def test_formdata_named_wscall(http_requests, pub):
formdata = formdef.data_class().select()[0]
assert formdata.evolution[0].parts[0].content == 'Hello bar World'
def test_formdata_named_wscall_in_conditions(http_requests, pub):
create_user(pub)
NamedWsCall.wipe()
wscall = NamedWsCall()
wscall.name = 'Hello world'
wscall.request = {'url': 'http://remote.example.net/json', 'method': 'GET'}
wscall.store()
assert wscall.slug == 'hello_world'
formdef = create_formdef()
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.PageField(id='1', label='2nd page', type='page',
condition={'type': 'python', 'value': 'webservice.hello_world["foo"] == "bar"'}),
fields.PageField(id='1', label='3rd page', type='page',
condition={'type': 'python', 'value': 'webservice.hello_world["foo"] != "bar"'}),
fields.PageField(id='1', label='4th page', type='page',
condition={'type': 'python', 'value': 'webservice.hello_world["foo"] == "bar"'}),
]
formdef.store()
formdef.data_class().wipe()
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
assert '>1st page<' in resp.body
assert '>2nd page<' in resp.body
assert '>3rd page<' not in resp.body
assert '>4th page<' in resp.body
assert len(http_requests.requests) == 1
def test_resubmit(pub):
user = create_user(pub)

View File

@ -34,6 +34,7 @@ class HTTPRequest(quixote.http_request.HTTPRequest):
self.charset = get_publisher().site_charset
self.is_json_marker = None
self.ignore_session = False
self.wscalls_cache = {}
_user = () # use empty tuple instead of None as None is a "valid" user value
def get_user(self):

View File

@ -21,7 +21,7 @@ import urllib
import urlparse
import xml.etree.ElementTree as ET
from quixote import get_publisher
from quixote import get_publisher, get_request
from qommon import _
from qommon.misc import simplify, get_variadic_url, JSONEncoder, json_loads
@ -36,7 +36,7 @@ from wcs.workflows import WorkflowStatusItem
def call_webservice(url, qs_data=None, request_signature_key=None,
method=None, post_data=None, post_formdata=None, formdata=None,
**kwargs):
cache=False, **kwargs):
url = url.strip()
if Template.is_template_string(url):
@ -70,6 +70,13 @@ def call_webservice(url, qs_data=None, request_signature_key=None,
qs = urllib.urlencode(qs)
url = urlparse.urlunparse(parsed[:4] + (qs,) + parsed[5:6])
unsigned_url = url
if method == 'GET' and cache is True: # check cache
request = get_request()
if hasattr(request, 'wscalls_cache') and unsigned_url in request.wscalls_cache:
return (None,) + request.wscalls_cache[unsigned_url]
if request_signature_key:
signature_key = str(WorkflowStatusItem.compute(request_signature_key))
if signature_key:
@ -106,6 +113,10 @@ def call_webservice(url, qs_data=None, request_signature_key=None,
else:
response, status, data, auth_header = qommon.misc.http_get_page(
url, headers=headers)
request = get_request()
if cache is True and request and hasattr(request, 'wscalls_cache'):
request.wscalls_cache[unsigned_url] = (status, data)
return (response, status, data)
@ -184,7 +195,7 @@ class NamedWsCall(XmlStorableObject):
return {'webservice': WsCallsSubstitutionProxy()}
def call(self):
(response, status, data) = call_webservice(**self.request)
(response, status, data) = call_webservice(cache=True, **self.request)
return json_loads(data)
class WsCallsSubstitutionProxy(object):