mirror of
https://github.com/open-webui/open-webui.git
synced 2026-10-06 02:48:04 +00:00
fix: repair system_oauth path and stream file uploads to terminal
- upload_file_to_terminal now receives __oauth_token__ via the builtin tool param injection (wired through get_builtin_tools) and reads the bearer from it. The previous metadata['oauth_token'] lookup was never populated for builtin tools, so system_oauth terminals silently sent no bearer and failed against protected servers. - Replace full-file materialization with an aiofiles-backed async generator fed into aiohttp.FormData, so uploads are streamed chunk by chunk without buffering the whole file in memory and without blocking the event loop on disk reads.
This commit is contained in:
parent
f165f7dc3d
commit
8416b9cfb5
2 changed files with 27 additions and 9 deletions
|
|
@ -2830,9 +2830,17 @@ async def delete_automation(
|
|||
# =============================================================================
|
||||
|
||||
|
||||
def _read_file_bytes(path: str) -> bytes:
|
||||
with open(path, 'rb') as fh:
|
||||
return fh.read()
|
||||
async def _iter_file_chunks(path: str, chunk_size: int = 65536):
|
||||
# Async-stream file contents so disk reads don't block the event loop
|
||||
# and the full file is never materialized in memory for the upload.
|
||||
import aiofiles
|
||||
|
||||
async with aiofiles.open(path, 'rb') as fh:
|
||||
while True:
|
||||
chunk = await fh.read(chunk_size)
|
||||
if not chunk:
|
||||
break
|
||||
yield chunk
|
||||
|
||||
|
||||
async def upload_file_to_terminal(
|
||||
|
|
@ -2840,6 +2848,7 @@ async def upload_file_to_terminal(
|
|||
__request__: Request = None,
|
||||
__user__: dict = None,
|
||||
__metadata__: dict = None,
|
||||
__oauth_token__: dict = None,
|
||||
) -> str:
|
||||
"""
|
||||
Upload a file to the connected Open Terminal server's working directory.
|
||||
|
|
@ -2902,7 +2911,11 @@ async def upload_file_to_terminal(
|
|||
headers['Authorization'] = f'Bearer {__request__.state.token.credentials}'
|
||||
elif auth_type == 'system_oauth':
|
||||
cookies = __request__.cookies
|
||||
oauth_token = metadata.get('oauth_token') or {}
|
||||
# __oauth_token__ is populated by middleware/get_builtin_tools;
|
||||
# the legacy metadata['oauth_token'] lookup was never populated for
|
||||
# builtin tools, so system_oauth terminals silently received no
|
||||
# bearer token and failed against protected servers.
|
||||
oauth_token = __oauth_token__ or {}
|
||||
if oauth_token.get('access_token'):
|
||||
headers['Authorization'] = f'Bearer {oauth_token["access_token"]}'
|
||||
# auth_type == 'none': no Authorization header
|
||||
|
|
@ -2927,11 +2940,10 @@ async def upload_file_to_terminal(
|
|||
):
|
||||
return json.dumps({'error': 'File not found'})
|
||||
|
||||
# Storage.get_file and file reads can do sync network/disk I/O for
|
||||
# remote backends (S3/GCS/Azure); offload to a worker thread to keep
|
||||
# the event loop responsive under concurrent chat load.
|
||||
# Storage.get_file can do sync network/disk I/O for remote backends
|
||||
# (S3/GCS/Azure); offload to a worker thread to keep the event loop
|
||||
# responsive. File contents are then streamed via aiofiles below.
|
||||
local_path = await asyncio.to_thread(Storage.get_file, file_record.path)
|
||||
file_bytes = await asyncio.to_thread(_read_file_bytes, local_path)
|
||||
|
||||
# --- 3. Upload to terminal server ---
|
||||
import aiohttp
|
||||
|
|
@ -2960,7 +2972,12 @@ async def upload_file_to_terminal(
|
|||
)
|
||||
|
||||
form_data = aiohttp.FormData()
|
||||
form_data.add_field('file', file_bytes, filename=file_record.filename)
|
||||
form_data.add_field(
|
||||
'file',
|
||||
_iter_file_chunks(local_path),
|
||||
filename=file_record.filename,
|
||||
content_type='application/octet-stream',
|
||||
)
|
||||
async with session.post(
|
||||
f'{terminal_url}/files/upload',
|
||||
params={'directory': upload_dir},
|
||||
|
|
|
|||
|
|
@ -564,6 +564,7 @@ async def get_builtin_tools(
|
|||
'__chat_id__': extra_params.get('__chat_id__'),
|
||||
'__message_id__': extra_params.get('__message_id__'),
|
||||
'__model_knowledge__': model_knowledge,
|
||||
'__oauth_token__': extra_params.get('__oauth_token__'),
|
||||
},
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue