test_url.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. # -*- coding: utf-8 -*-
  2. #
  3. import os
  4. import unittest
  5. from websocket._url import (
  6. _is_address_in_network,
  7. _is_no_proxy_host,
  8. get_proxy_info,
  9. parse_url,
  10. )
  11. from websocket._exceptions import WebSocketProxyException
  12. """
  13. test_url.py
  14. websocket - WebSocket client library for Python
  15. Copyright 2024 engn33r
  16. Licensed under the Apache License, Version 2.0 (the "License");
  17. you may not use this file except in compliance with the License.
  18. You may obtain a copy of the License at
  19. http://www.apache.org/licenses/LICENSE-2.0
  20. Unless required by applicable law or agreed to in writing, software
  21. distributed under the License is distributed on an "AS IS" BASIS,
  22. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  23. See the License for the specific language governing permissions and
  24. limitations under the License.
  25. """
  26. class UrlTest(unittest.TestCase):
  27. def test_address_in_network(self):
  28. self.assertTrue(_is_address_in_network("127.0.0.1", "127.0.0.0/8"))
  29. self.assertTrue(_is_address_in_network("127.1.0.1", "127.0.0.0/8"))
  30. self.assertFalse(_is_address_in_network("127.1.0.1", "127.0.0.0/24"))
  31. def test_parse_url(self):
  32. p = parse_url("ws://www.example.com/r")
  33. self.assertEqual(p[0], "www.example.com")
  34. self.assertEqual(p[1], 80)
  35. self.assertEqual(p[2], "/r")
  36. self.assertEqual(p[3], False)
  37. p = parse_url("ws://www.example.com/r/")
  38. self.assertEqual(p[0], "www.example.com")
  39. self.assertEqual(p[1], 80)
  40. self.assertEqual(p[2], "/r/")
  41. self.assertEqual(p[3], False)
  42. p = parse_url("ws://www.example.com/")
  43. self.assertEqual(p[0], "www.example.com")
  44. self.assertEqual(p[1], 80)
  45. self.assertEqual(p[2], "/")
  46. self.assertEqual(p[3], False)
  47. p = parse_url("ws://www.example.com")
  48. self.assertEqual(p[0], "www.example.com")
  49. self.assertEqual(p[1], 80)
  50. self.assertEqual(p[2], "/")
  51. self.assertEqual(p[3], False)
  52. p = parse_url("ws://www.example.com:8080/r")
  53. self.assertEqual(p[0], "www.example.com")
  54. self.assertEqual(p[1], 8080)
  55. self.assertEqual(p[2], "/r")
  56. self.assertEqual(p[3], False)
  57. p = parse_url("ws://www.example.com:8080/")
  58. self.assertEqual(p[0], "www.example.com")
  59. self.assertEqual(p[1], 8080)
  60. self.assertEqual(p[2], "/")
  61. self.assertEqual(p[3], False)
  62. p = parse_url("ws://www.example.com:8080")
  63. self.assertEqual(p[0], "www.example.com")
  64. self.assertEqual(p[1], 8080)
  65. self.assertEqual(p[2], "/")
  66. self.assertEqual(p[3], False)
  67. p = parse_url("wss://www.example.com:8080/r")
  68. self.assertEqual(p[0], "www.example.com")
  69. self.assertEqual(p[1], 8080)
  70. self.assertEqual(p[2], "/r")
  71. self.assertEqual(p[3], True)
  72. p = parse_url("wss://www.example.com:8080/r?key=value")
  73. self.assertEqual(p[0], "www.example.com")
  74. self.assertEqual(p[1], 8080)
  75. self.assertEqual(p[2], "/r?key=value")
  76. self.assertEqual(p[3], True)
  77. self.assertRaises(ValueError, parse_url, "http://www.example.com/r")
  78. p = parse_url("ws://[2a03:4000:123:83::3]/r")
  79. self.assertEqual(p[0], "2a03:4000:123:83::3")
  80. self.assertEqual(p[1], 80)
  81. self.assertEqual(p[2], "/r")
  82. self.assertEqual(p[3], False)
  83. p = parse_url("ws://[2a03:4000:123:83::3]:8080/r")
  84. self.assertEqual(p[0], "2a03:4000:123:83::3")
  85. self.assertEqual(p[1], 8080)
  86. self.assertEqual(p[2], "/r")
  87. self.assertEqual(p[3], False)
  88. p = parse_url("wss://[2a03:4000:123:83::3]/r")
  89. self.assertEqual(p[0], "2a03:4000:123:83::3")
  90. self.assertEqual(p[1], 443)
  91. self.assertEqual(p[2], "/r")
  92. self.assertEqual(p[3], True)
  93. p = parse_url("wss://[2a03:4000:123:83::3]:8080/r")
  94. self.assertEqual(p[0], "2a03:4000:123:83::3")
  95. self.assertEqual(p[1], 8080)
  96. self.assertEqual(p[2], "/r")
  97. self.assertEqual(p[3], True)
  98. class IsNoProxyHostTest(unittest.TestCase):
  99. def setUp(self):
  100. self.no_proxy = os.environ.get("no_proxy", None)
  101. if "no_proxy" in os.environ:
  102. del os.environ["no_proxy"]
  103. def tearDown(self):
  104. if self.no_proxy:
  105. os.environ["no_proxy"] = self.no_proxy
  106. elif "no_proxy" in os.environ:
  107. del os.environ["no_proxy"]
  108. def test_match_all(self):
  109. self.assertTrue(_is_no_proxy_host("any.websocket.org", ["*"]))
  110. self.assertTrue(_is_no_proxy_host("192.168.0.1", ["*"]))
  111. self.assertFalse(_is_no_proxy_host("192.168.0.1", ["192.168.1.1"]))
  112. self.assertFalse(
  113. _is_no_proxy_host("any.websocket.org", ["other.websocket.org"])
  114. )
  115. self.assertTrue(
  116. _is_no_proxy_host("any.websocket.org", ["other.websocket.org", "*"])
  117. )
  118. os.environ["no_proxy"] = "*"
  119. self.assertTrue(_is_no_proxy_host("any.websocket.org", None))
  120. self.assertTrue(_is_no_proxy_host("192.168.0.1", None))
  121. os.environ["no_proxy"] = "other.websocket.org, *"
  122. self.assertTrue(_is_no_proxy_host("any.websocket.org", None))
  123. def test_ip_address(self):
  124. self.assertTrue(_is_no_proxy_host("127.0.0.1", ["127.0.0.1"]))
  125. self.assertFalse(_is_no_proxy_host("127.0.0.2", ["127.0.0.1"]))
  126. self.assertTrue(
  127. _is_no_proxy_host("127.0.0.1", ["other.websocket.org", "127.0.0.1"])
  128. )
  129. self.assertFalse(
  130. _is_no_proxy_host("127.0.0.2", ["other.websocket.org", "127.0.0.1"])
  131. )
  132. os.environ["no_proxy"] = "127.0.0.1"
  133. self.assertTrue(_is_no_proxy_host("127.0.0.1", None))
  134. self.assertFalse(_is_no_proxy_host("127.0.0.2", None))
  135. os.environ["no_proxy"] = "other.websocket.org, 127.0.0.1"
  136. self.assertTrue(_is_no_proxy_host("127.0.0.1", None))
  137. self.assertFalse(_is_no_proxy_host("127.0.0.2", None))
  138. def test_ip_address_in_range(self):
  139. self.assertTrue(_is_no_proxy_host("127.0.0.1", ["127.0.0.0/8"]))
  140. self.assertTrue(_is_no_proxy_host("127.0.0.2", ["127.0.0.0/8"]))
  141. self.assertFalse(_is_no_proxy_host("127.1.0.1", ["127.0.0.0/24"]))
  142. os.environ["no_proxy"] = "127.0.0.0/8"
  143. self.assertTrue(_is_no_proxy_host("127.0.0.1", None))
  144. self.assertTrue(_is_no_proxy_host("127.0.0.2", None))
  145. os.environ["no_proxy"] = "127.0.0.0/24"
  146. self.assertFalse(_is_no_proxy_host("127.1.0.1", None))
  147. def test_hostname_match(self):
  148. self.assertTrue(_is_no_proxy_host("my.websocket.org", ["my.websocket.org"]))
  149. self.assertTrue(
  150. _is_no_proxy_host(
  151. "my.websocket.org", ["other.websocket.org", "my.websocket.org"]
  152. )
  153. )
  154. self.assertFalse(_is_no_proxy_host("my.websocket.org", ["other.websocket.org"]))
  155. os.environ["no_proxy"] = "my.websocket.org"
  156. self.assertTrue(_is_no_proxy_host("my.websocket.org", None))
  157. self.assertFalse(_is_no_proxy_host("other.websocket.org", None))
  158. os.environ["no_proxy"] = "other.websocket.org, my.websocket.org"
  159. self.assertTrue(_is_no_proxy_host("my.websocket.org", None))
  160. def test_hostname_match_domain(self):
  161. self.assertTrue(_is_no_proxy_host("any.websocket.org", [".websocket.org"]))
  162. self.assertTrue(_is_no_proxy_host("my.other.websocket.org", [".websocket.org"]))
  163. self.assertTrue(
  164. _is_no_proxy_host(
  165. "any.websocket.org", ["my.websocket.org", ".websocket.org"]
  166. )
  167. )
  168. self.assertFalse(_is_no_proxy_host("any.websocket.com", [".websocket.org"]))
  169. os.environ["no_proxy"] = ".websocket.org"
  170. self.assertTrue(_is_no_proxy_host("any.websocket.org", None))
  171. self.assertTrue(_is_no_proxy_host("my.other.websocket.org", None))
  172. self.assertFalse(_is_no_proxy_host("any.websocket.com", None))
  173. os.environ["no_proxy"] = "my.websocket.org, .websocket.org"
  174. self.assertTrue(_is_no_proxy_host("any.websocket.org", None))
  175. class ProxyInfoTest(unittest.TestCase):
  176. def setUp(self):
  177. self.http_proxy = os.environ.get("http_proxy", None)
  178. self.https_proxy = os.environ.get("https_proxy", None)
  179. self.no_proxy = os.environ.get("no_proxy", None)
  180. if "http_proxy" in os.environ:
  181. del os.environ["http_proxy"]
  182. if "https_proxy" in os.environ:
  183. del os.environ["https_proxy"]
  184. if "no_proxy" in os.environ:
  185. del os.environ["no_proxy"]
  186. def tearDown(self):
  187. if self.http_proxy:
  188. os.environ["http_proxy"] = self.http_proxy
  189. elif "http_proxy" in os.environ:
  190. del os.environ["http_proxy"]
  191. if self.https_proxy:
  192. os.environ["https_proxy"] = self.https_proxy
  193. elif "https_proxy" in os.environ:
  194. del os.environ["https_proxy"]
  195. if self.no_proxy:
  196. os.environ["no_proxy"] = self.no_proxy
  197. elif "no_proxy" in os.environ:
  198. del os.environ["no_proxy"]
  199. def test_proxy_from_args(self):
  200. self.assertRaises(
  201. WebSocketProxyException,
  202. get_proxy_info,
  203. "echo.websocket.events",
  204. False,
  205. proxy_host="localhost",
  206. )
  207. self.assertEqual(
  208. get_proxy_info(
  209. "echo.websocket.events", False, proxy_host="localhost", proxy_port=3128
  210. ),
  211. ("localhost", 3128, None),
  212. )
  213. self.assertEqual(
  214. get_proxy_info(
  215. "echo.websocket.events", True, proxy_host="localhost", proxy_port=3128
  216. ),
  217. ("localhost", 3128, None),
  218. )
  219. self.assertEqual(
  220. get_proxy_info(
  221. "echo.websocket.events",
  222. False,
  223. proxy_host="localhost",
  224. proxy_port=9001,
  225. proxy_auth=("a", "b"),
  226. ),
  227. ("localhost", 9001, ("a", "b")),
  228. )
  229. self.assertEqual(
  230. get_proxy_info(
  231. "echo.websocket.events",
  232. False,
  233. proxy_host="localhost",
  234. proxy_port=3128,
  235. proxy_auth=("a", "b"),
  236. ),
  237. ("localhost", 3128, ("a", "b")),
  238. )
  239. self.assertEqual(
  240. get_proxy_info(
  241. "echo.websocket.events",
  242. True,
  243. proxy_host="localhost",
  244. proxy_port=8765,
  245. proxy_auth=("a", "b"),
  246. ),
  247. ("localhost", 8765, ("a", "b")),
  248. )
  249. self.assertEqual(
  250. get_proxy_info(
  251. "echo.websocket.events",
  252. True,
  253. proxy_host="localhost",
  254. proxy_port=3128,
  255. proxy_auth=("a", "b"),
  256. ),
  257. ("localhost", 3128, ("a", "b")),
  258. )
  259. self.assertEqual(
  260. get_proxy_info(
  261. "echo.websocket.events",
  262. True,
  263. proxy_host="localhost",
  264. proxy_port=3128,
  265. no_proxy=["example.com"],
  266. proxy_auth=("a", "b"),
  267. ),
  268. ("localhost", 3128, ("a", "b")),
  269. )
  270. self.assertEqual(
  271. get_proxy_info(
  272. "echo.websocket.events",
  273. True,
  274. proxy_host="localhost",
  275. proxy_port=3128,
  276. no_proxy=["echo.websocket.events"],
  277. proxy_auth=("a", "b"),
  278. ),
  279. (None, 0, None),
  280. )
  281. self.assertEqual(
  282. get_proxy_info(
  283. "echo.websocket.events",
  284. True,
  285. proxy_host="localhost",
  286. proxy_port=3128,
  287. no_proxy=[".websocket.events"],
  288. ),
  289. (None, 0, None),
  290. )
  291. def test_proxy_from_env(self):
  292. os.environ["http_proxy"] = "http://localhost/"
  293. self.assertEqual(
  294. get_proxy_info("echo.websocket.events", False), ("localhost", None, None)
  295. )
  296. os.environ["http_proxy"] = "http://localhost:3128/"
  297. self.assertEqual(
  298. get_proxy_info("echo.websocket.events", False), ("localhost", 3128, None)
  299. )
  300. os.environ["http_proxy"] = "http://localhost/"
  301. os.environ["https_proxy"] = "http://localhost2/"
  302. self.assertEqual(
  303. get_proxy_info("echo.websocket.events", False), ("localhost", None, None)
  304. )
  305. os.environ["http_proxy"] = "http://localhost:3128/"
  306. os.environ["https_proxy"] = "http://localhost2:3128/"
  307. self.assertEqual(
  308. get_proxy_info("echo.websocket.events", False), ("localhost", 3128, None)
  309. )
  310. os.environ["http_proxy"] = "http://localhost/"
  311. os.environ["https_proxy"] = "http://localhost2/"
  312. self.assertEqual(
  313. get_proxy_info("echo.websocket.events", True), ("localhost2", None, None)
  314. )
  315. os.environ["http_proxy"] = "http://localhost:3128/"
  316. os.environ["https_proxy"] = "http://localhost2:3128/"
  317. self.assertEqual(
  318. get_proxy_info("echo.websocket.events", True), ("localhost2", 3128, None)
  319. )
  320. os.environ["http_proxy"] = ""
  321. os.environ["https_proxy"] = "http://localhost2/"
  322. self.assertEqual(
  323. get_proxy_info("echo.websocket.events", True), ("localhost2", None, None)
  324. )
  325. self.assertEqual(
  326. get_proxy_info("echo.websocket.events", False), (None, 0, None)
  327. )
  328. os.environ["http_proxy"] = ""
  329. os.environ["https_proxy"] = "http://localhost2:3128/"
  330. self.assertEqual(
  331. get_proxy_info("echo.websocket.events", True), ("localhost2", 3128, None)
  332. )
  333. self.assertEqual(
  334. get_proxy_info("echo.websocket.events", False), (None, 0, None)
  335. )
  336. os.environ["http_proxy"] = "http://localhost/"
  337. os.environ["https_proxy"] = ""
  338. self.assertEqual(get_proxy_info("echo.websocket.events", True), (None, 0, None))
  339. self.assertEqual(
  340. get_proxy_info("echo.websocket.events", False), ("localhost", None, None)
  341. )
  342. os.environ["http_proxy"] = "http://localhost:3128/"
  343. os.environ["https_proxy"] = ""
  344. self.assertEqual(get_proxy_info("echo.websocket.events", True), (None, 0, None))
  345. self.assertEqual(
  346. get_proxy_info("echo.websocket.events", False), ("localhost", 3128, None)
  347. )
  348. os.environ["http_proxy"] = "http://a:b@localhost/"
  349. self.assertEqual(
  350. get_proxy_info("echo.websocket.events", False),
  351. ("localhost", None, ("a", "b")),
  352. )
  353. os.environ["http_proxy"] = "http://a:b@localhost:3128/"
  354. self.assertEqual(
  355. get_proxy_info("echo.websocket.events", False),
  356. ("localhost", 3128, ("a", "b")),
  357. )
  358. os.environ["http_proxy"] = "http://a:b@localhost/"
  359. os.environ["https_proxy"] = "http://a:b@localhost2/"
  360. self.assertEqual(
  361. get_proxy_info("echo.websocket.events", False),
  362. ("localhost", None, ("a", "b")),
  363. )
  364. os.environ["http_proxy"] = "http://a:b@localhost:3128/"
  365. os.environ["https_proxy"] = "http://a:b@localhost2:3128/"
  366. self.assertEqual(
  367. get_proxy_info("echo.websocket.events", False),
  368. ("localhost", 3128, ("a", "b")),
  369. )
  370. os.environ["http_proxy"] = "http://a:b@localhost/"
  371. os.environ["https_proxy"] = "http://a:b@localhost2/"
  372. self.assertEqual(
  373. get_proxy_info("echo.websocket.events", True),
  374. ("localhost2", None, ("a", "b")),
  375. )
  376. os.environ["http_proxy"] = "http://a:b@localhost:3128/"
  377. os.environ["https_proxy"] = "http://a:b@localhost2:3128/"
  378. self.assertEqual(
  379. get_proxy_info("echo.websocket.events", True),
  380. ("localhost2", 3128, ("a", "b")),
  381. )
  382. os.environ[
  383. "http_proxy"
  384. ] = "http://john%40example.com:P%40SSWORD@localhost:3128/"
  385. os.environ[
  386. "https_proxy"
  387. ] = "http://john%40example.com:P%40SSWORD@localhost2:3128/"
  388. self.assertEqual(
  389. get_proxy_info("echo.websocket.events", True),
  390. ("localhost2", 3128, ("john@example.com", "P@SSWORD")),
  391. )
  392. os.environ["http_proxy"] = "http://a:b@localhost/"
  393. os.environ["https_proxy"] = "http://a:b@localhost2/"
  394. os.environ["no_proxy"] = "example1.com,example2.com"
  395. self.assertEqual(
  396. get_proxy_info("example.1.com", True), ("localhost2", None, ("a", "b"))
  397. )
  398. os.environ["http_proxy"] = "http://a:b@localhost:3128/"
  399. os.environ["https_proxy"] = "http://a:b@localhost2:3128/"
  400. os.environ["no_proxy"] = "example1.com,example2.com, echo.websocket.events"
  401. self.assertEqual(get_proxy_info("echo.websocket.events", True), (None, 0, None))
  402. os.environ["http_proxy"] = "http://a:b@localhost:3128/"
  403. os.environ["https_proxy"] = "http://a:b@localhost2:3128/"
  404. os.environ["no_proxy"] = "example1.com,example2.com, .websocket.events"
  405. self.assertEqual(get_proxy_info("echo.websocket.events", True), (None, 0, None))
  406. os.environ["http_proxy"] = "http://a:b@localhost:3128/"
  407. os.environ["https_proxy"] = "http://a:b@localhost2:3128/"
  408. os.environ["no_proxy"] = "127.0.0.0/8, 192.168.0.0/16"
  409. self.assertEqual(get_proxy_info("127.0.0.1", False), (None, 0, None))
  410. self.assertEqual(get_proxy_info("192.168.1.1", False), (None, 0, None))
  411. if __name__ == "__main__":
  412. unittest.main()