Skip to content

FastApi application to design API. Linked with Atlas - MongoDB database. Geo positioning requests implemented. Deployed with Docker.

Notifications You must be signed in to change notification settings

Peanuts-83/ny_restaurants_api

Repository files navigation

Python Fastapi MongoDB Docker OpenApi

Newyork restaurants API

Fastapi (python) app linked to Atlas-Mongodb database.

The purpose of this app is to provide quick and simple api to support any front-end project related to.

You can query to collections: restaurants and neighborhoods. Routes have been defined to query for one item, a list of items, distinct values on a field, create, update and delete items or fields.

A little demo api is also defined, not linked to any database, but connected to local variable for quick testing purpose.

Fastapi

Over the fast, intuitive and easy way to build your API, fastapi is totally standard-based giving access to wonderfull OpenAPI (Swagger) and JSON Schema.

By the way, a friend of mine told me Python was one of the worst code language for heat climate change, because it's not a compiled but interpreted language, low to run and large on space disk use |:( (his name's Grumpy!)

Up your choice to use it or not.

Setup project

Use any package manager (pip, conda, ...) to install fastapi, uvicorn and required librairies:

pip install "fastapi[all]"
pip install -r requirements.txt

First launch - set centroid field

Atlas mongoDB provides a Sample Dataset, which sample_restaurants used in this project comes from.

You will find in main.py file a commented line with console_setup() method . Uncomment and activate centroid option in order to update your neighborhoods collection. This way each of your neighborhood item will gain geometry.centroid field, the center coordinates of borough's polygon.

You can then comment console_setup() line back.

Run project

Navigate to the directory where your main.py file is located and run:

uvicorn main:app --reload

--reload option is a watch mode that reloads app at each change in the source code.

Once served:

Debug project

Json conf file is available at .vscode/launch.json, providing abillity to debug api app from "Run and debug" menu in vsCode. Just click Play button in front of Python debugger: FastAPi.

This way you can place breakpoints in your code and access available data at any moment.

OpenApi illustration swagger

Security

Don't expose your private credentials online, use dotenv to use environment variables for your secrets.

.env file (at root level) is added to .gitignore, so you will have to define your own .env file with the credentials required for mongodb connexion.

MONGO_URI=mongodb+srv://<user>:<password>@<mongo_cluster>

Mongodb

You can connect your Atlas cluster with Pymongo library.

This way you shall access your cluster, databases and collections.

The database used in this project called sample_restaurants is available in the Sample Dataset you can load on any free Atlas mongodb account.

Project structure

Demo

A demo module is provided, linked to a simple fake database simulated by a dictionary. The demo_routes are imported to main router with "include_router()" method from fastapi.

Main router

The real router is placed in /routes folder and imported in main.py the same way.

Mongodb connexion is managed in main.py with @app.on_event() decorators.

Models

In order to define easy typing, I suggest to use python 3.9 or later.

Models are mainly defined by Pydantic librairy. It allows to define database schematics with classes which inherit BaseModel from Pydantic.

You will find a nice startup for API setup here.

Debugg in vsCode

launch.json has been set up in ./.vscode/ for debugging purpose (modify values accordingly to your project). Just place the file at the right place and click on Start debugging button from Run and debugg menu.

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python Debugger: FastAPI",
            "type": "debugpy",
            "request": "launch",
            "module": "uvicorn",
            // "justMyCode": false, // to debugg also in libraries!
            "args": [
                "src.app.main:app",
                "--reload"
            ],
            "jinja": true
        }
    ]
}

Deploy

My choice is to deploy this api on a self-hosted place. You can of course deploy it on any server/service you want.

Docker nginx

A docker-compose.yml file let you build a docker image containing nginx and current api app. Running nginx inside Docker offers several advantages:

  • Isolation: Docker containers provide isolation for applications, including the Nginx web server. Each container runs in its own environment, separate from other containers and the host system, which helps prevent conflicts and dependency issues.
  • Portability: Docker containers are portable and can be easily deployed to different environments, such as development, testing, and production, without needing to worry about differences in the underlying system configuration.
  • Scalability: Docker makes it easy to scale applications horizontally by spinning up multiple instances of containers. This allows you to handle increased traffic and workload by distributing the load across multiple instances of Nginx containers.
  • Consistency: Docker enables you to define the environment and dependencies for your Nginx server using a Dockerfile, ensuring consistency across different deployments and environments.

Two dockerfiles set up the configurations required for each part (nginx and fastapi app).

Testing Docker deployement

From root level of the project, several commands may build and serve the app:

# build docker image
docker-compose build
# run docker containers
docker-compose up
# check for containers deployement
docker ps -a

# stop containers
CTL+C # in logs window or
docker-compose stop
# run back containers with logs --follow
docker-compose start -f
# stop and remove containers
docker-compose down
# run back containers with an updated configuration
docker-compose up -d

First tries will be on localhost network so ports should be set up with HTTP (:80)

# docker-compose.yml
version: '3'
services:

  fastapi:
    build:
      context: .
      dockerfile: fastapi_dockerfile
    ports:
      - "8000:8000" # host_port:container_port (:8000 for fastapi)
    env_file:
      - .env # give access to credentials

  nginx:
    build:
      context: .
      dockerfile: nginx_dockerfile
    ports:
      - "8080:80" # host_port (:80 in use on host, so using 8080):container_port(Http)
    depends_on:
      - fastapi # ref to fastapi service above
# nginx.conf
events {}

http {
    upstream fastapi {
        server 127.0.0.1:8000;
    }

    server {
        listen 127.0.0.1:80 default_server;

        location / {
            proxy_pass http://127.0.0.1:8000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }

    }
}

Once containers run, you can test in your browser at uris shown in run project part.

Production deployement

Port HTTPS (:446)

HTTP (:80) is not secure, so HTTPS (:446) must be used for giving access to api from internet. HTTPS allows traffic encryption between client and server, protecting against eavesdropping and interception.

Indeed the following points should also be taken in consideration:

  • Monitor network traffic and server logs for suspicious activity, and implement intrusion detection and prevention systems if necessary.
  • Consider using a web application firewall (WAF) to filter and block malicious traffic before it reaches your server.
  • Regularly audit and review your server's security configuration to identify and address potential vulnerabilities.

Domain name

Domain name is mostly required to expose host's IP address (hence it is possible to expose IP address with ssl-certificate but the cost is higher).

Many registrars give access to domain name registration and DNS management in order to point to your self-hosted server. Then you can get a ssl-certificate from a service like Letsencrypt.org.

docker-compose.yml must reference correct port.

# docker-compose.yml
version: '3'
services:

  fastapi:
    build:
      context: .
      dockerfile: fastapi_dockerfile
    ports:
      - "8000:8000" # host_port:container_port (:8000 for fastapi)
    env_file:
      - .env # give access to credentials

  nginx:
    build:
      context: .
      dockerfile: nginx_dockerfile
    ports:
      - "443:443" # host_port (:80 in use on host, so using 8080):container_port(Http)
    depends_on:
      - fastapi # ref to fastapi service above

nginx.conf must specify port change, domain_name and ssl certificate.

# nginx.conf
events {}

http {
    upstream fastapi {
        server 127.0.0.1:8000;
    }

    server {
    listen 443 ssl;
    server_name your_domain.com;

    ssl_certificate /path/to/your/certificate.crt;
    ssl_certificate_key /path/to/your/privatekey.key;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
}

still W.I.P .... Production deployement part needs to be tested.

About

FastApi application to design API. Linked with Atlas - MongoDB database. Geo positioning requests implemented. Deployed with Docker.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages