mirror of
https://github.com/apidoorman/doorman.git
synced 2026-02-09 11:07:05 -06:00
test soap gateway retries
This commit is contained in:
@@ -368,6 +368,20 @@ class GatewayService:
|
||||
if api.get('api_credits_enabled') and username and not bool(api.get('api_public')):
|
||||
if not await credit_util.deduct_credit(api.get('api_credit_group'), username):
|
||||
return GatewayService.error_response(request_id, 'GTW008', 'User does not have any credits', status=401)
|
||||
else:
|
||||
# Recursive call with url present; re-derive API context for headers/validation
|
||||
try:
|
||||
parts = [p for p in (path or '').split('/') if p]
|
||||
api_name_version = ''
|
||||
endpoint_uri = ''
|
||||
if len(parts) >= 3:
|
||||
api_name_version = f'/{parts[0]}/{parts[1]}'
|
||||
endpoint_uri = '/' + '/'.join(parts[2:])
|
||||
api_key = doorman_cache.get_cache('api_id_cache', api_name_version)
|
||||
api = await api_util.get_api(api_key, api_name_version)
|
||||
except Exception:
|
||||
api = None
|
||||
endpoint_uri = ''
|
||||
current_time = time.time() * 1000
|
||||
query_params = getattr(request, 'query_params', {})
|
||||
incoming_content_type = request.headers.get('Content-Type') or 'application/xml'
|
||||
@@ -377,7 +391,7 @@ class GatewayService:
|
||||
content_type = incoming_content_type
|
||||
else:
|
||||
content_type = 'text/xml; charset=utf-8'
|
||||
allowed_headers = api.get('api_allowed_headers') or []
|
||||
allowed_headers = api.get('api_allowed_headers') or [] if api else []
|
||||
headers = await get_headers(request, allowed_headers)
|
||||
headers['Content-Type'] = content_type
|
||||
if 'SOAPAction' not in headers:
|
||||
@@ -401,7 +415,7 @@ class GatewayService:
|
||||
pass
|
||||
|
||||
try:
|
||||
endpoint_doc = await api_util.get_endpoint(api, 'POST', '/' + endpoint_uri.lstrip('/'))
|
||||
endpoint_doc = await api_util.get_endpoint(api, 'POST', '/' + endpoint_uri.lstrip('/')) if api else None
|
||||
endpoint_id = endpoint_doc.get('endpoint_id') if endpoint_doc else None
|
||||
if endpoint_id:
|
||||
await validation_util.validate_soap_request(endpoint_id, envelope)
|
||||
|
||||
127
backend-services/tests/test_soap_gateway_retries.py
Normal file
127
backend-services/tests/test_soap_gateway_retries.py
Normal file
@@ -0,0 +1,127 @@
|
||||
import pytest
|
||||
|
||||
|
||||
class _Resp:
|
||||
def __init__(self, status_code=200, body='<ok/>', headers=None):
|
||||
self.status_code = status_code
|
||||
self.text = body
|
||||
base = {'Content-Type': 'text/xml'}
|
||||
if headers:
|
||||
base.update(headers)
|
||||
self.headers = base
|
||||
self.content = (self.text or '').encode('utf-8')
|
||||
|
||||
|
||||
def _mk_retry_xml_client(sequence, seen):
|
||||
counter = {'i': 0}
|
||||
|
||||
class _Client:
|
||||
def __init__(self, timeout=None):
|
||||
pass
|
||||
async def __aenter__(self):
|
||||
return self
|
||||
async def __aexit__(self, exc_type, exc, tb):
|
||||
return False
|
||||
async def post(self, url, content=None, params=None, headers=None):
|
||||
seen.append({'url': url, 'params': dict(params or {}), 'headers': dict(headers or {}), 'content': content})
|
||||
idx = min(counter['i'], len(sequence) - 1)
|
||||
code = sequence[idx]
|
||||
counter['i'] = counter['i'] + 1
|
||||
return _Resp(code)
|
||||
return _Client
|
||||
|
||||
|
||||
async def _setup_soap(client, name, ver, retry_count=0):
|
||||
payload = {
|
||||
'api_name': name,
|
||||
'api_version': ver,
|
||||
'api_description': f'{name} {ver}',
|
||||
'api_allowed_roles': ['admin'],
|
||||
'api_allowed_groups': ['ALL'],
|
||||
'api_servers': ['http://soap.retry'],
|
||||
'api_type': 'REST',
|
||||
'api_allowed_retry_count': retry_count,
|
||||
}
|
||||
r = await client.post('/platform/api', json=payload)
|
||||
assert r.status_code in (200, 201)
|
||||
r2 = await client.post('/platform/endpoint', json={
|
||||
'api_name': name,
|
||||
'api_version': ver,
|
||||
'endpoint_method': 'POST',
|
||||
'endpoint_uri': '/call',
|
||||
'endpoint_description': 'soap call',
|
||||
})
|
||||
assert r2.status_code in (200, 201)
|
||||
from conftest import subscribe_self
|
||||
await subscribe_self(client, name, ver)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_soap_retry_on_500_then_success(monkeypatch, authed_client):
|
||||
import services.gateway_service as gs
|
||||
name, ver = 'soapretry500', 'v1'
|
||||
await _setup_soap(authed_client, name, ver, retry_count=2)
|
||||
seen = []
|
||||
monkeypatch.setattr(gs.httpx, 'AsyncClient', _mk_retry_xml_client([500, 200], seen))
|
||||
r = await authed_client.post(
|
||||
f'/api/soap/{name}/{ver}/call', headers={'Content-Type': 'application/xml'}, content='<env/>'
|
||||
)
|
||||
assert r.status_code == 200
|
||||
assert len(seen) == 2
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_soap_retry_on_502_then_success(monkeypatch, authed_client):
|
||||
import services.gateway_service as gs
|
||||
name, ver = 'soapretry502', 'v1'
|
||||
await _setup_soap(authed_client, name, ver, retry_count=2)
|
||||
seen = []
|
||||
monkeypatch.setattr(gs.httpx, 'AsyncClient', _mk_retry_xml_client([502, 200], seen))
|
||||
r = await authed_client.post(
|
||||
f'/api/soap/{name}/{ver}/call', headers={'Content-Type': 'application/xml'}, content='<env/>'
|
||||
)
|
||||
assert r.status_code == 200
|
||||
assert len(seen) == 2
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_soap_retry_on_503_then_success(monkeypatch, authed_client):
|
||||
import services.gateway_service as gs
|
||||
name, ver = 'soapretry503', 'v1'
|
||||
await _setup_soap(authed_client, name, ver, retry_count=2)
|
||||
seen = []
|
||||
monkeypatch.setattr(gs.httpx, 'AsyncClient', _mk_retry_xml_client([503, 200], seen))
|
||||
r = await authed_client.post(
|
||||
f'/api/soap/{name}/{ver}/call', headers={'Content-Type': 'application/xml'}, content='<env/>'
|
||||
)
|
||||
assert r.status_code == 200
|
||||
assert len(seen) == 2
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_soap_retry_on_504_then_success(monkeypatch, authed_client):
|
||||
import services.gateway_service as gs
|
||||
name, ver = 'soapretry504', 'v1'
|
||||
await _setup_soap(authed_client, name, ver, retry_count=2)
|
||||
seen = []
|
||||
monkeypatch.setattr(gs.httpx, 'AsyncClient', _mk_retry_xml_client([504, 200], seen))
|
||||
r = await authed_client.post(
|
||||
f'/api/soap/{name}/{ver}/call', headers={'Content-Type': 'application/xml'}, content='<env/>'
|
||||
)
|
||||
assert r.status_code == 200
|
||||
assert len(seen) == 2
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_soap_no_retry_when_retry_count_zero(monkeypatch, authed_client):
|
||||
import services.gateway_service as gs
|
||||
name, ver = 'soapretry0', 'v1'
|
||||
await _setup_soap(authed_client, name, ver, retry_count=0)
|
||||
seen = []
|
||||
monkeypatch.setattr(gs.httpx, 'AsyncClient', _mk_retry_xml_client([500, 200], seen))
|
||||
r = await authed_client.post(
|
||||
f'/api/soap/{name}/{ver}/call', headers={'Content-Type': 'application/xml'}, content='<env/>'
|
||||
)
|
||||
assert r.status_code == 500
|
||||
assert len(seen) == 1
|
||||
|
||||
Reference in New Issue
Block a user