Skip to content
This repository was archived by the owner on Jun 13, 2024. It is now read-only.

Commit 7b3decb

Browse files
committed
First Commit
0 parents  commit 7b3decb

29 files changed

+540
-0
lines changed

.env.example

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
APP_HOST = '0.0.0.0'
2+
APP_PORT = 8000
3+
4+
SSL_CERTIFICATE = '/etc/ssl/certs/certificate.crt'
5+
SSL_KEYFILE = '/etc/ssl/private/private.key'

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
* linguist-detectable=false
2+
*.yml linguist-detectable=true

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
__pycache__/
2+
*.pyc
3+
*.pyo
4+
*.env

LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022 Natthasath Saksupanara
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# 🎉 Template Python FastAPI
2+
3+
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints. It has a simple and easy to use API, is lightweight, and includes features like asynchronous support, dependency injection, and more.
4+
5+
![version](https://img.shields.io/badge/version-1.0-blue)
6+
![rating](https://img.shields.io/badge/rating-★★★★★-yellow)
7+
![uptime](https://img.shields.io/badge/uptime-100%25-brightgreen)
8+
9+
### 🏆 Run
10+
11+
- [http://localhost:8000/docs](http://localhost:8000/docs)
12+
- [http://localhost:8000/subapi/docs](http://localhost:8000/subapi/docs)
13+
14+
```shell
15+
docker-compose up -d --scale app=3
16+
```

app/api.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from fastapi import FastAPI
2+
from fastapi.middleware.cors import CORSMiddleware
3+
from app.routers import template
4+
from app.tag import SubTags, Tags
5+
6+
app = FastAPI(
7+
title="FastAPI",
8+
description="Web API helps you do awesome stuff. 🚀",
9+
version="0.0.1",
10+
terms_of_service="http://example.com/terms/",
11+
contact={
12+
"name": "Information and Digital Technology Center (IDT)",
13+
"url": "https://codeinsane.wordpress.com/",
14+
"email": "natthasath.sak@gmail.com",
15+
},
16+
license_info={
17+
"name": "Apache 2.0",
18+
"url": "https://www.apache.org/licenses/LICENSE-2.0.html",
19+
},
20+
openapi_url="/api/v1/openapi.json",
21+
docs_url="/docs",
22+
openapi_tags=Tags(),
23+
swagger_ui_parameters={"defaultModelsExpandDepth": -1}
24+
)
25+
26+
origins = ["*"]
27+
app.add_middleware(
28+
CORSMiddleware,
29+
allow_origins=origins,
30+
allow_credentials=True,
31+
allow_methods=["*"],
32+
allow_headers=["*"],
33+
)
34+
35+
app.include_router(template.router)
36+
#
37+
#
38+
#
39+
40+
subapi = FastAPI(openapi_tags=SubTags(), swagger_ui_parameters={"defaultModelsExpandDepth": -1})
41+
42+
subapi.add_middleware(
43+
CORSMiddleware,
44+
allow_origins=origins,
45+
allow_credentials=True,
46+
allow_methods=["*"],
47+
allow_headers=["*"],
48+
)
49+
50+
subapi.include_router(template.router)
51+
#
52+
#
53+
#
54+
55+
app.mount("/subapi", subapi)

app/doc/.gitkeep

Whitespace-only changes.

app/font/.gitkeep

Whitespace-only changes.

app/handler/.gitkeep

Whitespace-only changes.

app/img/.gitkeep

Whitespace-only changes.

app/json/.gitkeep

Whitespace-only changes.

app/log/access.log

Whitespace-only changes.

app/models/model_template.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from fastapi import Form
2+
from pydantic import BaseModel, Field, EmailStr, SecretStr
3+
from typing import List, Union
4+
import inspect
5+
6+
def form_body(cls):
7+
cls.__signature__ = cls.__signature__.replace(
8+
parameters=[
9+
arg.replace(default=Form(default = arg.default) if arg.default is not inspect._empty else Form(...))
10+
for arg in cls.__signature__.parameters.values()
11+
]
12+
)
13+
return cls
14+
15+
@form_body
16+
class TemplateSchema(BaseModel):
17+
id: int = Field(default=None)
18+
19+
class Config:
20+
schema_extra = {
21+
"example": {
22+
"id": "Incremental Number"
23+
}
24+
}

app/routers/template.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from fastapi import APIRouter, Depends, Form
2+
from fastapi.responses import JSONResponse
3+
4+
router = APIRouter(
5+
prefix="/template",
6+
tags=["TEMPLATE"],
7+
responses={404: {"message": "Not found"}}
8+
)
9+
10+
@router.get("/")
11+
async def root():
12+
return {"message": "Hello World"}

app/services/service_template.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from decouple import config
2+
from fastapi.responses import JSONResponse
3+
4+
class TemplateService:
5+
def __init__(self):
6+
self.config = config("CONF_NAME")

app/sql/.gitkeep

Whitespace-only changes.

app/tag.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
def Tags():
2+
tags_metadata = [
3+
{
4+
"name": "AUTHENTICATION",
5+
"description": "Authentication using JSON Web Tokens (JWT) with **PyJWT** for sign, encode, and decode",
6+
"externalDocs": {
7+
"description": "Items external docs",
8+
"url": "https://testdriven.io/blog/fastapi-jwt-auth/",
9+
},
10+
},
11+
]
12+
return tags_metadata
13+
14+
def SubTags():
15+
tags_metadata = [
16+
{
17+
"name": "AUTHENTICATION",
18+
"description": "Authentication using JSON Web Tokens (JWT) with **PyJWT** for sign, encode, and decode",
19+
"externalDocs": {
20+
"description": "Items external docs",
21+
"url": "https://testdriven.io/blog/fastapi-jwt-auth/",
22+
},
23+
},
24+
]
25+
return tags_metadata

app/template/.gitkeep

Whitespace-only changes.

app/tmp/.gitkeep

Whitespace-only changes.

certs/certificate.crt

Whitespace-only changes.

certs/private.key

Whitespace-only changes.

config/nginx.conf

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
worker_processes 1;
2+
3+
events { worker_connections 1024; }
4+
5+
http {
6+
upstream myapi {
7+
server app:8000;
8+
}
9+
10+
server {
11+
listen 80;
12+
server_name example.com;
13+
14+
location / {
15+
proxy_pass http://myapi;
16+
proxy_set_header Host $host;
17+
proxy_set_header X-Real-IP $remote_addr;
18+
}
19+
}
20+
}

docker/.dockerignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
**/.env
2+
**/.aws
3+
**/.ssh
4+
__pycache__/
5+
*.pyc
6+
*.pyo

docker/Dockerfile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
FROM python:3.9
2+
3+
WORKDIR /code
4+
5+
COPY ./requirements.txt /code/requirements.txt
6+
COPY ./.env /code/.env
7+
COPY ./main.py /code/main.py
8+
COPY ./app /code/app
9+
10+
COPY ./certs/certificate.crt /etc/ssl/certs/
11+
COPY ./certs/private.key /etc/ssl/private/
12+
13+
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
14+
15+
CMD ["python", "main.py"]

docker/docker-compose.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
version: '3.9'
2+
services:
3+
app:
4+
build:
5+
context: ../
6+
dockerfile: docker/Dockerfile
7+
container_name: app
8+
restart: always
9+
ports:
10+
- 8000:8000
11+
networks:
12+
- default
13+
14+
nginx:
15+
image: nginx:latest
16+
container_name: nginx
17+
restart: always
18+
ports:
19+
- 80:80
20+
networks:
21+
- default
22+
volumes:
23+
- ./config/nginx.conf:/etc/nginx/nginx.conf
24+
25+
networks:
26+
default:
27+
driver: bridge
28+
29+
volumes:
30+
data:
31+
driver: local

main.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import uvicorn
2+
from decouple import config
3+
4+
if __name__ == "__main__":
5+
uvicorn.run("app.api:app", host=str(config("APP_HOST")), port=int(config("APP_PORT")), reload=True)
6+
# uvicorn.run("app.api:app", host=str(config("APP_HOST")), port=int(config("APP_PORT")), reload=True, ssl_certfile=config("SSL_CERTIFICATE"), ssl_keyfile=config("SSL_KEYFILE"))

0 commit comments

Comments
 (0)