33# Copyright 2017 The Dopple Authors.
44# Licensed under the Apache License, Version 2.0. See the LICENSE file.
55
6- """
6+ r """
77Dopple JSON-RPC Proxy
88
99This Python script provides HTTP proxy to Unix Socket based JSON-RPC servers.
1717
1818"""
1919
20- from argparse import ArgumentParser , ArgumentDefaultsHelpFormatter
20+ from argparse import ArgumentDefaultsHelpFormatter , ArgumentParser
2121import errno
22- import pkg_resources
23- from http .server import HTTPServer , BaseHTTPRequestHandler
22+ from http .server import BaseHTTPRequestHandler , HTTPServer
2423from os import path
2524import socket
2625import sys
27- import time
2826import threading
27+ import time
2928from typing import Any , Optional # noqa: F401
3029from urllib .parse import urlparse
3130
31+ import pkg_resources
3232
33- if sys .platform == ' win32' :
33+ if sys .platform == " win32" :
3434 import win32file
3535 import pywintypes
3636else :
4040try :
4141 VERSION = pkg_resources .get_distribution ("dopple" ).version
4242except pkg_resources .DistributionNotFound :
43- VERSION = ' unknown'
43+ VERSION = " unknown"
4444
4545BUFSIZE = 32
46- DELIMITER = ord (' \n ' )
46+ DELIMITER = ord (" \n " )
4747BACKEND_CONNECTION_TIMEOUT = 30.0
4848INFO = """Dopple JSON-RPC Proxy
4949
@@ -138,8 +138,14 @@ class NamedPipeConnector(object):
138138 def __init__ (self , ipc_path : str ) -> None :
139139 try :
140140 self .handle = win32file .CreateFile (
141- ipc_path , win32file .GENERIC_READ | win32file .GENERIC_WRITE ,
142- 0 , None , win32file .OPEN_EXISTING , 0 , None )
141+ ipc_path ,
142+ win32file .GENERIC_READ | win32file .GENERIC_WRITE ,
143+ 0 ,
144+ None ,
145+ win32file .OPEN_EXISTING ,
146+ 0 ,
147+ None ,
148+ )
143149 except pywintypes .error as err :
144150 raise IOError (err )
145151
@@ -155,25 +161,25 @@ def recv(self, max_length: int) -> Any:
155161 raise IOError (err )
156162 return data
157163
158- def sendall (self , data : bytes ) -> ' win32file.WriteFile' :
164+ def sendall (self , data : bytes ) -> " win32file.WriteFile" :
159165 return win32file .WriteFile (self .handle , data )
160166
161167 def close (self ) -> None :
162168 self .handle .close ()
163169
164170
165171def get_ipc_connector (ipc_path : str ) -> Any :
166- if sys .platform == ' win32' :
172+ if sys .platform == " win32" :
167173 return NamedPipeConnector (ipc_path )
168174 return UnixSocketConnector (ipc_path )
169175
170176
171177class HTTPRequestHandler (BaseHTTPRequestHandler ):
172178
173- server : ' Proxy'
179+ server : " Proxy"
174180
175181 def do_GET (self ) -> None :
176- if self .path != '/' :
182+ if self .path != "/" :
177183 self .send_response (404 )
178184 self .end_headers ()
179185 return
@@ -182,13 +188,15 @@ def do_GET(self) -> None:
182188 self .send_header ("Content-type" , "text/plain" )
183189 self .addCORS ()
184190 self .end_headers ()
185- backend_url = 'unix:' + self .server .backend_address
186- proxy_url = '{}:{}' .format (self .server .server_name ,
187- self .server .server_port )
188- info = INFO .format (version = VERSION , proxy_url = proxy_url ,
189- backend_url = backend_url ,
190- connected = self .server .conn .is_connected ())
191- self .wfile .write (info .encode ('utf-8' ))
191+ backend_url = "unix:" + self .server .backend_address
192+ proxy_url = "{}:{}" .format (self .server .server_name , self .server .server_port )
193+ info = INFO .format (
194+ version = VERSION ,
195+ proxy_url = proxy_url ,
196+ backend_url = backend_url ,
197+ connected = self .server .conn .is_connected (),
198+ )
199+ self .wfile .write (info .encode ("utf-8" ))
192200
193201 def do_OPTIONS (self ) -> None :
194202 self .send_response (200 )
@@ -197,7 +205,7 @@ def do_OPTIONS(self) -> None:
197205 self .end_headers ()
198206
199207 def do_POST (self ) -> None :
200- request_length = int (self .headers [' Content-Length' ]) # type: ignore
208+ request_length = int (self .headers [" Content-Length" ]) # type: ignore
201209 request_content = self .rfile .read (request_length )
202210 # self.log_message("Headers: {}".format(self.headers))
203211 # self.log_message("Request: {}".format(request_content))
@@ -214,7 +222,7 @@ def do_POST(self) -> None:
214222 self .wfile .write (response_content )
215223 except BackendError as err :
216224 self .send_response (502 )
217- error_msg = str (err ).encode (' utf-8' )
225+ error_msg = str (err ).encode (" utf-8" )
218226 # TODO: Send as JSON-RPC response
219227 self .send_header ("Content-type" , "text/plain" )
220228 self .send_header ("Content-length" , str (len (error_msg )))
@@ -231,11 +239,10 @@ def addCORS(self) -> None:
231239
232240
233241class Proxy (HTTPServer ):
234-
235242 def __init__ (self , proxy_url : str , backend_path : str ) -> None :
236243 self .proxy_url = proxy_url
237244 url = urlparse (proxy_url )
238- assert url .scheme == ' http'
245+ assert url .scheme == " http"
239246 proxy_address = url .hostname , url .port
240247
241248 super (Proxy , self ).__init__ (proxy_address , HTTPRequestHandler )
@@ -245,7 +252,7 @@ def __init__(self, proxy_url: str, backend_path: str) -> None:
245252 def process (self , request : Any ) -> bytes :
246253 self .conn .sendall (request )
247254
248- response = b''
255+ response = b""
249256 while True :
250257 r = self .conn .recv (BUFSIZE )
251258 if not r :
@@ -261,48 +268,57 @@ def run(self) -> None:
261268 self .conn = get_ipc_connector (self .backend_address )
262269 self .conn .check_connection (timeout = BACKEND_CONNECTION_TIMEOUT )
263270
264- print ("Dopple JSON-RPC HTTP Proxy: {} -> {}" .format (
265- self .backend_address , self .proxy_url ), file = sys .stderr , flush = True )
271+ print (
272+ "Dopple JSON-RPC HTTP Proxy: {} -> {}" .format (
273+ self .backend_address , self .proxy_url
274+ ),
275+ file = sys .stderr ,
276+ flush = True ,
277+ )
266278 self .serve_forever ()
267279
268280
269- if sys .platform == ' win32' :
270- DEFAULT_BACKEND_PATH = r' \\.\pipe\geth.ipc'
281+ if sys .platform == " win32" :
282+ DEFAULT_BACKEND_PATH = r" \\.\pipe\geth.ipc"
271283 BACKEND_PATH_HELP = "Named Pipe of a backend RPC server"
272284else :
273- DEFAULT_BACKEND_PATH = ' ~/.ethereum/geth.ipc'
285+ DEFAULT_BACKEND_PATH = " ~/.ethereum/geth.ipc"
274286 BACKEND_PATH_HELP = "Unix Socket of a backend RPC server"
275287
276- DEFAULT_PROXY_URL = ' http://127.0.0.1:8545'
288+ DEFAULT_PROXY_URL = " http://127.0.0.1:8545"
277289PROXY_URL_HELP = "URL for this proxy server"
278290
279291
280292def parse_args () -> Any :
281293 parser = ArgumentParser (
282- description = ' Dopple HTTP Proxy for JSON-RPC servers' ,
283- formatter_class = ArgumentDefaultsHelpFormatter
294+ description = " Dopple HTTP Proxy for JSON-RPC servers" ,
295+ formatter_class = ArgumentDefaultsHelpFormatter ,
284296 )
285297
286- parser .add_argument ('backend_path' , nargs = '?' ,
287- default = DEFAULT_BACKEND_PATH ,
288- help = BACKEND_PATH_HELP )
289- parser .add_argument ('proxy_url' , nargs = '?' ,
290- default = DEFAULT_PROXY_URL ,
291- help = PROXY_URL_HELP )
298+ parser .add_argument (
299+ "backend_path" , nargs = "?" , default = DEFAULT_BACKEND_PATH , help = BACKEND_PATH_HELP
300+ )
301+ parser .add_argument (
302+ "proxy_url" , nargs = "?" , default = DEFAULT_PROXY_URL , help = PROXY_URL_HELP
303+ )
292304 return parser .parse_args ()
293305
294306
295- def run (proxy_url : str = DEFAULT_PROXY_URL , backend_path : str = DEFAULT_BACKEND_PATH ) -> None :
307+ def run (
308+ proxy_url : str = DEFAULT_PROXY_URL , backend_path : str = DEFAULT_BACKEND_PATH
309+ ) -> None :
296310 proxy = Proxy (proxy_url , backend_path )
297311 try :
298312 proxy .run ()
299313 except KeyboardInterrupt :
300314 proxy .shutdown ()
301315
302316
303- def run_daemon (proxy_url : str = DEFAULT_PROXY_URL , backend_path : str = DEFAULT_BACKEND_PATH ) -> Proxy :
317+ def run_daemon (
318+ proxy_url : str = DEFAULT_PROXY_URL , backend_path : str = DEFAULT_BACKEND_PATH
319+ ) -> Proxy :
304320 proxy = Proxy (proxy_url , backend_path )
305- th = threading .Thread (name = ' dopple' , target = proxy .run )
321+ th = threading .Thread (name = " dopple" , target = proxy .run )
306322 th .daemon = True
307323 th .start ()
308324 return proxy
@@ -313,5 +329,5 @@ def main() -> None:
313329 run (args .proxy_url , args .backend_path )
314330
315331
316- if __name__ == ' __main__' :
332+ if __name__ == " __main__" :
317333 main ()
0 commit comments