Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: StructlogPlugin breaks SQLAdminPlugin #3986

Open
1 of 4 tasks
JaagupAverin opened this issue Feb 8, 2025 · 1 comment
Open
1 of 4 tasks

Bug: StructlogPlugin breaks SQLAdminPlugin #3986

JaagupAverin opened this issue Feb 8, 2025 · 1 comment
Labels
Bug 🐛 This is something that is not working as expected Great MCVE This is a great example of a great MCVE Logging This is related to our logging

Comments

@JaagupAverin
Copy link

JaagupAverin commented Feb 8, 2025

Description

SQLAdminPlugins works on its own but breaks when StructlogPlugin is added. I believe this is a Litestar Internal bug however which is why I'm raising this issue here. I have determined that:

  1. StructlogPlugin attempts to extract request fields when the POST (multi-part) request is sent
  2. litestar/data_extractors.py:172 calls self.extract_body() calls request.form() calls self.stream() calls self.route_handler.resolve_request_max_body_size()
  3. self.route_handler is NOT HTTPRouteHandler as expected, but instead ASGIRouteHandler, which does not support this method.
  4. Exception is raised, but then the exact same issue is triggered again from the exception handler:
        except Exception as exc:
            if self.skip_parse_malformed_body:
                return await request.body() <--- again ends up calling Request.stream(), raising same exception.
            raise exc

URL to code causing the issue

No response

MCVE

from litestar import Litestar
from sqladmin import ModelView
from sqladmin_litestar_plugin import SQLAdminPlugin
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy.orm import declarative_base
from litestar.plugins.structlog import StructlogConfig, StructlogPlugin


engine = create_async_engine("sqlite+aiosqlite:///example.db")
Base = declarative_base()


class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True)
    name = Column(String)


class UserAdmin(ModelView, model=User):
    column_list = [User.id, User.name]


async def on_startup() -> None:
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)  # Create tables


admin = SQLAdminPlugin(views=[UserAdmin], engine=engine)
plugins = [admin]

# Works fine without the StructlogPlugin; but adding the structlog plugin causes errors when creating/editing items in the admin page!
plugins.append(StructlogPlugin())

app = Litestar(plugins=plugins, on_startup=[on_startup])

Steps to reproduce

1. Run example
2. Go to localhost/admin
3. Try to create/edit an user
4. Internal Server Error 500

Screenshots

Logs

"path": "/user/edit/1/",
  "exception_0": {
    "summary": "AttributeError('ASGIRouteHandler' object has no attribute 'resolve_request_max_body_size')",
    "frames": [
      "data_extractors.py:303 (in ConnectionDataExtractor.extract_body)",
      "request.py:267 (in HTMXRequest.form)",
      "_multipart.py:78 (in parse_multipart_form)",
      "request.py:193 (in HTMXRequest.stream)"
    ]
  },
  "exception_1": {
    "summary": "AttributeError('ASGIRouteHandler' object has no attribute 'resolve_request_max_body_size')",
    "frames": [
      "middleware.py:159 (in ExceptionHandlerMiddleware.__call__)",
      "authentication.py:90 (in SessionAuthMiddleware.__call__)",
      "base.py:129 (in LoggingMiddleware.wrapped_call)",
      "logging.py:110 (in LoggingMiddleware.__call__)",
      "logging.py:124 (in LoggingMiddleware.log_request)",
      "logging.py:174 (in LoggingMiddleware.extract_request_data)",
      "data_extractors.py:172 (in ConnectionDataExtractor.extract)",
      "data_extractors.py:311 (in ConnectionDataExtractor.extract_body)",
      "request.py:252 (in HTMXRequest.body)",
      "request.py:193 (in HTMXRequest.stream)"
    ]
  }

Litestar Version

2.14.0

Platform

  • Linux
  • Mac
  • Windows
  • Other (Please specify in the description above)
@JaagupAverin JaagupAverin added the Bug 🐛 This is something that is not working as expected label Feb 8, 2025
@JaagupAverin JaagupAverin changed the title Bug: StructlogPlugins breaks SQLAdminPlugin Bug: StructlogPlugin breaks SQLAdminPlugin Feb 8, 2025
@euri10 euri10 added the Logging This is related to our logging label Feb 9, 2025
@provinzkraut
Copy link
Member

Hah, this is an interesting one.

So I think what's happening here is this:

  • The logging middleware ensures that it's only extracting data from HTTP requests
  • Because it assumes that, it can also safely assume that the incoming connection is a Request (instead of a generic ASGIConnection)
  • Request makes the assumption that it's being constructed from the context of an HTTP route handler (which is guaranteed within Litestar)
  • When mounting another ASGI app however, the route handler is an ASGI handler, but the request type is still HTTP. This means the middleware assumes a Request, which assumes an HTTP route handler, where there's actually an ASGI one

Not entirely sure yet how best to resolve this.


@JaagupAverin as a workaround, you can turn of logging of the request body, that should fix it.

@provinzkraut provinzkraut added the Great MCVE This is a great example of a great MCVE label Feb 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug 🐛 This is something that is not working as expected Great MCVE This is a great example of a great MCVE Logging This is related to our logging
Projects
None yet
Development

No branches or pull requests

3 participants