Skip to content

Commit 642d100

Browse files
committed
[NBA-39] add multiple nodes for web3 HTTPProvider (#1)
1 parent 608917b commit 642d100

File tree

1 file changed

+50
-28
lines changed

1 file changed

+50
-28
lines changed

web3/providers/rpc.py

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
1+
from eth_typing import (
2+
URI,
3+
)
4+
from eth_utils import (
5+
to_dict,
6+
)
17
import logging
8+
import random
9+
from requests import (
10+
RequestException,
11+
)
212
from typing import (
313
Any,
414
Dict,
@@ -8,13 +18,6 @@
818
Union,
919
)
1020

11-
from eth_typing import (
12-
URI,
13-
)
14-
from eth_utils import (
15-
to_dict,
16-
)
17-
1821
from web3._utils.http import (
1922
construct_user_agent,
2023
)
@@ -26,9 +29,15 @@
2629
from web3.datastructures import (
2730
NamedElementOnion,
2831
)
32+
from web3.exceptions import (
33+
CannotHandleRequest,
34+
)
2935
from web3.middleware import (
3036
http_retry_request_middleware,
3137
)
38+
from web3.providers import (
39+
BaseProvider,
40+
)
3241
from web3.types import (
3342
Middleware,
3443
RPCEndpoint,
@@ -42,32 +51,34 @@
4251

4352
class HTTPProvider(JSONBaseProvider):
4453
logger = logging.getLogger("web3.providers.HTTPProvider")
45-
endpoint_uri = None
54+
providers = None
4655
_request_args = None
4756
_request_kwargs = None
4857
# type ignored b/c conflict with _middlewares attr on BaseProvider
4958
_middlewares: Tuple[Middleware, ...] = NamedElementOnion([(http_retry_request_middleware, "http_retry_request")]) # type: ignore # noqa: E501
5059

5160
def __init__(
5261
self,
53-
endpoint_uri: Optional[Union[URI, str]] = None,
62+
providers: Union[list, str],
63+
randomize: Optional[bool] = False,
5464
request_kwargs: Optional[Any] = None,
5565
session: Optional[Any] = None,
5666
) -> None:
57-
if endpoint_uri is None:
58-
self.endpoint_uri = get_default_http_endpoint()
59-
else:
60-
self.endpoint_uri = URI(endpoint_uri)
61-
67+
if isinstance(providers, str):
68+
providers = [
69+
providers,
70+
]
71+
self.randomize = randomize
72+
self.providers = providers
6273
self._request_kwargs = request_kwargs or {}
6374

6475
if session:
65-
cache_and_return_session(self.endpoint_uri, session)
76+
cache_and_return_session(self.providers[0], session)
6677

6778
super().__init__()
6879

6980
def __str__(self) -> str:
70-
return f"RPC connection {self.endpoint_uri}"
81+
return "RPC connection {0}".format(self.providers)
7182

7283
@to_dict
7384
def get_request_kwargs(self) -> Iterable[Tuple[str, Any]]:
@@ -83,16 +94,27 @@ def get_request_headers(self) -> Dict[str, str]:
8394
}
8495

8596
def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
86-
self.logger.debug(
87-
f"Making request HTTP. URI: {self.endpoint_uri}, Method: {method}"
88-
)
8997
request_data = self.encode_rpc_request(method, params)
90-
raw_response = make_post_request(
91-
self.endpoint_uri, request_data, **self.get_request_kwargs()
92-
)
93-
response = self.decode_rpc_response(raw_response)
94-
self.logger.debug(
95-
f"Getting response HTTP. URI: {self.endpoint_uri}, "
96-
f"Method: {method}, Response: {response}"
97-
)
98-
return response
98+
if self.randomize:
99+
random.shuffle(self.providers)
100+
for provider in self.providers:
101+
provider_uri = URI(provider)
102+
self.logger.debug(
103+
"Making request HTTP. URI: %s, Method: %s", provider_uri, method
104+
)
105+
try:
106+
raw_response = make_post_request(
107+
provider_uri, request_data, **self.get_request_kwargs()
108+
)
109+
response = self.decode_rpc_response(raw_response)
110+
self.logger.debug(
111+
"Getting response HTTP. URI: %s, " "Method: %s, Response: %s",
112+
provider_uri,
113+
method,
114+
response,
115+
)
116+
return response
117+
except RequestException:
118+
pass
119+
else:
120+
raise CannotHandleRequest

0 commit comments

Comments
 (0)