def test_unsatisfied_uri_template_parameters(): s = UnsatisfiedParametersService() with raises(AnnotationError) as e: WsgiApp(s) assert str(e.value) == ( '"/foo/{bar}/" does not fully satisfy all parameters of foo_bar_baz() ' 'method; unsatisfied parameters are: baz, foo') # As parameter names overlapped to Python keywords append an underscore # to their names, it should deal with the case as well. s = SatisfiedParametersService() WsgiApp(s) # Should not raise AnnotationError
def test_readable_error_when_null_returned_from_null_disallowed_method(caplog): """Even if the method implementation returns None (FYI Python functions return None when it lacks return statement so that service methods are prone to return None by mistake) the error message should be readable and helpful for debugging. """ expected_message = '''The return type of null-disallowed-method() method \ is not optional (i.e., no trailing question mark), but its server-side \ implementation has tried to return nothing (i.e., null, nil, None). \ It is an internal server error and should be fixed by server-side.''' app = WsgiApp(NullDisallowedMethodServiceImpl(None)) client = Client(app, Response) caplog.handler.records = [] # Clear log records response = client.post('/?method=null_disallowed_method', data=json.dumps({}), content_type='application/json') assert caplog.record_tuples and caplog.record_tuples[-1] == ( '{0}.null_disallowed_method'.format( typing._type_repr(NullDisallowedMethodServiceImpl)), logging.ERROR, '''None is an invalid return value for the return type of {0}.\ null_disallowed_method() method.'''.format( typing._type_repr(NullDisallowedMethodServiceImpl)), ) assert response.status_code == 500, response.get_data(as_text=True) actual = json.loads(response.get_data(as_text=True)) assert actual == { '_type': 'error', '_tag': 'internal_server_error', 'message': expected_message, }
def test_omit_optional_parameter(payload, expected): app = WsgiApp(StatisticsServiceImpl()) client = Client(app, Response) response = client.post('/?method=daily_purchase', data=json.dumps(payload), content_type='application/json') assert response.status_code == 200, response.get_data(as_text=True) actual = json.loads(response.get_data(as_text=True)) assert actual == expected
def test_cors_http_resouce(origin, disallowed_origin_host, url, allow_methods, request_method): app = WsgiApp(CorsVerbServiceImpl(), allowed_origins=frozenset([ 'example.com', '*.prefix.example.com', 'infix.*.example.com', ])) assert app.allows_origin(origin) assert not app.allows_origin(u'http://' + disallowed_origin_host) assert not app.allows_origin(u'https://' + disallowed_origin_host) client = Client(app, Response) resp = client.options(url, headers={ 'Origin': origin, 'Access-Control-Request-Method': request_method, }) assert resp.status_code == 200 assert resp.headers['Access-Control-Allow-Origin'] == origin assert split(resp.headers['Access-Control-Allow-Methods']) == allow_methods assert u'origin' in split(resp.headers['Vary'], lower=True) resp2 = getattr(client, request_method.lower())( url, headers={ 'Origin': origin, 'Access-Control-Request-Method': request_method, 'Content-Type': u'application/json', }, ) assert resp2.status_code == 200, resp2.get_data(as_text=True) assert resp2.headers['Access-Control-Allow-Origin'] == origin assert allow_methods == split( resp2.headers['Access-Control-Allow-Methods']) assert 'origin' in split(resp2.headers['Vary'], lower=True) resp3 = client.options(url, headers={ 'Origin': u'https://' + disallowed_origin_host, 'Access-Control-Request-Method': request_method, }) assert resp3.status_code == 200 allow_origin = resp3.headers.get('Access-Control-Allow-Origin', u'') assert disallowed_origin_host not in allow_origin
def test_resolve_querystring(qs, expected): app = WsgiApp(StatisticsServiceImpl(), allowed_origins=frozenset(['example.com'])) client = Client(app, Response) url = '/statistics/purchases/?' + urllib.parse.urlencode(qs) response = client.get(url) assert response.status_code == 200, response.get_data(as_text=True) return_result = deserialize_meta( typing.Sequence[int], json.loads(response.get_data(as_text=True))) assert return_result == expected
def test_cors(): app = WsgiApp(MusicServiceImpl(), allowed_origins=frozenset(['example.com'])) client = Client(app, Response) def split(header, lower=False): vs = map(str.strip, header.split(',')) if lower: vs = map(str.lower, vs) return frozenset(vs) resp = client.options('/?method=get_music_by_artist_name', headers={ 'Origin': 'https://example.com', 'Access-Control-Request-Method': 'POST', }) assert resp.status_code == 200 assert resp.headers['Access-Control-Allow-Origin'] == 'https://example.com' assert split(resp.headers['Access-Control-Allow-Methods']) == { 'POST', 'OPTIONS', } assert 'origin' in split(resp.headers['Vary'], lower=True) resp2 = client.post('/?method=get_music_by_artist_name', headers={ 'Origin': 'https://example.com', 'Access-Control-Request-Method': 'POST', 'Content-Type': 'application/json', }, data=json.dumps({'artist_name': 'damien'})) assert resp2.status_code == 200, resp2.get_data(as_text=True) assert resp2.headers['Access-Control-Allow-Origin'] == \ 'https://example.com' assert {'POST', 'OPTIONS'} == split(resp2.headers['Access-Control-Allow-Methods']) assert 'origin' in split(resp2.headers['Vary'], lower=True) resp3 = client.options('/?method=get_music_by_artist_name', headers={ 'Origin': 'https://disallowed.com', 'Access-Control-Request-Method': 'POST', }) assert resp3.status_code == 200 allow_origin = resp3.headers.get('Access-Control-Allow-Origin', '') assert 'disallowed.com' not in allow_origin
def fx_music_wsgi(): return WsgiApp(MusicServiceImpl())