def test_requests( init_microraiden_requests, revert_chain, api_endpoint_address: str, token_contract_address, channel_manager_contract_address, receiver_address ): import microraiden.requests with requests_mock.mock() as server_mock: headers1 = Munch() headers1.token_address = token_contract_address headers1.contract_address = channel_manager_contract_address headers1.receiver_address = receiver_address headers1.price = '7' headers2 = Munch() headers2.cost = '7' headers1 = HTTPHeaders.serialize(headers1) headers2 = HTTPHeaders.serialize(headers2) url = 'http://{}/something'.format(api_endpoint_address) server_mock.get(url, [ {'status_code': 402, 'headers': headers1}, {'status_code': 200, 'headers': headers2, 'text': 'success'} ]) response = microraiden.requests.get(url) assert response.text == 'success'
def test_static_price(empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks, receiver_privkey: str): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address content = PaywalledContent( 'resource', price=3, get_fn=lambda url: ('SUCCESS', 200), ) proxy.add_content(content) response = requests.get(endpoint_url + '/resource') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 3 channel = client.get_suitable_channel(headers.receiver_address, 3) wait_for_blocks(6) channel.balance = 3 headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource', headers=headers) assert response.status_code == 200 assert response.text.strip() == '"SUCCESS"' close_channel_cooperatively(channel, receiver_privkey, client.channel_manager_address, 0)
def test_dynamic_price(empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks, receiver_privkey: str): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address price_cycle = cycle([1, 2, 3, 4, 5]) url_to_price = {} def price_fn(url: str): if url in url_to_price: price = url_to_price[url] else: price = next(price_cycle) url_to_price[url] = price return price content = PaywalledContent( 'resource_\d', price=price_fn, get_fn=lambda url: (url.split("_")[1], 200), ) proxy.add_content(content) response = requests.get(endpoint_url + '/resource_3') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 1 response = requests.get(endpoint_url + '/resource_5') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 2 response = requests.get(endpoint_url + '/resource_2') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 3 response = requests.get(endpoint_url + '/resource_3') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 1 channel = client.get_suitable_channel(headers.receiver_address, 2) wait_for_blocks(6) channel.balance = 2 headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource_5', headers=headers) assert response.status_code == 200 assert response.text.strip() == '"5"' close_channel_cooperatively(channel, receiver_privkey, client.channel_manager_address, 0)
def test_static_price(empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address proxy.add_paywalled_resource(StaticPriceResource, '/resource', 3) # test GET response = requests.get(endpoint_url + '/resource') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 3 channel = client.get_suitable_channel(headers.receiver_address, int(headers.price) * 4) wait_for_blocks(6) channel.update_balance(int(headers.price)) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource', headers=headers) assert response.status_code == 200 assert response.text.strip() == 'GET' assert_method(requests.post, endpoint_url + '/resource', headers, channel, 'POST') assert_method(requests.put, endpoint_url + '/resource', headers, channel, 'PUT') assert_method(requests.delete, endpoint_url + '/resource', headers, channel, 'DEL')
def test_explicit_json( empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks ): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address proxy.add_paywalled_resource(JSONResource, '/resource', 3) # test GET response = requests.get(endpoint_url + '/resource') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 3 channel = client.get_suitable_channel(headers.receiver_address, int(headers.price) * 4) wait_for_blocks(6) channel.update_balance(int(headers.price)) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource', headers=headers) assert response.status_code == 200 # If headers don't merge properly, this results in 'application/json,application/json'. assert response.headers['Content-Type'] == 'application/json' assert response.json() == {'GET': 1}
def test_explicit_json(empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address proxy.add_paywalled_resource(JSONResource, '/resource', 3) # test GET response = requests.get(endpoint_url + '/resource') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 3 channel = client.get_suitable_channel(headers.receiver_address, int(headers.price) * 4) wait_for_blocks(6) channel.update_balance(int(headers.price)) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource', headers=headers) assert response.status_code == 200 # If headers don't merge properly, this results in 'application/json,application/json'. assert response.headers['Content-Type'] == 'application/json' assert response.json() == {'GET': 1}
def test_static_price( empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks ): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address proxy.add_paywalled_resource(StaticPriceResource, '/resource', 3) # test GET response = requests.get(endpoint_url + '/resource') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 3 channel = client.get_suitable_channel(headers.receiver_address, int(headers.price) * 4) wait_for_blocks(6) channel.update_balance(int(headers.price)) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource', headers=headers) assert response.status_code == 200 assert response.text.strip() == 'GET' assert_method(requests.post, endpoint_url + '/resource', headers, channel, 'POST') assert_method(requests.put, endpoint_url + '/resource', headers, channel, 'PUT') assert_method(requests.delete, endpoint_url + '/resource', headers, channel, 'DEL')
def test_full_cycle_error_500(session: Session, api_endpoint_address: str, token_address: str, channel_manager_address: str, receiver_address: str): session.initial_deposit = lambda x: x with requests_mock.mock() as server_mock: headers1 = Munch() headers1.token_address = token_address headers1.contract_address = channel_manager_address headers1.receiver_address = receiver_address headers1.price = '3' headers2 = Munch() headers2.cost = '3' headers1 = HTTPHeaders.serialize(headers1) headers2 = HTTPHeaders.serialize(headers2) url = 'http://{}/something'.format(api_endpoint_address) server_mock.get(url, [{ 'status_code': 402, 'headers': headers1 }, { 'status_code': 500, 'headers': {} }, { 'status_code': 200, 'headers': headers2, 'text': 'success' }]) response = session.get(url) # First cycle, request price. request = server_mock.request_history[0] assert request.path == '/something' assert request.method == 'GET' assert request.headers['RDN-Contract-Address'] == channel_manager_address # Second cycle, pay price but receive error. request = server_mock.request_history[1] assert request.path == '/something' assert request.method == 'GET' assert request.headers['RDN-Contract-Address'] == channel_manager_address assert request.headers['RDN-Balance'] == '3' assert session.channel.balance == 3 balance_sig_hex = encode_hex(session.channel.balance_sig) assert request.headers['RDN-Balance-Signature'] == balance_sig_hex # Third cycle, retry naively. request = server_mock.request_history[2] assert request.path == '/something' assert request.method == 'GET' assert request.headers['RDN-Contract-Address'] == channel_manager_address assert request.headers['RDN-Balance'] == '3' assert session.channel.balance == 3 assert request.headers['RDN-Balance-Signature'] == balance_sig_hex assert session.channel.balance_sig assert response.text == 'success'
def test_custom_headers( session: Session, api_endpoint_address: str, token_address: str, channel_manager_address: str, receiver_address: str ): session.initial_deposit = lambda x: x with requests_mock.mock(real_http=True) as server_mock: headers1 = Munch() headers1.token_address = token_address headers1.contract_address = channel_manager_address headers1.receiver_address = receiver_address headers1.price = '7' headers2 = Munch() headers2.cost = '7' headers1 = HTTPHeaders.serialize(headers1) headers2 = HTTPHeaders.serialize(headers2) url = 'http://{}/something'.format(api_endpoint_address) server_mock.get(url, [ {'status_code': 402, 'headers': headers1}, {'status_code': 200, 'headers': headers2, 'text': 'success'} ]) response = session.get(url, headers={ 'someheader': 'somevalue', # This should override the actual balance but doesn't actually make sense. 'RDN-Balance': '5' }) # Filter out any requests made to the ethereum node. request_history = [request for request in server_mock.request_history if request.port == 5000] # First cycle, request price. request = request_history[0] assert request.path == '/something' assert request.method == 'GET' assert request.headers['RDN-Contract-Address'] == channel_manager_address assert request.headers['RDN-Balance'] == '5' assert request.headers['someheader'] == 'somevalue' # Second cycle, pay price. request = request_history[1] assert request.path == '/something' assert request.method == 'GET' assert request.headers['RDN-Contract-Address'] == channel_manager_address assert request.headers['RDN-Balance'] == '5' assert request.headers['someheader'] == 'somevalue' assert session.channel.balance == 7 balance_sig_hex = encode_hex(session.channel.balance_sig) assert request.headers['RDN-Balance-Signature'] == balance_sig_hex assert session.channel.balance_sig assert response.text == 'success'
def test_get(empty_proxy: PaywalledProxy, api_endpoint_address: str, channel_manager_address: str, token_address: str, sender_address: str, receiver_address: str, client: Client, wait_for_blocks): """ Test with manual client interaction for isolated server testing. Note: Debug in microraiden.proxy.resources.expensive for most of the server response logic. """ es_mock = ElasticsearchBackend(None) es_mock.search = mock.Mock(return_value=Resource( price=5, content='success', expires_at=time.time() + 30)) server = APIServer(empty_proxy, es=es_mock) api_path = 'http://' + api_endpoint_address # Request price (and cache resource). body = {'query': 'query something'} url = api_path + '/some_index/some_type/_search' response = requests.get(url, json=body) print(response.content) assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert headers.token_address == token_address assert headers.contract_address == channel_manager_address assert headers.receiver_address == receiver_address price = int(headers.price) assert price == 5 assert len(server.resource_cache) == 1 # Perform payment and request same resource again. Include payment information in headers. channel = client.get_suitable_channel(receiver_address, price) # Server requires some confirmations, so mine some blocks. wait_for_blocks(10) channel.create_transfer(price) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = sender_address headers.receiver_address = receiver_address headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(url, headers=headers, json=body) headers = HTTPHeaders.deserialize(response.headers) assert 'nonexisting_channel' not in headers, 'Server should acknowledge the created channel.' assert 'insuf_confs' not in headers, 'Server should acknowledge the created channel.' assert 'invalid_amount' not in headers, 'The correct amount should have been sent.' assert response.status_code == 200 assert response.json() == 'success' assert len(server.resource_cache) == 1 es_mock.search.assert_called_once_with(index='some_index', doc_type='some_type', body={'query': 'query something'})
def test_custom_headers(default_http_client: DefaultHTTPClient, api_endpoint_address: str, token_address: str, channel_manager_address: str, receiver_address: str): default_http_client.initial_deposit = lambda x: x with requests_mock.mock() as server_mock: headers1 = Munch() headers1.token_address = token_address headers1.contract_address = channel_manager_address headers1.receiver_address = receiver_address headers1.price = '7' headers2 = Munch() headers2.cost = '7' headers1 = HTTPHeaders.serialize(headers1) headers2 = HTTPHeaders.serialize(headers2) url = 'http://{}/something'.format(api_endpoint_address) server_mock.get(url, [{ 'status_code': 402, 'headers': headers1 }, { 'status_code': 200, 'headers': headers2, 'text': 'success' }]) response = default_http_client.get( url, headers={ 'someheader': 'somevalue', # This should override the actual balance but doesn't actually make sense. 'RDN-Balance': '5' }) # First cycle, request price. request = server_mock.request_history[0] assert request.path == '/something' assert request.method == 'GET' assert request.headers['RDN-Contract-Address'] == channel_manager_address assert request.headers['RDN-Balance'] == '5' assert request.headers['someheader'] == 'somevalue' # Second cycle, pay price. request = server_mock.request_history[1] assert request.path == '/something' assert request.method == 'GET' assert request.headers['RDN-Contract-Address'] == channel_manager_address assert request.headers['RDN-Balance'] == '5' assert request.headers['someheader'] == 'somevalue' channel = default_http_client.get_channel(url) assert channel.balance == 7 balance_sig_hex = encode_hex(channel.balance_sig) assert request.headers['RDN-Balance-Signature'] == balance_sig_hex assert channel.balance_sig assert response.text == 'success'
def test_dynamic_price(empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address price_cycle = cycle([1, 2, 3, 4, 5]) url_to_price = {} # type: Dict def price_fn(url: str): if url in url_to_price: price = url_to_price[url] else: price = next(price_cycle) url_to_price[url] = price return price proxy.add_paywalled_resource(DynamicPriceResource, '/resource_<int:res_id>', price_fn) response = requests.get(endpoint_url + '/resource_3') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 1 response = requests.get(endpoint_url + '/resource_5') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 2 response = requests.get(endpoint_url + '/resource_2') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 3 response = requests.get(endpoint_url + '/resource_3') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 1 channel = client.get_suitable_channel(headers.receiver_address, 2) wait_for_blocks(6) channel.update_balance(2) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource_5', headers=headers) assert response.status_code == 200 assert response.text.strip() == '5'
def test_full_cycle_error_500(session: Session, api_endpoint_address: str, token_address: str, channel_manager_address: str, receiver_address: str): session.initial_deposit = lambda x: x with requests_mock.mock(real_http=True) as server_mock: headers1 = Munch() headers1.token_address = token_address headers1.contract_address = channel_manager_address headers1.receiver_address = receiver_address headers1.price = '3' headers2 = Munch() headers2.cost = '3' headers1 = HTTPHeaders.serialize(headers1) headers2 = HTTPHeaders.serialize(headers2) url = 'http://{}/something'.format(api_endpoint_address) server_mock.get(url, [{ 'status_code': 402, 'headers': headers1 }, { 'status_code': 500, 'headers': {} }]) response = session.get(url) # Filter out any requests made to the ethereum node. request_history = [ request for request in server_mock.request_history if request.port == 5000 ] # First cycle, request price. request = request_history[0] assert request.path == '/something' assert request.method == 'GET' assert request.headers['RDN-Contract-Address'] == channel_manager_address # Second cycle, pay price but receive error. request = request_history[1] assert request.path == '/something' assert request.method == 'GET' assert request.headers['RDN-Contract-Address'] == channel_manager_address assert request.headers['RDN-Balance'] == '3' assert session.channel.balance == 3 balance_sig_hex = encode_hex(session.channel.balance_sig) assert request.headers['RDN-Balance-Signature'] == balance_sig_hex assert response.status_code == 500
def test_full_cycle_success_post(session: Session, api_endpoint_address: str, token_address: str, channel_manager_address: str, receiver_address: str): session.initial_deposit = lambda x: x with requests_mock.mock() as server_mock: headers1 = Munch() headers1.token_address = token_address headers1.contract_address = channel_manager_address headers1.receiver_address = receiver_address headers1.price = '7' headers2 = Munch() headers2.cost = '7' headers1 = HTTPHeaders.serialize(headers1) headers2 = HTTPHeaders.serialize(headers2) url = 'http://{}/something'.format(api_endpoint_address) server_mock.post(url, [{ 'status_code': 402, 'headers': headers1 }, { 'status_code': 200, 'headers': headers2, 'text': 'success' }]) response = session.post(url, json={'somefield': 'somevalue'}) # First cycle, request price. request = server_mock.request_history[0] assert request.path == '/something' assert request.method == 'POST' assert request.headers['RDN-Contract-Address'] == channel_manager_address assert request.json()['somefield'] == 'somevalue' # Second cycle, pay price. request = server_mock.request_history[1] assert request.path == '/something' assert request.method == 'POST' assert request.headers['RDN-Contract-Address'] == channel_manager_address assert request.headers['RDN-Balance'] == '7' assert request.json()['somefield'] == 'somevalue' assert session.channel.balance == 7 balance_sig_hex = encode_hex(session.channel.balance_sig) assert request.headers['RDN-Balance-Signature'] == balance_sig_hex assert session.channel.balance_sig assert response.text == 'success'
def test_method_price(empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address proxy.add_paywalled_resource(DynamicMethodResource, '/resource', resource_class_args=(42, ), resource_class_kwargs={'bar': 9814072356}) # test GET response = requests.get(endpoint_url + '/resource') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 1 channel = client.get_suitable_channel(headers.receiver_address, 1 + 2 + 3 + 4) wait_for_blocks(6) channel.update_balance(int(headers.price)) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource', headers=headers) assert response.status_code == 200 assert response.text.strip() == 'GET' assert_method(requests.post, endpoint_url + '/resource', headers, channel, 'POST', expected_price=2) assert_method(requests.put, endpoint_url + '/resource', headers, channel, 'PUT', expected_price=3) assert_method(requests.delete, endpoint_url + '/resource', headers, channel, 'DEL', expected_price=4)
def test_full_cycle_error_500( session: Session, api_endpoint_address: str, token_address: str, channel_manager_address: str, receiver_address: str ): session.initial_deposit = lambda x: x with requests_mock.mock(real_http=True) as server_mock: headers1 = Munch() headers1.token_address = token_address headers1.contract_address = channel_manager_address headers1.receiver_address = receiver_address headers1.price = '3' headers2 = Munch() headers2.cost = '3' headers1 = HTTPHeaders.serialize(headers1) headers2 = HTTPHeaders.serialize(headers2) url = 'http://{}/something'.format(api_endpoint_address) server_mock.get(url, [ {'status_code': 402, 'headers': headers1}, {'status_code': 500, 'headers': {}} ]) response = session.get(url) # Filter out any requests made to the ethereum node. request_history = [request for request in server_mock.request_history if request.port == 5000] # First cycle, request price. request = request_history[0] assert request.path == '/something' assert request.method == 'GET' assert request.headers['RDN-Contract-Address'] == channel_manager_address # Second cycle, pay price but receive error. request = request_history[1] assert request.path == '/something' assert request.method == 'GET' assert request.headers['RDN-Contract-Address'] == channel_manager_address assert request.headers['RDN-Balance'] == '3' assert session.channel.balance == 3 balance_sig_hex = encode_hex(session.channel.balance_sig) assert request.headers['RDN-Balance-Signature'] == balance_sig_hex assert response.status_code == 500
def test_method_price( empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks ): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address proxy.add_paywalled_resource( DynamicMethodResource, '/resource', resource_class_args=(42,), resource_class_kwargs={'bar': 9814072356}) # test GET response = requests.get(endpoint_url + '/resource') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 1 channel = client.get_suitable_channel(headers.receiver_address, 1 + 2 + 3 + 4) wait_for_blocks(6) channel.update_balance(int(headers.price)) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource', headers=headers) assert response.status_code == 200 assert response.text.strip() == 'GET' assert_method(requests.post, endpoint_url + '/resource', headers, channel, 'POST', expected_price=2) assert_method(requests.put, endpoint_url + '/resource', headers, channel, 'PUT', expected_price=3) assert_method(requests.delete, endpoint_url + '/resource', headers, channel, 'DEL', expected_price=4)
def test_get_expired(empty_proxy: PaywalledProxy, api_endpoint_address: str, sender_address: str, receiver_address: str, client: Client, wait_for_blocks): """ Test with manual client interaction for isolated server testing. Note: Debug in microraiden.proxy.resources.expensive for most of the server response logic. """ es_mock = ElasticsearchBackend(None) es_mock.search = mock.Mock(return_value=Resource( price=5, content='success', expires_at=time.time() + 0.05)) APIServer(empty_proxy, es=es_mock) api_path = 'http://' + api_endpoint_address # Request price (and cache resource). body = {'query': 'query something'} url = api_path + '/some_index/some_type/_search' response = requests.get(url, json=body) assert response.status_code == 402 # Perform payment and request same resource again. Include payment information in headers. channel = client.get_suitable_channel(receiver_address, 5) # Server requires some confirmations, so mine some blocks. wait_for_blocks(10) channel.create_transfer(5) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = sender_address headers.receiver_address = receiver_address headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) # Make sure the price changes for the next request. es_mock.search = mock.Mock(return_value=Resource( price=3, content='success', expires_at=time.time() + 0.05)) # Let former query expire. gevent.sleep(0.1) # Query same resource again with the old expired price. response = requests.get(url, headers=headers, json=body) assert response.status_code == 402 assert response.headers[HTTPHeaders.PRICE] == '3' channel.update_balance(3) headers[HTTPHeaders.BALANCE] = str(channel.balance) headers[HTTPHeaders.BALANCE_SIGNATURE] = encode_hex(channel.balance_sig) response = requests.get(url, headers=headers, json=body) assert response.json() == 'success' es_mock.search.call_args_list == [{ 'query': 'query something' }, { 'query': 'query something' }]
def assert_method(method, url, headers, channel, expected_reply, expected_price=3): # test POST response = method(url, headers=headers) assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == expected_price channel.update_balance(int(headers.sender_balance) + int(headers.price)) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = method(url, headers=headers) assert response.status_code == 200 assert response.text.strip() == expected_reply
def assert_method(method, url, headers, channel, expected_reply): # test POST response = method(url, headers=headers) assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 3 channel.update_balance(int(headers.sender_balance) + int(headers.price)) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = method(url, headers=headers) assert response.status_code == 200 assert response.text.strip() == expected_reply
def test_requests( patched_contract, web3: Web3, sender_privkey: str, api_endpoint_address: str, token_address: str, channel_manager_address: str, receiver_address: str, revert_chain ): import microraiden.requests with requests_mock.mock() as server_mock: headers1 = Munch() headers1.token_address = token_address headers1.contract_address = channel_manager_address headers1.receiver_address = receiver_address headers1.price = '7' headers2 = Munch() headers2.cost = '7' headers1 = HTTPHeaders.serialize(headers1) headers2 = HTTPHeaders.serialize(headers2) url = 'http://{}/something'.format(api_endpoint_address) server_mock.get(url, [ {'status_code': 402, 'headers': headers1}, {'status_code': 200, 'headers': headers2, 'text': 'success'} ]) response = microraiden.requests.get( url, retry_interval=0.1, private_key=sender_privkey, web3=web3, channel_manager_address=channel_manager_address ) assert response.text == 'success'
def test_requests( patched_contract, web3: Web3, sender_privkey: str, api_endpoint_address: str, token_address: str, channel_manager_address: str, receiver_address: str, revert_chain ): import microraiden.requests with requests_mock.mock(real_http=True) as server_mock: headers1 = Munch() headers1.token_address = token_address headers1.contract_address = channel_manager_address headers1.receiver_address = receiver_address headers1.price = '7' headers2 = Munch() headers2.cost = '7' headers1 = HTTPHeaders.serialize(headers1) headers2 = HTTPHeaders.serialize(headers2) url = 'http://{}/something'.format(api_endpoint_address) server_mock.get(url, [ {'status_code': 402, 'headers': headers1}, {'status_code': 200, 'headers': headers2, 'text': 'success'} ]) response = microraiden.requests.get( url, retry_interval=0.1, private_key=sender_privkey, web3=web3, channel_manager_address=channel_manager_address ) assert response.text == 'success'
def test_full_cycle_adapt_balance( session: Session, api_endpoint_address: str, token_address: str, channel_manager_address: str, receiver_address: str ): # Simulate a lost balance signature. client = session.client channel = client.get_suitable_channel(receiver_address, 10, initial_deposit=lambda x: 2 * x) channel.create_transfer(3) lost_balance_sig = channel.balance_sig channel.update_balance(0) with requests_mock.mock() as server_mock: headers1 = Munch() headers1.token_address = token_address headers1.contract_address = channel_manager_address headers1.receiver_address = receiver_address headers1.price = '7' headers2 = headers1.copy() headers2.invalid_amount = '1' headers2.sender_balance = '3' headers2.balance_signature = encode_hex(lost_balance_sig) headers3 = Munch() headers3.cost = '7' headers1 = HTTPHeaders.serialize(headers1) headers2 = HTTPHeaders.serialize(headers2) headers3 = HTTPHeaders.serialize(headers3) url = 'http://{}/something'.format(api_endpoint_address) server_mock.get(url, [ {'status_code': 402, 'headers': headers1}, {'status_code': 402, 'headers': headers2}, {'status_code': 200, 'headers': headers3, 'text': 'success'} ]) response = session.get(url) # First cycle, request price. request = server_mock.request_history[0] assert request.path == '/something' assert request.method == 'GET' assert request.headers['RDN-Contract-Address'] == channel_manager_address # Second cycle, pay price based on outdated balance. request = server_mock.request_history[1] assert request.path == '/something' assert request.method == 'GET' assert request.headers['RDN-Contract-Address'] == channel_manager_address assert request.headers['RDN-Balance'] == '7' assert request.headers['RDN-Balance-Signature'] # Third cycle, adapt new balance and pay price again. request = server_mock.request_history[2] assert request.path == '/something' assert request.method == 'GET' assert request.headers['RDN-Contract-Address'] == channel_manager_address assert request.headers['RDN-Balance'] == '10' assert session.channel.balance == 10 balance_sig_hex = encode_hex(session.channel.balance_sig) assert request.headers['RDN-Balance-Signature'] == balance_sig_hex assert session.channel.balance_sig assert response.text == 'success'
def test_dynamic_price( empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks ): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address price_cycle = cycle([1, 2, 3, 4, 5]) url_to_price = {} # type: Dict def price_fn(): url = request.path if int(url.split('_')[-1]) == 0: return 0 if url in url_to_price: price = url_to_price[url] else: price = next(price_cycle) url_to_price[url] = price return price proxy.add_paywalled_resource( DynamicPriceResource, '/resource_<int:res_id>', price=price_fn ) response = requests.get(endpoint_url + '/resource_3') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 1 response = requests.get(endpoint_url + '/resource_5') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 2 response = requests.get(endpoint_url + '/resource_2') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 3 response = requests.get(endpoint_url + '/resource_3') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 1 response = requests.get(endpoint_url + '/resource_0') assert response.status_code == 200 assert response.text.strip() == '0' channel = client.get_suitable_channel(headers.receiver_address, 2) wait_for_blocks(6) channel.update_balance(2) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource_5', headers=headers) assert response.status_code == 200 assert response.text.strip() == '5'
def test_full_cycle_adapt_balance( session: Session, api_endpoint_address: str, token_address: str, channel_manager_address: str, receiver_address: str ): # Simulate a lost balance signature. client = session.client channel = client.get_suitable_channel(receiver_address, 10, initial_deposit=lambda x: 2 * x) channel.create_transfer(3) lost_balance_sig = channel.balance_sig channel.update_balance(0) with requests_mock.mock(real_http=True) as server_mock: headers1 = Munch() headers1.token_address = token_address headers1.contract_address = channel_manager_address headers1.receiver_address = receiver_address headers1.price = '7' headers2 = headers1.copy() headers2.invalid_amount = '1' headers2.sender_balance = '3' headers2.balance_signature = encode_hex(lost_balance_sig) headers3 = Munch() headers3.cost = '7' headers1 = HTTPHeaders.serialize(headers1) headers2 = HTTPHeaders.serialize(headers2) headers3 = HTTPHeaders.serialize(headers3) url = 'http://{}/something'.format(api_endpoint_address) server_mock.get(url, [ {'status_code': 402, 'headers': headers1}, {'status_code': 402, 'headers': headers2}, {'status_code': 200, 'headers': headers3, 'text': 'success'} ]) response = session.get(url) # Filter out any requests made to the ethereum node. request_history = [request for request in server_mock.request_history if request.port == 5000] # First cycle, request price. request = request_history[0] assert request.path == '/something' assert request.method == 'GET' assert request.headers['RDN-Contract-Address'] == channel_manager_address # Second cycle, pay price based on outdated balance. request = request_history[1] assert request.path == '/something' assert request.method == 'GET' assert request.headers['RDN-Contract-Address'] == channel_manager_address assert request.headers['RDN-Balance'] == '7' assert request.headers['RDN-Balance-Signature'] # Third cycle, adapt new balance and pay price again. request = request_history[2] assert request.path == '/something' assert request.method == 'GET' assert request.headers['RDN-Contract-Address'] == channel_manager_address assert request.headers['RDN-Balance'] == '10' assert session.channel.balance == 10 balance_sig_hex = encode_hex(session.channel.balance_sig) assert request.headers['RDN-Balance-Signature'] == balance_sig_hex assert session.channel.balance_sig assert response.text == 'success'