{"id":15288727,"url":"https://github.com/kludex/flake8-fastapi","last_synced_at":"2025-04-13T06:15:18.026Z","repository":{"id":40239348,"uuid":"372750696","full_name":"Kludex/flake8-fastapi","owner":"Kludex","description":"Flake8 FastAPI - Avoid simple FastAPI mistakes ~opinionated~ 🤓","archived":false,"fork":false,"pushed_at":"2023-01-29T09:52:34.000Z","size":83,"stargazers_count":44,"open_issues_count":3,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-13T06:15:11.732Z","etag":null,"topics":["asgi","fastapi","flake8","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Kludex.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-06-01T08:07:52.000Z","updated_at":"2025-02-23T02:41:46.000Z","dependencies_parsed_at":"2023-02-15T22:00:44.041Z","dependency_job_id":null,"html_url":"https://github.com/Kludex/flake8-fastapi","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kludex%2Fflake8-fastapi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kludex%2Fflake8-fastapi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kludex%2Fflake8-fastapi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kludex%2Fflake8-fastapi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Kludex","download_url":"https://codeload.github.com/Kludex/flake8-fastapi/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248670434,"owners_count":21142904,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asgi","fastapi","flake8","python"],"created_at":"2024-09-30T15:52:28.578Z","updated_at":"2025-04-13T06:15:18.006Z","avatar_url":"https://github.com/Kludex.png","language":"Python","readme":"\u003ch1 align=\"center\"\u003e\n    \u003cstrong\u003eflake8-fastapi\u003c/strong\u003e\n\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/Kludex/flake8-fastapi\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/last-commit/Kludex/flake8-fastapi\" alt=\"Latest Commit\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/Kludex/flake8-fastapi/actions/workflows/test.yml\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://github.com/Kludex/flake8-fastapi/actions/workflows/test.yml/badge.svg\" alt=\"Test workflow action\"\u003e\n    \u003c/a\u003e\n        \u003cimg src=\"https://img.shields.io/codecov/c/github/Kludex/flake8-fastapi\"\u003e\n    \u003cbr /\u003e\n    \u003ca href=\"https://pypi.org/project/flake8-fastapi\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://img.shields.io/pypi/v/flake8-fastapi\" alt=\"Package version\"\u003e\n    \u003c/a\u003e\n    \u003cimg src=\"https://img.shields.io/pypi/pyversions/flake8-fastapi\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/license/Kludex/flake8-fastapi\"\u003e\n\u003c/p\u003e\n\nA [flake8](https://flake8.pycqa.org/en/latest/index.html) plugin that helps you avoid simple FastAPI mistakes.\n\n## Installation\n\nFirst, install the package:\n\n``` bash\npip install flake8-fastapi\n```\n\nThen, check if the plugin is installed using `flake8`:\n\n``` bash\n$ flake8 --version\n6.0.0 (flake8-fastapi: 0.7.0, mccabe: 0.7.0, pycodestyle: 2.10.0, pyflakes: 3.0.1) CPython 3.8.11 on Linux\n```\n\n## Rules\n\n\u003c!-- prettier-ignore-start --\u003e\n  - [CF001 - Route Decorator Error](#cf001---route-decorator-error)\n  - [CF002 - Router Prefix Error](#cf002---router-prefix-error)\n  - [CF008 - CORSMiddleware Order](#cf008---corsmiddleware-order)\n  - [CF009 - Undocumented HTTPException](#cf009---undocumented-httpexception)\n  - [CF011 - No Content Response](#cf011---no-content-response)\n\u003c!-- prettier-ignore-end --\u003e\n\n### CF001 - Route Decorator Error\n\nDevelopers that were used to [flask](https://flask.palletsprojects.com/en/2.0.x/) can be persuaded or want to use the same pattern in FastAPI:\n\n```python\nfrom fastapi import FastAPI\n\napp = FastAPI()\n\n\n@app.route(\"/\", methods=[\"GET\"])\ndef home():\n    return \"Hello world!\"\n```\n\nBut on FastAPI, we have a simpler way to define this (and is the most known way to create endpoints):\n\n```python\nfrom fastapi import FastAPI\n\napp = FastAPI()\n\n\n@app.get(\"/\")\ndef home():\n    return \"Hello world!\"\n```\n\n### CF002 - Router Prefix Error\n\nOn old FastAPI versions, we were able to add a prefix only on the `include_router` method:\n\n```python\nfrom fastapi import APIRouter, FastAPI\n\nrouter = APIRouter()\n\n\n@router.get(\"/\")\ndef home():\n    ...\n\n\napp = FastAPI()\napp.include_router(router, prefix=\"/prefix\")\n```\n\nNow, it's possible to add in the `Router` initialization:\n\n```python\nfrom fastapi import APIRouter, FastAPI\n\nrouter = APIRouter(prefix=\"/prefix\")\n\n\n@router.get(\"/\")\ndef home():\n    ...\n\n\napp = FastAPI()\napp.include_router(router)\n```\n\n\n### CF008 - CORSMiddleware Order\n\nThere's a [tricky issue](https://github.com/tiangolo/fastapi/issues/1663) about [CORSMiddleware](https://www.starlette.io/middleware/#corsmiddleware) that people are usually unaware. Which is that this middleware should be the last one on the middleware stack. You can read more about it [here](https://github.com/tiangolo/fastapi/issues/1663).\n\nLet's see an example of what doesn't work:\n\n```python\nfrom fastapi import FastAPI\n\napp = FastAPI()\n\napp.add_middleware(\n    CORSMiddleware,\n    allow_origins=['*'],\n    allow_credentials=True,\n    allow_methods=['*'],\n    allow_headers=['*']\n)\napp.add_middleware(GZipMiddleware)\n```\n\nAs you see, the last middleware added is not `CORSMiddleware`, so it will not work as expected. On the other hand, if you change the order, it will:\n\n```python\nfrom fastapi import FastAPI\n\napp = FastAPI()\n\napp.add_middleware(GZipMiddleware)\napp.add_middleware(\n    CORSMiddleware,\n    allow_origins=['*'],\n    allow_credentials=True,\n    allow_methods=['*'],\n    allow_headers=['*']\n)\n```\n\n### CF009 - Undocumented HTTPException\n\nCurrently, there's no automatic solution to document the `HTTPException`s, besides the experimental package [`fastapi-responses`](https://github.com/Kludex/fastapi-responses).\n\nFor that reason, it's easy to forget the documentation, and have a lot of undocumented endpoints. Let's see an example:\n\n```python\nfrom fastapi import FastAPI, HTTPException\n\napp = FastAPI()\n\n\n@app.get(\"/\")\ndef home():\n    raise HTTPException(status_code=400, detail=\"Bad Request\")\n```\n\nThe above endpoint doesn't have a `responses` field, even if it's clear that the response will have a `400` status code.\n\n### CF011 - No Content Response\n\nCurrently, if you try to send a response with no content (204), FastAPI will send a 204 status with a non-empty body.\nIt will send a body content-length being 4 bytes.\n\nYou can verify this statement running the following code:\n\n```python\n# main.py\nfrom fastapi import FastAPI\n\napp = FastAPI()\n\n\n@app.get(\"/\", status_code=204)\ndef home():\n    ...\n```\n\nNow feel free to run with your favorite server implementation:\n\n```bash\nuvicorn main:app\n```\n\nThen use curl or any other tool to send a request:\n\n```bash\n$ curl localhost:8000\n*   Trying 127.0.0.1:8000...\n* TCP_NODELAY set\n* Connected to localhost (127.0.0.1) port 8000 (#0)\n\u003e GET / HTTP/1.1\n\u003e Host: localhost:8000\n\u003e User-Agent: curl/7.68.0\n\u003e Accept: */*\n\u003e\n* Mark bundle as not supporting multiuse\n\u003c HTTP/1.1 204 No Content\n\u003c date: Sat, 24 Jul 2021 19:21:24 GMT\n\u003c server: uvicorn\n\u003c content-length: 4\n\u003c content-type: application/json\n\u003c\n* Connection #0 to host localhost left intact\n```\n\nThis goes against the [RFC](https://tools.ietf.org/html/rfc7231#section-6.3.5), which specifies that a 204 response should have no body.\n\n## License\n\nThis project is licensed under the terms of the MIT license.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkludex%2Fflake8-fastapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkludex%2Fflake8-fastapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkludex%2Fflake8-fastapi/lists"}