Skip to content

Commit c68fe40

Browse files
lzwjavaclaude
andcommitted
feat(commands): add /proxy and /ca_bundle command handlers
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 6a07dc2 commit c68fe40

2 files changed

Lines changed: 111 additions & 0 deletions

File tree

iclaw/commands/proxy.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import os
2+
3+
4+
def handle_proxy_command(current_proxy, arg):
5+
if arg is None:
6+
if current_proxy:
7+
print(f" proxy: {current_proxy}")
8+
else:
9+
print(" proxy: (not set)")
10+
return current_proxy
11+
12+
if arg == "off":
13+
print(" Proxy cleared.")
14+
return None
15+
16+
if not (arg.startswith("http://") or arg.startswith("https://")):
17+
print(f" Invalid proxy URL: {arg}")
18+
print(" Only http:// and https:// schemes are supported.")
19+
return current_proxy
20+
21+
print(f" Proxy set to {arg}")
22+
return arg
23+
24+
25+
def handle_ca_bundle_command(current_ca_bundle, arg):
26+
if arg is None:
27+
if current_ca_bundle:
28+
print(f" ca_bundle: {current_ca_bundle}")
29+
else:
30+
print(" ca_bundle: (system default)")
31+
return current_ca_bundle
32+
33+
if arg == "off":
34+
print(" CA bundle cleared. Using system default.")
35+
return None
36+
37+
abs_path = os.path.abspath(arg)
38+
if not os.path.isfile(abs_path):
39+
print(f" File not found: {abs_path}")
40+
return current_ca_bundle
41+
42+
print(f" CA bundle set to {abs_path}")
43+
return abs_path

tests/test_proxy_commands.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import os
2+
import unittest
3+
4+
from iclaw.commands.proxy import handle_proxy_command, handle_ca_bundle_command
5+
6+
7+
class TestHandleProxyCommand(unittest.TestCase):
8+
def test_show_current_proxy(self):
9+
result = handle_proxy_command("http://proxy:8080", None)
10+
self.assertEqual(result, "http://proxy:8080")
11+
12+
def test_show_no_proxy(self):
13+
result = handle_proxy_command(None, None)
14+
self.assertIsNone(result)
15+
16+
def test_set_proxy(self):
17+
result = handle_proxy_command(None, "http://new:1234")
18+
self.assertEqual(result, "http://new:1234")
19+
20+
def test_set_https_proxy(self):
21+
result = handle_proxy_command(None, "https://secure:4321")
22+
self.assertEqual(result, "https://secure:4321")
23+
24+
def test_clear_proxy(self):
25+
result = handle_proxy_command("http://old:1234", "off")
26+
self.assertIsNone(result)
27+
28+
def test_reject_socks_proxy(self):
29+
result = handle_proxy_command(None, "socks5://proxy:1080")
30+
self.assertIsNone(result)
31+
32+
def test_reject_invalid_scheme(self):
33+
result = handle_proxy_command(None, "ftp://proxy:21")
34+
self.assertIsNone(result)
35+
36+
37+
class TestHandleCaBundleCommand(unittest.TestCase):
38+
def test_show_current_ca_bundle(self):
39+
result = handle_ca_bundle_command("/path/cert.pem", None)
40+
self.assertEqual(result, "/path/cert.pem")
41+
42+
def test_show_no_ca_bundle(self):
43+
result = handle_ca_bundle_command(None, None)
44+
self.assertIsNone(result)
45+
46+
def test_set_ca_bundle(self):
47+
# Use a file that actually exists
48+
path = os.path.abspath(__file__)
49+
result = handle_ca_bundle_command(None, path)
50+
self.assertEqual(result, path)
51+
52+
def test_set_ca_bundle_nonexistent_file(self):
53+
result = handle_ca_bundle_command(None, "/nonexistent/cert.pem")
54+
self.assertIsNone(result)
55+
56+
def test_clear_ca_bundle(self):
57+
result = handle_ca_bundle_command("/path/cert.pem", "off")
58+
self.assertIsNone(result)
59+
60+
def test_set_ca_bundle_resolves_relative_path(self):
61+
# Use current file as a known existing file
62+
rel_path = os.path.relpath(__file__)
63+
result = handle_ca_bundle_command(None, rel_path)
64+
self.assertEqual(result, os.path.abspath(rel_path))
65+
66+
67+
if __name__ == "__main__":
68+
unittest.main()

0 commit comments

Comments
 (0)