Skip to content
Snippets Groups Projects
Commit b4653ef0 authored by Vincent Texier's avatar Vincent Texier
Browse files

[enh] #58 request_id argument is mandatory in ws2p requests

Improve example structure and use mandatory request_id
parent 29dd3bcd
No related branches found
No related tags found
No related merge requests found
...@@ -183,17 +183,14 @@ REQUIREMENTS_RESPONSE_SCHEMA = { ...@@ -183,17 +183,14 @@ REQUIREMENTS_RESPONSE_SCHEMA = {
} }
def get_current(request_id: Optional[str] = None) -> str: def get_current(request_id: str) -> str:
""" """
Return ws2p getCurrent() request as json string Return ws2p getCurrent() request as json string
:return: :return:
""" """
if request_id is None: if not re.fullmatch("^[0-9a-zA-Z]{8}$", request_id):
request_id = get_ws2p_challenge()[:8] raise Exception("Invalid ws2p request unique id")
else:
if not re.fullmatch("^[0-9a-zA-Z]{8}$", request_id):
raise Exception("Invalid ws2p request unique id")
return json.dumps({ return json.dumps({
"reqId": request_id, "reqId": request_id,
"body": { "body": {
...@@ -203,17 +200,14 @@ def get_current(request_id: Optional[str] = None) -> str: ...@@ -203,17 +200,14 @@ def get_current(request_id: Optional[str] = None) -> str:
}) })
def get_block(block_number: int, request_id: Optional[str] = None) -> str: def get_block(request_id: str, block_number: int) -> str:
""" """
Return ws2p getBlock() request as json string Return ws2p getBlock() request as json string
:return: :return:
""" """
if request_id is None: if not re.fullmatch("^[0-9a-zA-Z]{8}$", request_id):
request_id = get_ws2p_challenge()[:8] raise Exception("Invalid ws2p request unique id")
else:
if not re.fullmatch("^[0-9a-zA-Z]{8}$", request_id):
raise Exception("Invalid ws2p request unique id")
return json.dumps({ return json.dumps({
"reqId": request_id, "reqId": request_id,
"body": { "body": {
...@@ -225,17 +219,14 @@ def get_block(block_number: int, request_id: Optional[str] = None) -> str: ...@@ -225,17 +219,14 @@ def get_block(block_number: int, request_id: Optional[str] = None) -> str:
}) })
def get_blocks(from_number: int, count: int, request_id: Optional[str] = None) -> str: def get_blocks(request_id: str, from_number: int, count: int) -> str:
""" """
Return ws2p getBlocks(fromNumber, count) request as json string Return ws2p getBlocks(fromNumber, count) request as json string
:return: :return:
""" """
if request_id is None: if not re.fullmatch("^[0-9a-zA-Z]{8}$", request_id):
request_id = get_ws2p_challenge()[:8] raise Exception("Invalid ws2p request unique id")
else:
if not re.fullmatch("^[0-9a-zA-Z]{8}$", request_id):
raise Exception("Invalid ws2p request unique id")
return json.dumps({ return json.dumps({
"reqId": request_id, "reqId": request_id,
"body": { "body": {
...@@ -248,17 +239,14 @@ def get_blocks(from_number: int, count: int, request_id: Optional[str] = None) - ...@@ -248,17 +239,14 @@ def get_blocks(from_number: int, count: int, request_id: Optional[str] = None) -
}) })
def get_requirements_pending(min_cert: int, request_id: Optional[str] = None) -> str: def get_requirements_pending(request_id: str, min_cert: int) -> str:
""" """
Return ws2p getRequirementsPending(minCert) request as json string Return ws2p getRequirementsPending(minCert) request as json string
:return: :return:
""" """
if request_id is None: if not re.fullmatch("^[0-9a-zA-Z]{8}$", request_id):
request_id = get_ws2p_challenge()[:8] raise Exception("Invalid ws2p request unique id")
else:
if not re.fullmatch("^[0-9a-zA-Z]{8}$", request_id):
raise Exception("Invalid ws2p request unique id")
return json.dumps({ return json.dumps({
"reqId": request_id, "reqId": request_id,
"body": { "body": {
...@@ -267,4 +255,4 @@ def get_requirements_pending(min_cert: int, request_id: Optional[str] = None) -> ...@@ -267,4 +255,4 @@ def get_requirements_pending(min_cert: int, request_id: Optional[str] = None) ->
"minCert": min_cert "minCert": min_cert
} }
} }
}) })
\ No newline at end of file
import asyncio import asyncio
import json
import time
from _socket import gaierror from _socket import gaierror
...@@ -6,6 +8,9 @@ import aiohttp ...@@ -6,6 +8,9 @@ import aiohttp
import jsonschema import jsonschema
from jsonschema import ValidationError from jsonschema import ValidationError
from duniterpy.helpers import get_ws2p_challenge
from duniterpy.key import SigningKey
from duniterpy.api import ws2p from duniterpy.api import ws2p
from duniterpy.api.ws2p import requests from duniterpy.api.ws2p import requests
from duniterpy.documents.ws2p.messages import Connect, Ack, Ok from duniterpy.documents.ws2p.messages import Connect, Ack, Ok
...@@ -16,8 +21,6 @@ from duniterpy.api.client import Client, parse_text ...@@ -16,8 +21,6 @@ from duniterpy.api.client import Client, parse_text
# You can either use a complete defined endpoint : [NAME_OF_THE_API] [DOMAIN] [IPv4] [IPv6] [PORT] # You can either use a complete defined endpoint : [NAME_OF_THE_API] [DOMAIN] [IPv4] [IPv6] [PORT]
# or the simple definition : [NAME_OF_THE_API] [DOMAIN] [PORT] # or the simple definition : [NAME_OF_THE_API] [DOMAIN] [PORT]
# Here we use the WS2P API (WS2P) # Here we use the WS2P API (WS2P)
from duniterpy.key import SigningKey
WS2P_ENDPOINT = "WS2P 2f731dcd 127.0.0.1 20900" WS2P_ENDPOINT = "WS2P 2f731dcd 127.0.0.1 20900"
CURRENCY = "g1-test" CURRENCY = "g1-test"
...@@ -63,6 +66,9 @@ async def main(): ...@@ -63,6 +66,9 @@ async def main():
async with ws_connection as ws: async with ws_connection as ws:
print("Connected successfully to web socket endpoint") print("Connected successfully to web socket endpoint")
# START HANDSHAKE #######################################################
print("\nSTART HANDSHAKE...")
print("Send CONNECT message") print("Send CONNECT message")
await ws.send_str(connect_message) await ws.send_str(connect_message)
...@@ -74,45 +80,52 @@ async def main(): ...@@ -74,45 +80,52 @@ async def main():
try: try:
# Validate json string with jsonschema and return a dict # Validate json string with jsonschema and return a dict
data = parse_text(msg.data, ws2p.network.WS2P_CONNECT_MESSAGE_SCHEMA) data = parse_text(msg.data, ws2p.network.WS2P_CONNECT_MESSAGE_SCHEMA)
print("Received a CONNECT message")
remote_connect_document = Connect(CURRENCY, data["pub"], data["challenge"], data["sig"])
print("Received CONNECT message signature is valid")
ack_message = Ack(CURRENCY, signing_key.pubkey,
remote_connect_document.challenge).get_signed_json(
signing_key)
# send ACK message
print("Send ACK message...")
await ws.send_str(ack_message)
except jsonschema.exceptions.ValidationError: except jsonschema.exceptions.ValidationError:
try: try:
# Validate json string with jsonschema and return a dict # Validate json string with jsonschema and return a dict
data = parse_text(msg.data, ws2p.network.WS2P_ACK_MESSAGE_SCHEMA) data = parse_text(msg.data, ws2p.network.WS2P_ACK_MESSAGE_SCHEMA)
print("Received a ACK message")
# create ACK document from ACK response to verify signature
Ack(CURRENCY, data["pub"], connect_document.challenge, data["sig"])
print("Received ACK message signature is valid")
# Si ACK response ok, create OK message
ok_message = Ok(CURRENCY, signing_key.pubkey, connect_document.challenge).get_signed_json(
signing_key)
# send OK message
print("Send OK message...")
await ws.send_str(ok_message)
except jsonschema.exceptions.ValidationError: except jsonschema.exceptions.ValidationError:
try: try:
# Validate json string with jsonschema and return a dict # Validate json string with jsonschema and return a dict
data = parse_text(msg.data, ws2p.network.WS2P_OK_MESSAGE_SCHEMA) data = parse_text(msg.data, ws2p.network.WS2P_OK_MESSAGE_SCHEMA)
print("Received a OK message")
Ok(CURRENCY, remote_connect_document.pubkey, connect_document.challenge, data["sig"])
print("Received OK message signature is valid")
# do not wait for messages anymore
break
except jsonschema.exceptions.ValidationError: except jsonschema.exceptions.ValidationError:
pass continue
print("Received a OK message")
Ok(CURRENCY, remote_connect_document.pubkey, connect_document.challenge, data["sig"])
print("Received OK message signature is valid")
# do not wait for messages anymore
break
print("Received a ACK message")
# create ACK document from ACK response to verify signature
Ack(CURRENCY, data["pub"], connect_document.challenge, data["sig"])
print("Received ACK message signature is valid")
# Si ACK response ok, create OK message
ok_message = Ok(CURRENCY, signing_key.pubkey, connect_document.challenge).get_signed_json(
signing_key)
# send OK message
print("Send OK message...")
await ws.send_str(ok_message)
continue
print("Received a CONNECT message")
remote_connect_document = Connect(CURRENCY, data["pub"], data["challenge"], data["sig"])
print("Received CONNECT message signature is valid")
ack_message = Ack(CURRENCY, signing_key.pubkey,
remote_connect_document.challenge).get_signed_json(
signing_key)
# send ACK message
print("Send ACK message...")
await ws.send_str(ack_message)
elif msg.type == aiohttp.WSMsgType.CLOSED: elif msg.type == aiohttp.WSMsgType.CLOSED:
# Connection is closed # Connection is closed
...@@ -121,86 +134,112 @@ async def main(): ...@@ -121,86 +134,112 @@ async def main():
# Connection error # Connection error
print("Web socket connection error !") print("Web socket connection error !")
# END HANDSHAKE #######################################################
print("END OF HANDSHAKE\n")
# send ws2p request # send ws2p request
print("Send getCurrent() request") print("Send getCurrent() request")
await ws.send_str(requests.get_current()) request_id = get_ws2p_challenge()[:8]
# receive response as string await ws.send_str(requests.get_current(request_id))
response = await ws.receive_str()
# wait response with request id
response_str = await ws.receive_str()
while "resId" not in json.loads(response_str) or (
"resId" in json.loads(response_str) and json.loads(response_str)["resId"] != request_id):
response_str = await ws.receive_str()
time.sleep(1)
try: try:
# check response format # check response format
parse_text(response, requests.BLOCK_RESPONSE_SCHEMA) parse_text(response_str, requests.BLOCK_RESPONSE_SCHEMA)
# if valid display response # if valid display response
print("Response: " + response) print("Response: " + response_str)
except ValidationError as exception: except ValidationError as exception:
# if invalid response... # if invalid response...
try: try:
# check error response format # check error response format
parse_text(response, requests.ERROR_RESPONSE_SCHEMA) parse_text(response_str, requests.ERROR_RESPONSE_SCHEMA)
# if valid, display error response # if valid, display error response
print("Error response: " + response) print("Error response: " + response_str)
except ValidationError as e: except ValidationError as e:
# if invalid, display exception on response validation # if invalid, display exception on response validation
print(exception) print(exception)
# send ws2p request # send ws2p request
print("Send getBlock(360000) request") print("Send getBlock(360000) request")
await ws.send_str(requests.get_block(360000)) request_id = get_ws2p_challenge()[:8]
# receive response as string await ws.send_str(requests.get_block(request_id, 360000))
response = await ws.receive_str()
# wait response with request id
response_str = await ws.receive_str()
while "resId" not in json.loads(response_str) or (
"resId" in json.loads(response_str) and json.loads(response_str)["resId"] != request_id):
response_str = await ws.receive_str()
time.sleep(1)
try: try:
# check response format # check response format
parse_text(response, requests.BLOCK_RESPONSE_SCHEMA) parse_text(response_str, requests.BLOCK_RESPONSE_SCHEMA)
# if valid display response # if valid display response
print("Response: " + response) print("Response: " + response_str)
except ValidationError as exception: except ValidationError as exception:
# if invalid response... # if invalid response...
try: try:
# check error response format # check error response format
parse_text(response, requests.ERROR_RESPONSE_SCHEMA) parse_text(response_str, requests.ERROR_RESPONSE_SCHEMA)
# if valid, display error response # if valid, display error response
print("Error response: " + response) print("Error response: " + response_str)
except ValidationError as e: except ValidationError as e:
# if invalid, display exception on response validation # if invalid, display exception on response validation
print(exception) print(exception)
# send ws2p request # send ws2p request
print("Send getBlocks(360000, 2) request") print("Send getBlocks(360000, 2) request")
await ws.send_str(requests.get_blocks(360000, 2)) request_id = get_ws2p_challenge()[:8]
# receive response as string await ws.send_str(requests.get_blocks(request_id, 360000, 2))
response = await ws.receive_str()
# wait response with request id
response_str = await ws.receive_str()
while "resId" not in json.loads(response_str) or (
"resId" in json.loads(response_str) and json.loads(response_str)["resId"] != request_id):
response_str = await ws.receive_str()
time.sleep(1)
try: try:
# check response format # check response format
parse_text(response, requests.BLOCKS_RESPONSE_SCHEMA) parse_text(response_str, requests.BLOCKS_RESPONSE_SCHEMA)
# if valid display response # if valid display response
print("Response: " + response) print("Response: " + response_str)
except ValidationError as exception: except ValidationError as exception:
# if invalid response... # if invalid response...
try: try:
# check error response format # check error response format
parse_text(response, requests.ERROR_RESPONSE_SCHEMA) parse_text(response_str, requests.ERROR_RESPONSE_SCHEMA)
# if valid, display error response # if valid, display error response
print("Error response: " + response) print("Error response: " + response_str)
except ValidationError as e: except ValidationError as e:
# if invalid, display exception on response validation # if invalid, display exception on response validation
print(exception) print(exception)
# send ws2p request # send ws2p request
print("Send getRequirementsPending(3) request") print("Send getRequirementsPending(3) request")
await ws.send_str(requests.get_requirements_pending(3)) request_id = get_ws2p_challenge()[:8]
# receive response as string await ws.send_str(requests.get_requirements_pending(request_id, 3))
response = await ws.receive_str() # wait response with request id
response_str = await ws.receive_str()
while "resId" not in json.loads(response_str) or (
"resId" in json.loads(response_str) and json.loads(response_str)["resId"] != request_id):
response_str = await ws.receive_str()
time.sleep(1)
try: try:
# check response format # check response format
parse_text(response, requests.REQUIREMENTS_RESPONSE_SCHEMA) parse_text(response_str, requests.REQUIREMENTS_RESPONSE_SCHEMA)
# if valid display response # if valid display response
print("Response: " + response) print("Response: " + response_str)
except ValidationError as exception: except ValidationError as exception:
# if invalid response... # if invalid response...
try: try:
# check error response format # check error response format
parse_text(response, requests.ERROR_RESPONSE_SCHEMA) parse_text(response_str, requests.ERROR_RESPONSE_SCHEMA)
# if valid, display error response # if valid, display error response
print("Error response: " + response) print("Error response: " + response_str)
except ValidationError as e: except ValidationError as e:
# if invalid, display exception on response validation # if invalid, display exception on response validation
print(exception) print(exception)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment