/people_api

Primary LanguagePythonMIT LicenseMIT

A Very Simple REST API.

Overview

This minimal REST API stores person records. Each person is uniquely identifiable by their associated person_id (UUID) and version. Once a unique person is created, updates to the person's attributes result in the creation of a new record with the same person_id, but with a new version attribute. Only the most current version of a person can be updated. When a person is updated, the API enforces that there are changes compared to the current version. It does not, however, verify that the new version is unique across all versions for the associated person_id. The most current version of a person can be deleted.

Bulk queries are not supported at this time.

This project was built using Python3.8, the FastAPI framework, and PostgreSQL, all running stress-free in Docker.

Why FastAPI? There's been a lot of talk about this framework and I've been eager to test drive it. It did not disappoint. It has superior async support--there's absolutely no need to think about event loops. FastAPI uses mandatory data validation via pydantic, which provides smooth error handling and enables very nice auto-generated documentation. Recommend. 10/10. Would use again.


Run

These instructions assume the host is running MacOS or Linux and Docker is installed.

To run,

  • clone repo
  • cd into project root, then...
$ docker-compose up -d --build

Test the service is running by navigating to http://localhost:8002/docs.

To run the unit tests...

$ tox --

Authentication and Credentials

There is currently no authentication. The PostgreSQL credentials are hard-coded where needed (and checked into version control). This is deliberate, as this is only a POC. If this were going to be used in production, credentials never would have been checked into version control.

Remove the hardcoded DB credentials and change the login and password prior to public use.


API Documentation

When the service is running, detailed Swagger/OpenAPI documentation can be found at the /docs endpoint. check it out here. Or the ReDoc version here.

Overview of Available REST Endpoints:

ENDPOINT ACTION REQ. PARAM OPTIONAL PARAMS BODY REQUIRED
/person/ POST None None Yes
/person/ GET person_id version No
/person/ PUT person_id None Yes
/person/ DELETE person_id None No
/persons/ GET None None No

Sample curls:

POST /person/

$ curl -X POST "http://localhost:8002/person/" -H  "accept: application/json" -H  "Content-Type: application/json" -d '{"first_name":"guido","last_name":"van rossum","email":"guidovr@python.com","age":64}' -i

GET /person/{person_id}

$ curl -X GET "http://localhost:8002/person/843651c0-4e05-4960-a274-95578912bfe1" -H "accept: application/json" -i

PUT /person/

$ curl -X PUT "http://localhost:8002/person/" -H  "accept: application/json" -H  "Content-Type: application/json" -d "{'person_id':'843651c0-4e05-4960-a274-95578912bfe1','email':'guidovr@python3.com'}" -i

DELETE /person/{person_id}

curl -X DELETE "http://localhost:8002/person/843651c0-4e05-4960-a274-95578912bfe1" -H  "accept: application/json" -i

GET /persons/

$ curl -X GET "http://localhost:8002/persons/" -H "accept: application/json" -i

The project's Swagger Documentation contains sample request and response objects, as well as the ability to interactively test the API.

A note on mandatory trailing /'s in requests. In an effort to keep the swagger clean since this is just a POC, I chose not to go with either of the two inelegant options discussed here. TL;DR: changes to a FastAPI dependency broke standard regex in routes.


Considerations

  • DB Transactions. Currently no DB queries are transactional/atomic. The downside to this is obvious. In addition to increasing data integrity, using transactional, atomic queries would reduce the complexity of the handler code.
  • Relational vs Non-Relational. Lots of thoughts here.
  • Delete returns success even if no target record was found. There are varying opinions on this behavior. From a security standpoint it could be considered a feature, from a usability standpoint it could be viewed as a bug.

Future Features

  • Cache. Caching the latest version of each person with some TTL will reduce the need for the most common DB query.
  • Testing. This needs integration tests. And more unit tests!!
  • Logging

Code Convention and Style

This project mostly conforms to the standards in PEP-8. Max line length is extended to 88 characters, which is Black's default line-length.