http.py 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #!/usr/bin/env python3
  2. #
  3. # MMGen Wallet, a terminal-based cryptocurrency wallet
  4. # Copyright (C)2013-2025 The MMGen Project <mmgen@tuta.io>
  5. # Licensed under the GNU General Public License, Version 3:
  6. # https://www.gnu.org/licenses
  7. # Public project repositories:
  8. # https://github.com/mmgen/mmgen-wallet
  9. # https://gitlab.com/mmgen/mmgen-wallet
  10. """
  11. http: HTTP client base class
  12. """
  13. import requests
  14. class HTTPClient:
  15. network_proto = 'https'
  16. host = None
  17. timeout = 60
  18. http_hdrs = {
  19. 'User-Agent': 'curl/8.7.1',
  20. 'Proxy-Connection': 'Keep-Alive'}
  21. extra_http_hdrs = {}
  22. verify = True
  23. text_mode = True
  24. def __init__(self, cfg, *, network_proto=None, host=None):
  25. self.cfg = cfg
  26. if network_proto:
  27. self.network_proto = network_proto
  28. if host:
  29. self.host = host
  30. self.session = requests.Session()
  31. self.session.trust_env = False # ignore *_PROXY environment vars
  32. self.session.headers = (self.http_hdrs | self.extra_http_hdrs)
  33. if cfg.proxy == 'env':
  34. self.session.trust_env = True
  35. elif cfg.proxy:
  36. self.session.proxies.update({
  37. 'http': f'socks5h://{cfg.proxy}',
  38. 'https': f'socks5h://{cfg.proxy}'})
  39. def call(self, name, path, err_fs, timeout, *, data=None):
  40. url = self.network_proto + '://' + self.host + path
  41. kwargs = {
  42. 'url': url,
  43. 'timeout': self.cfg.http_timeout or timeout or self.timeout,
  44. 'verify': self.verify}
  45. if data:
  46. kwargs['data'] = data
  47. res = getattr(self.session, name)(**kwargs)
  48. if res.status_code != 200:
  49. from .util import die
  50. die(2, '\n' + err_fs.format(s=res.status_code, u=url, d=data))
  51. return res.content.decode() if self.text_mode else res.content
  52. def get(self, *, path, timeout=None):
  53. return self.call(
  54. 'get',
  55. path,
  56. 'HTTP GET failed with status code {s}\n URL: {u}',
  57. timeout)
  58. def post(self, *, path, data, timeout=None):
  59. return self.call(
  60. 'post',
  61. path,
  62. 'HTTP POST failed with status code {s}\n URL: {u}\n DATA: {d}',
  63. timeout,
  64. data = data)