{"id":28527508,"url":"https://github.com/peanuts-83/ny_restaurants_api","last_synced_at":"2026-04-10T00:44:30.323Z","repository":{"id":232463637,"uuid":"783404199","full_name":"Peanuts-83/ny_restaurants_api","owner":"Peanuts-83","description":"FastApi application to design API. Linked with Atlas - MongoDB database. Geo positioning requests implemented. Deployed with Docker.","archived":false,"fork":false,"pushed_at":"2025-05-02T21:03:40.000Z","size":1529,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-05T22:37:01.748Z","etag":null,"topics":["api-rest","docker","docker-compose","fastapi","geoposition","mongodb-atlas","openapi","python3","uvicorn"],"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/Peanuts-83.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,"zenodo":null}},"created_at":"2024-04-07T19:44:49.000Z","updated_at":"2025-05-08T16:02:24.000Z","dependencies_parsed_at":"2024-04-10T00:24:36.703Z","dependency_job_id":"d463fa79-591a-4cba-acae-e739a79f6c44","html_url":"https://github.com/Peanuts-83/ny_restaurants_api","commit_stats":null,"previous_names":["peanuts-83/ny_restaurants"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Peanuts-83/ny_restaurants_api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Peanuts-83%2Fny_restaurants_api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Peanuts-83%2Fny_restaurants_api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Peanuts-83%2Fny_restaurants_api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Peanuts-83%2Fny_restaurants_api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Peanuts-83","download_url":"https://codeload.github.com/Peanuts-83/ny_restaurants_api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Peanuts-83%2Fny_restaurants_api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279015055,"owners_count":26085643,"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","status":"online","status_checked_at":"2025-10-13T02:00:06.723Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["api-rest","docker","docker-compose","fastapi","geoposition","mongodb-atlas","openapi","python3","uvicorn"],"created_at":"2025-06-09T12:13:46.275Z","updated_at":"2025-10-13T12:40:33.572Z","avatar_url":"https://github.com/Peanuts-83.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Python](https://img.shields.io/badge/Language-Python-info?logo=python\u0026logoColor=white\u0026color=3776AB)](https://www.python.org/)\n[![Fastapi](https://img.shields.io/badge/Code-Fastapi-info?logo=fastapi\u0026logoColor=white\u0026color=009688)](https://fastapi.tiangolo.com/)\n[![MongoDB](https://img.shields.io/badge/Database-MongoDB-info?logo=mongodb\u0026logoColor=white\u0026color=47A248)](https://www.mongodb.com/)\n[![Docker](https://img.shields.io/badge/Deploy-Docker-info?logo=docker\u0026logoColor=white\u0026color=2496ED)](https://www.docker.com/)\n[![OpenApi](https://img.shields.io/badge/Doc-OpenApi-info?logo=openapiinitiative\u0026logoColor=white\u0026color=6BA539)](https://www.openapis.org/)\n\n# Newyork restaurants API\n\n[Fastapi](https://fastapi.tiangolo.com/) (python) API linked to [Atlas-Mongodb database](https://www.mongodb.com/).\nThe purpose of this app is to provide quick and simple api to support any front-end project related to.\n\nYou 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.\n\n\u003e *A little demo api is also defined, not linked to any database, but connected to local variable for quick testing purpose.*\n\n\n## Quick launch\n\n### Dev mode\n\nTo make some changes and watch effects on the API\n\n```bash\n# build\ndocker-compose build\n# run\ndocker-compose up -d\n# stop\ndocker-compose down\n```\n\n**-d**: detached mode. If you need to see logs, you can dismiss this parameter\n\n### Prod mode\n\nTo make it run on server for production use, refer to [my self-hosted server repository](https://github.com/Peanuts-83/home_server). Adjust path in prepublis.sh script to your use case.\n\n```bash\n# prepublish on server\n./prepublish.sh\n```\n\n\n## Fastapi\n\nOver the fast, intuitive and easy way to build your API, fastapi is totally standard-based giving access to wonderfull [OpenAPI (Swagger)](https://github.com/OAI/OpenAPI-Specification) and [JSON Schema](https://json-schema.org/).\n\nBy 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!)\n\nUp your choice to use it or not.\n\n### Setup project\n\nUse any package manager (pip, conda, ...) [to install fastapi, uvicorn](https://fastapi.tiangolo.com/tutorial/#install-fastapi) and required librairies:\n\n```bash\n# install with conda and a virtual env in my case\nconda create -n NYCrest_env python=3.12.7 anaconda\nconda activate NYCrest_env\npip install -r requirements.txt\n```\n\nSelect right python interpreter: CTL+SHIFT+P \"Python select interpreter\" (I select NYCrest_env)\n\n### First launch - set centroid field\n\nAtlas mongoDB provides a **Sample Dataset**, which **sample_restaurants** used in this project comes from.\n\nYou 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.\n\nYou can then comment *console_setup()* line back.\n\n### Run project\n\nFrom root of the project run (using path to main file for relative imports resolution):\n\n```bash\nuvicorn src.app.main:app --reload\n```\n\n**--reload** option is a watch mode that reloads app at each change in the source code.\n\nOnce served:\n\n* the app shall be available at: \u003chttp://localhost:8000/\u003e\n* **OpenApi documentation** is served at: \u003chttp://localhost:8000/docs\u003e\n* Redoc documentation is served at: \u003chttp://localhost:8000/redoc\u003e\n\n### Debug project\n\nJson conf file is available at .vscode/launch.json, providing abillity to debug api app from \"Run and debug\" menu in vsCode.\nJust click **Play** button in front of **Python debugger: FastAPi**.\n\nThis way you can place breakpoints in your code and access available data at any moment.\n\n**OpenApi illustration**\n![swagger](./assets/swagger.png)\n\n## Security\n\nDon't expose your private credentials online, use [dotenv](https://pypi.org/project/python-dotenv/) to use environment variables for your secrets.\n\n.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.\n\n```env\nMONGO_URI=mongodb+srv://\u003cuser\u003e:\u003cpassword\u003e@\u003cmongo_cluster\u003e\n```\n\n## Mongodb\n\nYou can connect your Atlas cluster with [Pymongo](https://www.mongodb.com/docs/drivers/pymongo/) library.\n\nThis way you shall access your cluster, databases and collections.\n\nThe database used in this project called **sample_restaurants** is available in the **Sample Dataset** you can load on any free Atlas mongodb account.\n\n## Real open data - NYC Open Data (Socrata)\n\n### DocRef\n\n* \u003chttps://dev.socrata.com/foundry/bronx.lehman.cuny.edu/nc96-khaq\u003e\n* \u003chttps://support.socrata.com/hc/en-us/articles/115005364207-Access-Data-Insights-Data-using-OData\u003e\n\n### API\n\n* \u003chttps://data.cityofnewyork.us/api/odata/v4/pitm-atqc\u003e\n\n### Analyse\n\nReal recent data could be used in a second time, on condition to be reformated the right way to apply current model.\nWe can download data in *.csv format, which allows us to rework them and insert them into a DB, and integrate them into a framework which allows a more elegant query system...\n\nThe SoQL (SQL like) query used for the public API is encoded in the url, which gives a disgusting blob! No way I would use this way of exposing my requests. Come on baby, don't you know body payload?!!  XD\n\nQuery for top 100 results from restaurant table with all columns:\n\n* URl\n\n```bash\nhttps://data.cityofnewyork.us/resource/pitm-atqc.json?$query=SELECT%0A%20%20%60objectid%60%2C%0A%20%20%60globalid%60%2C%0A%20%20%60seating_interest_sidewalk%60%2C%0A%20%20%60restaurant_name%60%2C%0A%20%20%60legal_business_name%60%2C%0A%20%20%60doing_business_as_dba%60%2C%0A%20%20%60bulding_number%60%2C%0A%20%20%60street%60%2C%0A%20%20%60borough%60%2C%0A%20%20%60zip%60%2C%0A%20%20%60business_address%60%2C%0A%20%20%60food_service_establishment%60%2C%0A%20%20%60sidewalk_dimensions_length%60%2C%0A%20%20%60sidewalk_dimensions_width%60%2C%0A%20%20%60sidewalk_dimensions_area%60%2C%0A%20%20%60roadway_dimensions_length%60%2C%0A%20%20%60roadway_dimensions_width%60%2C%0A%20%20%60roadway_dimensions_area%60%2C%0A%20%20%60approved_for_sidewalk_seating%60%2C%0A%20%20%60approved_for_roadway_seating%60%2C%0A%20%20%60qualify_alcohol%60%2C%0A%20%20%60sla_serial_number%60%2C%0A%20%20%60sla_license_type%60%2C%0A%20%20%60landmark_district_or_building%60%2C%0A%20%20%60landmarkdistrict_terms%60%2C%0A%20%20%60healthcompliance_terms%60%2C%0A%20%20%60time_of_submission%60%2C%0A%20%20%60latitude%60%2C%0A%20%20%60longitude%60%2C%0A%20%20%60community_board%60%2C%0A%20%20%60council_district%60%2C%0A%20%20%60census_tract%60%2C%0A%20%20%60bin%60%2C%0A%20%20%60bbl%60%2C%0A%20%20%60nta%60%0AORDER%20BY%20%60objectid%60%20ASC%20NULL%20LAST%0ALIMIT%20100%0AOFFSET%200\u0026\n```\n\n* Decoded request\n\n```SQL\n$query: SELECT\n  `objectid`,\n  `globalid`,\n  `seating_interest_sidewalk`,\n  `restaurant_name`,\n  `legal_business_name`,\n  `doing_business_as_dba`,\n  `bulding_number`,\n  `street`,\n  `borough`,\n  `zip`,\n  `business_address`,\n  `food_service_establishment`,\n  `sidewalk_dimensions_length`,\n  `sidewalk_dimensions_width`,\n  `sidewalk_dimensions_area`,\n  `roadway_dimensions_length`,\n  `roadway_dimensions_width`,\n  `roadway_dimensions_area`,\n  `approved_for_sidewalk_seating`,\n  `approved_for_roadway_seating`,\n  `qualify_alcohol`,\n  `sla_serial_number`,\n  `sla_license_type`,\n  `landmark_district_or_building`,\n  `landmarkdistrict_terms`,\n  `healthcompliance_terms`,\n  `time_of_submission`,\n  `latitude`,\n  `longitude`,\n  `community_board`,\n  `council_district`,\n  `census_tract`,\n  `bin`,\n  `bbl`,\n  `nta`\nORDER BY `objectid` ASC NULL LAST\nLIMIT 100\nOFFSET 0\n```\n\n## Project structure\n\n### Demo\n\nA demo module is provided, linked to a simple fake database simulated by a dictionary.\nThe demo_routes are imported to main router with \"include_router()\" method from fastapi.\n\n### Main router\n\nThe real router is placed in /routes folder and imported in main.py the same way.\n\nMongodb connexion is managed in main.py with @app.on_event() decorators.\n\n## Models\n\nIn order to define easy typing, I suggest to use python 3.9 or later.\n\nModels are mainly defined by [Pydantic](https://docs.pydantic.dev/) librairy.\nIt allows to define database schematics with classes which inherit BaseModel from Pydantic.\n\nYou will find a nice startup for API setup [here](https://www.mongodb.com/languages/python/pymongo-tutorial).\n\n## Debugg in vsCode\n\n**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.\n\n```json\n{\n    // Use IntelliSense to learn about possible attributes.\n    // Hover to view descriptions of existing attributes.\n    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"name\": \"Python Debugger: FastAPI\",\n            \"type\": \"debugpy\",\n            \"request\": \"launch\",\n            \"module\": \"uvicorn\",\n            // \"justMyCode\": false, // to debugg also in libraries!\n            \"args\": [\n                \"src.app.main:app\",\n                \"--reload\"\n            ],\n            \"jinja\": true\n        }\n    ]\n}\n```\n\n## Deploy\n\nMy choice is to deploy this api on a self-hosted place. You can of course deploy it on any server/service you want.\n\n### Docker nginx\n\nA docker-compose.yml file let you build a docker image containing nginx and current api app.\nRunning nginx inside Docker offers several advantages:\n\n* 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.\n* 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.\n* 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.\n* Consistency: Docker enables you to define the environment and dependencies for your Nginx server using a Dockerfile, ensuring consistency across different deployments and environments.\n\nTwo dockerfiles set up the configurations required for each part (nginx and fastapi app).\n\n### Testing Docker deployement\n\nFrom root level of the project, several commands may build and serve the app:\n\n```bash\n# build docker image\ndocker-compose build\n# run docker containers\ndocker-compose up\n# check for containers deployement\ndocker ps -a\n\n# stop containers\nCTL+C # in logs window or\ndocker-compose stop\n# run back containers with logs --follow\ndocker-compose start -f\n# stop and remove containers\ndocker-compose down\n# run back containers with an updated configuration\ndocker-compose up -d\n```\n\nFirst tries will be on localhost network so ports should be set up with HTTP (:80)\n\n```yml\n# docker-compose.yml\nversion: '3'\nservices:\n\n  fastapi:\n    build:\n      context: .\n      dockerfile: fastapi_dockerfile\n    ports:\n      - \"8000:8000\" # host_port:container_port (:8000 for fastapi)\n    env_file:\n      - .env # give access to credentials\n\n  nginx:\n    build:\n      context: .\n      dockerfile: nginx_dockerfile\n    ports:\n      - \"8080:80\" # host_port (:80 in use on host, so using 8080):container_port(Http)\n    depends_on:\n      - fastapi # ref to fastapi service above\n```\n\n```conf\n# nginx.conf\nevents {}\n\nhttp {\n    upstream fastapi {\n        server 127.0.0.1:8000;\n    }\n\n    server {\n        listen 127.0.0.1:80 default_server;\n\n        location / {\n            proxy_pass http://127.0.0.1:8000;\n            proxy_set_header Host $host;\n            proxy_set_header X-Real-IP $remote_addr;\n            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n            proxy_set_header X-Forwarded-Proto $scheme;\n        }\n\n    }\n}\n\n```\n\nOnce containers run, you can test in your browser at uris shown in [run project part](#run-project).\n\n### Production deployement\n\n#### Port HTTPS (:443)\n\nHTTP (:80) is not secure, so HTTPS (:443) must be used for giving access to api from internet. HTTPS allows traffic encryption between client and server, protecting against eavesdropping and interception.\n\nIndeed the following points should also be taken in consideration:\n\n* Monitor network traffic and server logs for suspicious activity, and implement intrusion detection and prevention systems if necessary.\n* Consider using a web application firewall (WAF) to filter and block malicious traffic before it reaches your server.\n* Regularly audit and review your server's security configuration to identify and address potential vulnerabilities.\n\n#### Domain name\n\nDomain 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).\n\nMany registrars give access to domain name registration and DNS management in order to point to your self-hosted server.\nThen you can get a ssl-certificate from a service like [Letsencrypt.org](https://letsencrypt.org/).\n\ndocker-compose.yml must reference correct port.\n\n```yml\n# docker-compose.yml\nversion: '3'\nservices:\n\n  fastapi:\n    build:\n      context: .\n      dockerfile: fastapi_dockerfile\n    ports:\n      - \"8000:8000\" # host_port:container_port (:8000 for fastapi)\n    env_file:\n      - .env # give access to credentials\n\n  nginx:\n    build:\n      context: .\n      dockerfile: nginx_dockerfile\n    ports:\n      - \"443:443\" # host_port (:80 in use on host, so using 8080):container_port(Http)\n    depends_on:\n      - fastapi # ref to fastapi service above\n```\n\nnginx.conf must specify port change, domain_name and ssl certificate.\n\n```conf\n# nginx.conf\nevents {}\n\nhttp {\n    upstream fastapi {\n        server 127.0.0.1:8000;\n    }\n\n    server {\n    listen 443 ssl;\n    server_name your_domain.com;\n\n    ssl_certificate /path/to/your/certificate.crt;\n    ssl_certificate_key /path/to/your/privatekey.key;\n\n    location / {\n        proxy_pass http://127.0.0.1:8000;\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n    }\n}\n}\n```\n\nstill W.I.P ....\nProduction deployement part needs to be tested.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeanuts-83%2Fny_restaurants_api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpeanuts-83%2Fny_restaurants_api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeanuts-83%2Fny_restaurants_api/lists"}