wormhole-proxy 3.3.2__tar.gz → 3.3.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: wormhole-proxy
3
- Version: 3.3.2
3
+ Version: 3.3.3
4
4
  Summary: Asynchronous I/O HTTP and HTTPS Proxy on Python >= 3.11
5
5
  License: MIT
6
6
  Keywords: wormhole,asynchronous,web,proxy
@@ -1,7 +1,7 @@
1
1
  # Main project metadata (PEP 621 standard)
2
2
  [project]
3
3
  name = "wormhole-proxy"
4
- version = "3.3.2"
4
+ version = "3.3.3"
5
5
  description = "Asynchronous I/O HTTP and HTTPS Proxy on Python >= 3.11"
6
6
  readme = "README.md"
7
7
  authors = [
@@ -303,9 +303,13 @@ async def process_https_tunnel(
303
303
 
304
304
  finally:
305
305
  # Ensure server streams are closed if they were opened.
306
- if server_writer and not server_writer.is_closing():
306
+ if server_writer is not None and not server_writer.is_closing():
307
307
  server_writer.close()
308
- await server_writer.wait_closed()
308
+ wc = getattr(server_writer, "wait_closed", None)
309
+ if callable(wc):
310
+ result = wc()
311
+ if asyncio.iscoroutine(result):
312
+ await result
309
313
 
310
314
 
311
315
  async def _send_http_request(
@@ -432,7 +436,11 @@ async def process_http_request(
432
436
  )
433
437
  if server_writer and not server_writer.is_closing():
434
438
  server_writer.close()
435
- await server_writer.wait_closed()
439
+ wc = getattr(server_writer, "wait_closed", None)
440
+ if callable(wc):
441
+ result = wc()
442
+ if asyncio.iscoroutine(result):
443
+ await result
436
444
 
437
445
  # Attempt 2: Fallback to original HTTP/1.0
438
446
  original_headers = [
@@ -49,8 +49,16 @@ async def main_async(args) -> None:
49
49
  )
50
50
  )
51
51
 
52
+ # Initialize the resolver with the configured verbosity.
53
+ resolver.initialize(verbose=args.verbose)
54
+
52
55
  if args.allowlist:
53
- num_allowed = load_allowlist(args.allowlist, args.host)
56
+ num_allowed = load_allowlist(
57
+ args.allowlist,
58
+ args.host,
59
+ ident={"id": "000000", "client": args.host},
60
+ verbose=args.verbose,
61
+ )
54
62
  if num_allowed > 0:
55
63
  logger.info(
56
64
  flm(
@@ -61,7 +69,12 @@ async def main_async(args) -> None:
61
69
  )
62
70
 
63
71
  if args.ad_block_db:
64
- num_blocked = await load_ad_block_db(args.ad_block_db, args.host)
72
+ num_blocked = await load_ad_block_db(
73
+ args.ad_block_db,
74
+ args.host,
75
+ ident={"id": "000000", "client": args.host},
76
+ verbose=args.verbose,
77
+ )
65
78
  if num_blocked > 0:
66
79
  logger.info(
67
80
  flm(
@@ -246,7 +259,6 @@ def main() -> int:
246
259
  args.verbose,
247
260
  async_mode=is_server_mode,
248
261
  )
249
- resolver.configure(verbose=args.verbose)
250
262
 
251
263
  if args.update_ad_block_db:
252
264
  # For this standalone utility, configure a simple logger to show progress.
@@ -32,12 +32,12 @@ class Resolver:
32
32
  self.resolver: aiodns.DNSResolver | None = None
33
33
  self.hosts_cache: dict[str, str] = {}
34
34
  self.verbose: int = 0 # Verbosity level, configured separately
35
- self._load_hosts_file()
36
35
  Resolver._instance = self
37
36
 
38
- def configure(self, verbose: int) -> None:
39
- """Sets the verbosity level for logging."""
37
+ def initialize(self, verbose: int) -> None:
38
+ """Initializes the resolver with a verbosity level and loads the hosts file."""
40
39
  self.verbose = verbose
40
+ self._load_hosts_file()
41
41
 
42
42
  @staticmethod
43
43
  def get_instance() -> "Resolver":
@@ -64,7 +64,7 @@ class Resolver:
64
64
  def _load_hosts_file(self) -> None:
65
65
  """Parses the system's hosts file and populates the cache."""
66
66
  hosts_path = self._get_hosts_path()
67
- ident = {"id": "resolver", "client": "internal"}
67
+ ident = {"id": "000000", "client": "0.0.0.0"}
68
68
 
69
69
  if not hosts_path.exists():
70
70
  logger.warning(
@@ -144,7 +144,10 @@ class Resolver:
144
144
  for res in results:
145
145
  if isinstance(res, list):
146
146
  for record in res:
147
- resolved_ips.add(record.host)
147
+ if isinstance(record.host, bytes):
148
+ resolved_ips.add(record.host.decode())
149
+ else:
150
+ resolved_ips.add(record.host)
148
151
  elif isinstance(res, aiodns.error.DNSError):
149
152
  # Ignore common "not found" errors. Log other DNS errors for debugging.
150
153
  if res.args[0] not in (
@@ -1,4 +1,4 @@
1
- from .logger import logger
1
+ from .logger import logger, format_log_message as flm
2
2
  from functools import lru_cache
3
3
  import aiosqlite
4
4
  import ipaddress
@@ -84,7 +84,9 @@ def is_private_ip(ip_str: str) -> bool:
84
84
  return True
85
85
 
86
86
 
87
- async def load_ad_block_db(path: str, host: str) -> int:
87
+ async def load_ad_block_db(
88
+ path: str, host: str, ident: dict[str, str], verbose: int = 0
89
+ ) -> int:
88
90
  """
89
91
  Loads a list of domains to block from a SQLite database into a global set
90
92
  for fast in-memory access.
@@ -105,7 +107,11 @@ async def load_ad_block_db(path: str, host: str) -> int:
105
107
  AD_BLOCK_SET.add(row[0])
106
108
  except Exception as e:
107
109
  logger.error(
108
- f"[000000][{host}]: Could not load ad-block database from '{path}': {e}",
110
+ flm(
111
+ f"Could not load ad-block database from '{path}': {e}",
112
+ ident=ident,
113
+ verbose=verbose,
114
+ )
109
115
  )
110
116
 
111
117
  if AD_BLOCK_SET:
@@ -114,13 +120,19 @@ async def load_ad_block_db(path: str, host: str) -> int:
114
120
  content_size = sum(sys.getsizeof(s) for s in AD_BLOCK_SET)
115
121
  total_size_mb = (set_size + content_size) / (1024 * 1024)
116
122
  logger.debug(
117
- f"[000000][{host}]: Ad-block set memory usage: ~{total_size_mb:.2f} MB for {len(AD_BLOCK_SET)} domains"
123
+ flm(
124
+ f"Ad-block set memory usage: ~{total_size_mb:.2f} MB for {len(AD_BLOCK_SET)} domains",
125
+ ident=ident,
126
+ verbose=verbose,
127
+ )
118
128
  )
119
129
 
120
130
  return len(AD_BLOCK_SET)
121
131
 
122
132
 
123
- def load_allowlist(path: str, host: str) -> int:
133
+ def load_allowlist(
134
+ path: str, host: str, ident: dict[str, str], verbose: int = 0
135
+ ) -> int:
124
136
  """
125
137
  Loads domains from a user-provided file and adds them to the global allowlist set.
126
138
  """
@@ -130,7 +142,13 @@ def load_allowlist(path: str, host: str) -> int:
130
142
  if line.strip() and not line.startswith("#"):
131
143
  ALLOW_LIST_SET.add(line.strip().lower())
132
144
  except FileNotFoundError:
133
- logger.error(f"[000000][{host}]: Allowlist file not found at '{path}'")
145
+ logger.error(
146
+ flm(
147
+ f"Allowlist file not found at '{path}'",
148
+ ident=ident,
149
+ verbose=verbose,
150
+ )
151
+ )
134
152
  return len(ALLOW_LIST_SET)
135
153
 
136
154
 
File without changes
File without changes