Skip to content

[BUG]match to wrong router method if prefix is same #280

@fishjam

Description

@fishjam

Describe the bug
I create a user.py to check fastapi-utils, there are 4 method.

  • @router.get("/user")
  • @router.post("/user")
  • @router.get("/user/{user_id}")
  • @router.get("/user/query_by_name")

when I try execute the query_by_name, seems it match to /user/{user_id}. and get HTTP/1.1 422 Unprocessable Entity Error.

Screenshots
image

Environment:

  • OS: [Windows]
  • FastAPI Utils: 0.2.1
  • FastAPI: 0.101.0
  • Pydantic: 1.10.12
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import http.client

from fastapi import Body, Query
from fastapi_utils.cbv import cbv
from pydantic import BaseModel, Field

from demos.routers.common import router
from fjutils.logHelper import logger
from tools.common.webSupport import CommonResponse, ResponseFactory


class User(BaseModel):
    id: int = Field(..., description="User id")
    name: str = Field(..., description="User name")


@cbv(router)
class UserRouter:
    def __init__(self):
        logger.info("Enter UserRouter.__init__")  # TODO: every router method will print this

    user_maps = {
        1: User(id=1, name="userA"),
        2: User(id=2, name="userB"),
        3: User(id=3, name="userC"),
        4: User(id=4, name="userD"),
        5: User(id=5, name="userE"),
    }

    @router.get("/user", tags=["User"])
    async def get_user_list(self, skip: int = 0, limit: int = 10) -> CommonResponse:
        logger.info(f"get user list, len={len(self.user_maps)}, self={self}")
        return ResponseFactory.ok(list(self.user_maps.values())[skip: skip + limit])

    @router.post("/user", tags=["User"])
    async def create_user(self, user: User = Body(...)) -> CommonResponse:
        self.user_maps[user.id] = user
        logger.info(f"input user={user}, len(user_maps)={len(self.user_maps)}, self={self}")
        return ResponseFactory.ok(user)

    @router.get("/user/{user_id}", tags=["User"])
    async def get_user_by_id(self, user_id: int) -> CommonResponse:
        logger.info(f"get user by id={user_id}")
        if user_id in self.user_maps:
            return ResponseFactory.ok(self.user_maps.get(user_id))
        else:
            return ResponseFactory.error(http.HTTPStatus.NOT_FOUND, "not found", None)

    @router.get("/user/query_by_name", tags=["User"])  # , response_model=CommonResponse[list(User)]
    async def query_user_by_name(self, name: str = Query(..., max_length=10)) -> CommonResponse:
        logger.info(f"query name={name}")
        result = []
        for k, v in self.user_maps.items():
            if name.upper() in v.upper():
                result.append(v)
        return ResponseFactory.ok(result)
  • Python version, get it with:
    Python 3.10.12

Additional context
BTW: I add log in __init__ method, I found every I execute the rest api, the __init__ will execute, is it right?

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions