{"id":16514727,"url":"https://github.com/andgineer/api-db-prototype","last_synced_at":"2026-05-09T20:01:57.477Z","repository":{"id":145706260,"uuid":"156404690","full_name":"andgineer/api-db-prototype","owner":"andgineer","description":"API with SQL Alchemy layer alternatively implemented with Flask and Connexion","archived":false,"fork":false,"pushed_at":"2025-02-18T16:57:38.000Z","size":1282,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-18T17:38:02.521Z","etag":null,"topics":["alembic","connexion","flask","flask-login","jwt","sqlalchemy"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andgineer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-11-06T15:28:08.000Z","updated_at":"2025-02-18T16:56:28.000Z","dependencies_parsed_at":null,"dependency_job_id":"9ea4e909-1dbc-4a08-9f8b-1499a1d464f8","html_url":"https://github.com/andgineer/api-db-prototype","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andgineer%2Fapi-db-prototype","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andgineer%2Fapi-db-prototype/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andgineer%2Fapi-db-prototype/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andgineer%2Fapi-db-prototype/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andgineer","download_url":"https://codeload.github.com/andgineer/api-db-prototype/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241511724,"owners_count":19974451,"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":["alembic","connexion","flask","flask-login","jwt","sqlalchemy"],"created_at":"2024-10-11T16:13:32.272Z","updated_at":"2026-05-09T20:01:57.472Z","avatar_url":"https://github.com/andgineer.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://github.com/andgineer/api-db-prototype/workflows/ci/badge.svg)](https://github.com/andgineer/api-db-prototype/actions)\n[![Coverage](https://raw.githubusercontent.com/andgineer/api-db-prototype/python-coverage-comment-action-data/badge.svg)](https://htmlpreview.github.io/?https://github.com/andgineer/api-db-prototype/blob/python-coverage-comment-action-data/htmlcov/index.html)\n# API server experiment\n\nThis project is an experimental implementation of an API server using different approaches.\n\n## Approaches\n\n1. **Connexion - Spec First**\n2. **Flask - Code First**\n\nIn both cases, we use SQLAlchemy for DB access and Alembic for DB versioning, implement JWT auth,\nand provide Swagger UI.\n\n## Common Controllers\n\nIn this project, we're trying to create controllers (application logic)\nthat can be shared between the two different approaches we're using.\n\nHowever, because of the way Connexion generates code, we can't use application objects in the\ncontrollers parameters. We have to keep their signatures a bit more generic to work with both\napproaches.\n\n## Real-World Considerations\n\nIn a real-world project, it is advisable to choose a single approach and use it consistently.\n\nFrameworks like FastAPI and LiteStar utilize Python type hinting to automatically generate\nAPI specifications. I would prefer them over Flask.\n\nIn contrast, Connexion generates Python code from API specs, requiring you to develop the API\nspecification first.\n\nThe choice between these approaches depends on various factors, including project size, development team size,\nand the requirement to implement an external API specification.\n\n# Run dev version (Flask Werkzeug) with auto reload on source change\n\n    . ./activate.sh  # Build and/or activate virtual environment\n    make run  # Run dev server\n\n# API UI\n[Swagger UI](http://127.0.0.1:5000/ui)\n\n### To authorize API calls:\n- Execute from the UI API request `Users` -\u003e `Auth` -\u003e `Try it`\n  - email `admin@`, password `admin`\n  - press `Execute`\n  - copy the token from the response\n- On top of the page press green button with lock icon `Authorize`\n  - paste in the `Value` the token\n  - press `Authorize` and after that `Close`\n\nAfter that you can send all the API requests (`Try it out` button).\nSwagger API will automatically add the security token.\n\n# Folders overview\n\n* `api` - Swagger (Open API) description of the API\n* `src/db` - SQLAlchemy models\n* `src/alembic` - DB metadata versioning\n* `src/controllers` - Application logic common for Flask and Connexion\n* `src/flask_server` - HTTP server (request routing to application logic)\n* `src/openapi_server` - Auto-generated with `make codegen`.\n`controllers/` and `encoder.py` are manually modified.\n* `src/settings.py` - Configs for test/dev/prod\n* `src/build_timestamp` - Autogenerated file with last git commit timestamp to use as 'build' time - see `make git-hook-install`\n* `src/secret` - Key and certificate for signing and verification of security tokens (`jwt_token.py`)\n* `src/tests` - Pytest tests, to run use `make test`\n* `src/app.py` - ASGI/WSGI app\n* `src/journaling.py` - Central journaling settings\n* `src/jwt_token.py` - Security tokens\n* `src/password_hash.py` - Password hashing\n* `src/config.py` - Config loader, is not used in this project\n\n# Scripts\n\n    make help\n\n# Development\n\n## Virtual environment\n\nUse `. ./activate.sh` to create and/or activate.\n\nAnd `deactivate` to exit.\n\nTo upgrade python packages in the virtual environment use `make reqs`.\n\n## DB\n\nThe project uses SQLAlchemy and Alembic for DB access and versioning.\n\nTo create objects in an empty DB:\n\n    make db-create\n\nThe DB connect string is in `src/settings.py`.\n\nOther DB-related commands:\n\n    make db-upgrade\n    make db-show-migration\n    make db-migration\n\n## API development\nTo add new requests to the API, first implement controllers for them in `src/controllers/`.\nNext, we use different approaches for Flask and Connexion.\n\n### Flask\nImplement proxies for the requests in `src/flask_server/api_app.py`.\n\n### Connexion\nAdd new requests to the API spec in `api/swagger.yaml`.\n\nRun `make codegen` to generate new code in `src/openapi_server/`.\n\nUnfortunately, this can break some manual changes - for example, I had to\nmodify `src/openapi_server/encoder.py`. In most cases, you can just rollback unwanted changes.\n\nNext, implement proxies for the requests in `src/openapi_server/controllers`\nusing signatures from auto-generated `src/openapi_server/controllers_boilerplate`.\n\n## Libraries\n\n* [Flask](https://flask.palletsprojects.com/en/3.0.x/)\n* [Flask OpenAPI UI](https://github.com/sveint/flask-swagger-ui)\n* [Connexion](https://connexion.readthedocs.io/en/latest/index.html)\n* DB [SQLAlchemy](http://wiki.python.su/%D0%94%D0%BE%D0%BA%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%86%D0%B8%D0%B8/SQLAlchemy)\n* [alembic](https://pypi.org/project/alembic/) for DB metadata versioning\n* [flask-login](https://flask-login.readthedocs.io/en/latest/)\n* [jwt](https://realpython.com/token-based-authentication-with-flask/)\n\n\n## Open API (Swagger) spec\n\nYou can convert the Swagger file `api/swagger.yaml` into a document at\nhttps://editor.swagger.io or in the AWS console - `Amazon AWS API Gateway`.\n\nVisualization is also available on [Swagger Hub](https://app.swaggerhub.com/apis/andgineer/api-db-prototype/1.0-oas3)\n\n## Configs\n\nSee `settings.py`.\n\nFor `Prod` config you should specify DB in `settings.py`.\nThis config would be used by default (if no `SERVER_ENV` specified).\n\n## JWT keys\n\nFor web token crypto, the server uses keys from files configured in the config\nobject.\nThe default is `secret/`.\n\nFor an example of how to recreate keys, see `create_keys.sh`.\nThe private key is for token issuing.\n\nIf the web application gets tokens from an external service\nlike Amazon Cognito, you should provide only the public key from that\nexternal service, so our server can check this external service's tokens.\n\nThe public key is expected in `pem` certificate format.\n\n## Python version\n\nAt least 3.10 because we use [Concatenate](https://peps.python.org/pep-0612/)\n\n# Production\n\nIn production, you should use production-ready servers like\nGunicorn or uWSGI.\n\n[WSGI for Flask](https://flask.palletsprojects.com/en/3.0.x/deploying/) and\n[ASGI for Connexion](https://connexion.readthedocs.io/en/latest/quickstart.html#running-your-application).\n\nSee example in `prod.sh` and `Dockerfile`.\n\n## Coverage report\n* [Codecov](https://app.codecov.io/gh/andgineer/api-db-prototype/tree/master/src)\n* [Coveralls](https://coveralls.io/github/andgineer/api-db-prototype)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandgineer%2Fapi-db-prototype","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandgineer%2Fapi-db-prototype","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandgineer%2Fapi-db-prototype/lists"}