Compare commits

..

3 Commits

Author SHA1 Message Date
Josiah Baldwin
5ee2c8edf3 1.0.0 release 2024-12-13 16:39:59 -08:00
Josiah Baldwin
d3d5b87287 Fixed various issues with (down/up)load file functions not passing through arguments 2024-12-13 08:51:49 -08:00
Josiah Baldwin
18eb2de5b6 Added no_proxy os variable bypass so urllib.requests acts as expected 2024-12-13 08:28:54 -08:00
4 changed files with 40 additions and 9 deletions

View File

@@ -2,7 +2,7 @@
Changelog Changelog
========= =========
Version 0.1 Version 1.0.0
=========== ===========
Create First release

View File

@@ -4,9 +4,27 @@ from . import exceptions
from . import util from . import util
import asyncio import asyncio
import json import json
import urllib import importlib
import importlib.util
import shutil import shutil
# import urllib
# import urllib.request
import urllib.parse
old_parse = urllib.parse
# Default proxy handler uses OS defined no_proxy in order to be helpful. This is unhelpful for our usecase. Monkey patch out proxy getting functions, but don't effect the user's urllib instance.
spec = importlib.util.find_spec('urllib')
urllib = importlib.util.module_from_spec(spec)
spec.loader.exec_module(urllib)
spec = importlib.util.find_spec('urllib.request')
urllib.request = importlib.util.module_from_spec(spec)
spec.loader.exec_module(urllib.request)
urllib.parse = old_parse
urllib.request.getproxies_environment = lambda: {}
urllib.request.getproxies_registry = lambda: {}
urllib.request.getproxies_macosx_sysconf = lambda: {}
urllib.request.getproxies = lambda: {}
class Files(tunnel.Tunnel): class Files(tunnel.Tunnel):
def __init__(self, session, node): def __init__(self, session, node):
super().__init__(session, node.nodeid, constants.Protocol.FILES) super().__init__(session, node.nodeid, constants.Protocol.FILES)
@@ -23,8 +41,9 @@ class Files(tunnel.Tunnel):
if self._session._proxy is not None: if self._session._proxy is not None:
# We don't know which protocol the user is going to use, but we only need support one at a time, so just assume both # We don't know which protocol the user is going to use, but we only need support one at a time, so just assume both
proxies = { proxies = {
"http_proxy": self._session._proxy, "http": self._session._proxy,
"https_proxy": self._session._proxy "https": self._session._proxy,
"no": ""
} }
self._proxy_handler = urllib.request.ProxyHandler(proxies=proxies) self._proxy_handler = urllib.request.ProxyHandler(proxies=proxies)
self._http_opener = urllib.request.build_opener(self._proxy_handler, urllib.request.HTTPSHandler(context=self._session._ssl_context)) self._http_opener = urllib.request.build_opener(self._proxy_handler, urllib.request.HTTPSHandler(context=self._session._ssl_context))

View File

@@ -1844,7 +1844,7 @@ class Session(object):
node = await self.device_info(node) node = await self.device_info(node)
if unique_file_tunnel: if unique_file_tunnel:
async with self.file_explorer(node) as files: async with self.file_explorer(node) as files:
return await files.upload(source, target) return await files.upload(source, target, timeout=timeout)
else: else:
files = await self._cached_file_explorer(node, node.nodeid) files = await self._cached_file_explorer(node, node.nodeid)
return await files.upload(source, target, timeout=timeout) return await files.upload(source, target, timeout=timeout)
@@ -1898,12 +1898,12 @@ class Session(object):
start = target.tell() start = target.tell()
if unique_file_tunnel: if unique_file_tunnel:
async with self.file_explorer(node) as files: async with self.file_explorer(node) as files:
await files.download(source, target) await files.download(source, target, skip_http_attempt=skip_http_attempt, skip_ws_attempt=skip_ws_attempt, timeout=timeout)
target.seek(start) target.seek(start)
return target return target
else: else:
files = await self._cached_file_explorer(node, node.nodeid) files = await self._cached_file_explorer(node, node.nodeid)
await files.download(source, target, timeout=timeout) await files.download(source, target, skip_http_attempt=skip_http_attempt, skip_ws_attempt=skip_ws_attempt, timeout=timeout)
target.seek(start) target.seek(start)
return target return target
@@ -1928,7 +1928,7 @@ class Session(object):
None None
''' '''
with open(filepath, "wb") as f: with open(filepath, "wb") as f:
await self.download(node, source, f, unique_file_tunnel, timeout=timeout) await self.download(node, source, f, skip_http_attempt=skip_http_attempt, skip_ws_attempt=skip_ws_attempt, unique_file_tunnel=unique_file_tunnel, timeout=timeout)
async def _cached_file_explorer(self, node, _id): async def _cached_file_explorer(self, node, _id):
if (_id not in self._file_tunnels or not self._file_tunnels[_id].alive): if (_id not in self._file_tunnels or not self._file_tunnels[_id].alive):

View File

@@ -53,6 +53,18 @@ async def test_commands(env):
finally: finally:
assert (await admin_session.remove_device_group(mesh.meshid, timeout=10)), "Failed to remove device group" assert (await admin_session.remove_device_group(mesh.meshid, timeout=10)), "Failed to remove device group"
async def test_os_proxy_bypass():
os.environ["no_proxy"] = "*"
import urllib
import urllib.request
os_proxies = urllib.request.getproxies()
meshctrl_proxies = meshctrl.files.urllib.request.getproxies()
print(f"os_proxies: {os_proxies}")
print(f"meshctrl_proxies: {meshctrl_proxies}")
assert meshctrl_proxies.get("no", None) == None, "Meshctrl is using system proxies"
assert os_proxies.get("no", None) == "*", "System is using meshctrl proxies"
assert os_proxies != meshctrl_proxies, "Override didn't work"
async def test_upload_download(env): async def test_upload_download(env):
async with meshctrl.Session("wss://" + env.dockerurl, user="admin", password=env.users["admin"], ignore_ssl=True, proxy=env.proxyurl) as admin_session: async with meshctrl.Session("wss://" + env.dockerurl, user="admin", password=env.users["admin"], ignore_ssl=True, proxy=env.proxyurl) as admin_session:
mesh = await admin_session.add_device_group("test", description="This is a test group", amtonly=False, features=0, consent=0, timeout=10) mesh = await admin_session.add_device_group("test", description="This is a test group", amtonly=False, features=0, consent=0, timeout=10)