From 40c5605973c71f7d83cc0e225d82c1544d55f2b1 Mon Sep 17 00:00:00 2001 From: mvdbeek Date: Wed, 22 Jun 2022 19:17:10 +0200 Subject: [PATCH 1/2] Adapt byte content for StreamingResponse Fixes https://github.com/galaxyproject/galaxy/issues/14156 ``` TypeError: 'bytes' object is not an iterator File "starlette/middleware/base.py", line 69, in __call__ await response(scope, receive, send) File "starlette/responses.py", line 260, in __call__ await wrap(partial(self.listen_for_disconnect, receive)) File "anyio/_backends/_asyncio.py", line 662, in __aexit__ raise exceptions[0] File "starlette/responses.py", line 256, in wrap await func() File "starlette/responses.py", line 245, in stream_response async for chunk in self.body_iterator: File "starlette/middleware/base.py", line 58, in body_stream raise app_exc File "starlette/middleware/base.py", line 36, in coro await self.app(scope, request.receive, send_stream.send) File "starlette/exceptions.py", line 93, in __call__ raise exc File "starlette/exceptions.py", line 82, in __call__ await self.app(scope, receive, sender) File "fastapi/middleware/asyncexitstack.py", line 21, in __call__ raise e File "fastapi/middleware/asyncexitstack.py", line 18, in __call__ await self.app(scope, receive, send) File "starlette/routing.py", line 670, in __call__ await route.handle(scope, receive, send) File "starlette/routing.py", line 266, in handle await self.app(scope, receive, send) File "starlette/routing.py", line 68, in app await response(scope, receive, send) File "starlette/responses.py", line 260, in __call__ await wrap(partial(self.listen_for_disconnect, receive)) File "anyio/_backends/_asyncio.py", line 662, in __aexit__ raise exceptions[0] File "starlette/responses.py", line 256, in wrap await func() File "starlette/responses.py", line 245, in stream_response async for chunk in self.body_iterator: File "starlette/concurrency.py", line 63, in iterate_in_threadpool yield await anyio.to_thread.run_sync(_next, iterator) File "anyio/to_thread.py", line 31, in run_sync return await get_asynclib().run_sync_in_worker_thread( File "anyio/_backends/_asyncio.py", line 937, in run_sync_in_worker_thread return await future File "anyio/_backends/_asyncio.py", line 867, in run result = context.run(func, *args) File "starlette/concurrency.py", line 53, in _next return next(iterator) ``` --- lib/galaxy/webapps/galaxy/api/datasets.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/galaxy/webapps/galaxy/api/datasets.py b/lib/galaxy/webapps/galaxy/api/datasets.py index c78a12a0e0e6..cd4a8e6c88d6 100644 --- a/lib/galaxy/webapps/galaxy/api/datasets.py +++ b/lib/galaxy/webapps/galaxy/api/datasets.py @@ -2,7 +2,10 @@ API operations on the contents of a history dataset. """ import logging -from io import IOBase +from io import ( + BytesIO, + IOBase, +) from typing import ( Any, cast, @@ -259,6 +262,8 @@ def display( return FileResponse(file_name, headers=headers) elif isinstance(display_data, ZipstreamWrapper): return StreamingResponse(display_data.response(), headers=headers) + elif isinstance(display_data, bytes): + return StreamingResponse(BytesIO(display_data), headers=headers) return StreamingResponse(display_data, headers=headers) @router.get( From bd73e06799fb6b93a695bdb75d72c28b4c6d222d Mon Sep 17 00:00:00 2001 From: mvdbeek Date: Wed, 22 Jun 2022 19:55:02 +0200 Subject: [PATCH 2/2] Fix set_user function Should fix https://sentry.galaxyproject.org/organizations/galaxy/issues/84836/?project=3&query=is%3Aunresolved&statsPeriod=14d: ``` AttributeError: 'NoneType' object has no attribute 'bootstrap_admin_user' File "uvicorn/protocols/http/h11_impl.py", line 366, in run_asgi result = await app(self.scope, self.receive, self.send) File "uvicorn/middleware/proxy_headers.py", line 75, in __call__ return await self.app(scope, receive, send) File "fastapi/applications.py", line 269, in __call__ await super().__call__(scope, receive, send) File "starlette/applications.py", line 124, in __call__ await self.middleware_stack(scope, receive, send) File "starlette/middleware/errors.py", line 184, in __call__ raise exc File "starlette/middleware/errors.py", line 162, in __call__ await self.app(scope, receive, _send) File "starlette_context/middleware/raw_middleware.py", line 96, in __call__ await self.app(scope, receive, send_wrapper) File "starlette/middleware/base.py", line 69, in __call__ await response(scope, receive, send) File "starlette/responses.py", line 260, in __call__ await wrap(partial(self.listen_for_disconnect, receive)) File "anyio/_backends/_asyncio.py", line 662, in __aexit__ raise exceptions[0] File "starlette/responses.py", line 256, in wrap await func() File "starlette/responses.py", line 245, in stream_response async for chunk in self.body_iterator: File "starlette/middleware/base.py", line 58, in body_stream raise app_exc File "starlette/middleware/base.py", line 36, in coro await self.app(scope, request.receive, send_stream.send) File "starlette/middleware/base.py", line 69, in __call__ await response(scope, receive, send) File "starlette/responses.py", line 260, in __call__ await wrap(partial(self.listen_for_disconnect, receive)) File "anyio/_backends/_asyncio.py", line 662, in __aexit__ raise exceptions[0] File "starlette/responses.py", line 256, in wrap await func() File "starlette/responses.py", line 245, in stream_response async for chunk in self.body_iterator: File "starlette/middleware/base.py", line 58, in body_stream raise app_exc File "starlette/middleware/base.py", line 36, in coro await self.app(scope, request.receive, send_stream.send) File "starlette/exceptions.py", line 93, in __call__ raise exc File "starlette/exceptions.py", line 82, in __call__ await self.app(scope, receive, sender) File "fastapi/middleware/asyncexitstack.py", line 21, in __call__ raise e File "fastapi/middleware/asyncexitstack.py", line 18, in __call__ await self.app(scope, receive, send) File "starlette/routing.py", line 670, in __call__ await route.handle(scope, receive, send) File "starlette/routing.py", line 418, in handle await self.app(scope, receive, send) File "a2wsgi/wsgi.py", line 140, in __call__ return await responder(scope, receive, send) File "a2wsgi/wsgi.py", line 179, in __call__ raise self.exc_info[0].with_traceback( File "galaxy/web/framework/middleware/error.py", line 165, in __call__ app_iter = self.application(environ, sr_checker) File "/cvmfs/main.galaxyproject.org/venv/lib/python3.8/site-packages/paste/recursive.py", line 85, in __call__ return self.application(environ, start_response) File "galaxy/web/framework/middleware/statsd.py", line 29, in __call__ req = self.application(environ, start_response) File "/cvmfs/main.galaxyproject.org/venv/lib/python3.8/site-packages/paste/httpexceptions.py", line 640, in __call__ return self.application(environ, start_response) File "galaxy/web/framework/base.py", line 159, in __call__ return self.handle_request(environ, start_response) File "galaxy/web/framework/base.py", line 215, in handle_request trans = self.transaction_factory(environ) File "galaxy/webapps/base/webapp.py", line 105, in self.set_transaction_factory(lambda e: self.transaction_chooser(e, galaxy_app, session_cookie)) File "galaxy/webapps/base/webapp.py", line 194, in transaction_chooser return GalaxyWebTransaction(environ, galaxy_app, self, session_cookie) File "galaxy/webapps/base/webapp.py", line 311, in __init__ self.error_message = self._authenticate_api(session_cookie) File "galaxy/webapps/base/webapp.py", line 541, in _authenticate_api self.user = None File "galaxy/webapps/base/webapp.py", line 451, in set_user if user.bootstrap_admin_user: ``` Not sure what I was thinking when I did this in https://github.com/galaxyproject/galaxy/pull/10823/files#diff-ca6cf7b8ec16cb97add6d9535857de123352878e979bcc16812cdfa23f22b204R360 If we have a boostrap_admin_user we certainly can't add it to a session, that would definitely fail. --- lib/galaxy/webapps/base/webapp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/galaxy/webapps/base/webapp.py b/lib/galaxy/webapps/base/webapp.py index a67d34fe8cf1..a173b03b7583 100644 --- a/lib/galaxy/webapps/base/webapp.py +++ b/lib/galaxy/webapps/base/webapp.py @@ -368,7 +368,7 @@ def get_user(self): def set_user(self, user): """Set the current user.""" if self.galaxy_session: - if user.bootstrap_admin_user: + if user and not user.bootstrap_admin_user: self.galaxy_session.user = user self.sa_session.add(self.galaxy_session) self.sa_session.flush()