From e07334859b481ae4935c3254c1749f841291abc5 Mon Sep 17 00:00:00 2001 From: Vincent Texier <vit@free.fr> Date: Mon, 16 Jul 2018 12:14:24 +0200 Subject: [PATCH] issue #56 WIP - Support Elasticsearch/Duniter4j nodes ES_CORE_API with example --- duniterpy/api/client.py | 3 ++ duniterpy/api/endpoint.py | 53 ++++++++++++++++++++++++-- examples/request_data_elasticsearch.py | 42 ++++++++++++++++++++ 3 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 examples/request_data_elasticsearch.py diff --git a/duniterpy/api/client.py b/duniterpy/api/client.py index efffcb64..f1b53e85 100644 --- a/duniterpy/api/client.py +++ b/duniterpy/api/client.py @@ -203,6 +203,9 @@ class Client: else: self.endpoint = _endpoint + if isinstance(self.endpoint, endpoint.UnknownEndpoint): + raise NotImplementedError("{0} endpoint in not supported".format(self.endpoint.api)) + # if no user session... if session is None: # open a session diff --git a/duniterpy/api/endpoint.py b/duniterpy/api/endpoint.py index 79ceaae0..0d1acd8b 100644 --- a/duniterpy/api/endpoint.py +++ b/duniterpy/api/endpoint.py @@ -319,11 +319,56 @@ class WS2PEndpoint(Endpoint): return hash((self.ws2pid, self.server, self.port, self.path)) +class ESCoreEndpoint(Endpoint): + API = "ES_CORE_API" + re_inline = re.compile( + '^ES_CORE_API ((?:{host_regex})|(?:{ipv4_regex})) ([0-9]+)$'.format(host_regex=HOST_REGEX, + ipv4_regex=IPV4_REGEX)) + + def __init__(self, server, port): + self.server = server + self.port = port + + @classmethod + def from_inline(cls, inline): + m = ESCoreEndpoint.re_inline.match(inline) + if m is None: + raise MalformedDocumentError(ESCoreEndpoint.API) + server = m.group(1) + port = int(m.group(2)) + return cls(server, port) + + def inline(self): + inlined = [str(info) for info in (self.server, self.port) if info] + return ESCoreEndpoint.API + " " + " ".join(inlined) + + def conn_handler(self, session: aiohttp.ClientSession, proxy: str = None) -> ConnectionHandler: + """ + Return connection handler instance for the endpoint + + :param aiohttp.ClientSession session: AIOHTTP client session instance + :param str proxy: Proxy url + :rtype: ConnectionHandler + """ + return ConnectionHandler("https", "wss", self.server, self.port, "", proxy, session) + + def __str__(self): + return self.inline() + + def __eq__(self, other): + if isinstance(other, ESCoreEndpoint): + return self.server == other.server and self.port == other.port + else: + return False + + def __hash__(self): + return hash((self.server, self.port)) + + class ESUserEndpoint(Endpoint): API = "ES_USER_API" re_inline = re.compile( - '^ES_USER_API ((?:{host_regex})|(?:{ipv4_regex})) ([0-9]+)$'.format(ws2pid_regex=WS2PID_REGEX, - host_regex=HOST_REGEX, + '^ES_USER_API ((?:{host_regex})|(?:{ipv4_regex})) ([0-9]+)$'.format(host_regex=HOST_REGEX, ipv4_regex=IPV4_REGEX)) def __init__(self, server, port): @@ -369,8 +414,7 @@ class ESUserEndpoint(Endpoint): class ESSubscribtionEndpoint(Endpoint): API = "ES_SUBSCRIPTION_API" re_inline = re.compile( - '^ES_SUBSCRIPTION_API ((?:{host_regex})|(?:{ipv4_regex})) ([0-9]+)$'.format(ws2pid_regex=WS2PID_REGEX, - host_regex=HOST_REGEX, + '^ES_SUBSCRIPTION_API ((?:{host_regex})|(?:{ipv4_regex})) ([0-9]+)$'.format(host_regex=HOST_REGEX, ipv4_regex=IPV4_REGEX)) def __init__(self, server, port): @@ -417,6 +461,7 @@ MANAGED_API = { BMAEndpoint.API: BMAEndpoint, SecuredBMAEndpoint.API: SecuredBMAEndpoint, WS2PEndpoint.API: WS2PEndpoint, + ESCoreEndpoint.API: ESCoreEndpoint, ESUserEndpoint.API: ESUserEndpoint, ESSubscribtionEndpoint.API: ESSubscribtionEndpoint } diff --git a/examples/request_data_elasticsearch.py b/examples/request_data_elasticsearch.py new file mode 100644 index 00000000..ba4d1959 --- /dev/null +++ b/examples/request_data_elasticsearch.py @@ -0,0 +1,42 @@ +import asyncio + +from duniterpy.api.client import Client + +# Duniter4j ES API documentation: https://git.duniter.org/clients/java/duniter4j/blob/master/src/site/markdown/ES_API.md +# Duniter4j project: https://git.duniter.org/clients/java/duniter4j/ + +# CONFIG ####################################### + +# 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] +# Here we use the secure BASIC_MERKLED_API (BMAS) +ES_CORE_ENDPOINT = "ES_CORE_API g1-test.data.duniter.fr 443" + + +################################################ + + +async def main(): + """ + Main code (synchronous requests) + """ + # Create Client from endpoint string in Duniter format + client = Client(ES_CORE_ENDPOINT) + + # Get the current node (direct REST GET request) + print("\nGET g1-test/block/current/_source:") + response = await client.get('g1-test/block/current/_source') + print(response) + + # Get the node number 2 with only selected fields (direct REST GET request) + print("\nGET g1-test/block/2/_source:") + response = await client.get('g1-test/block/2/_source', {'_source': 'number,hash,dividend,membersCount'}) + print(response) + + # Close client aiohttp session + await client.close() + + +# Latest duniter-python-api is asynchronous and you have to use asyncio, an asyncio loop and a "as" on the data. +# ( https://docs.python.org/3/library/asyncio.html ) +asyncio.get_event_loop().run_until_complete(main()) -- GitLab