1. fastapi homepage https://fastapi.tiangolo.com

최종 업데이트 : 2025-01-11

main.py

            
                
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import Dict
from hashlib import sha256
from http import HTTPStatus
import logging

logging_mode = "Y"

if logging_mode == "Y":
    logging.basicConfig(level=logging.DEBUG)
    logger = logging.getLogger(__name__)

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

users_db: Dict[str, str] = {}

class SignUpRequest(BaseModel):
    id: str
    password: str

class CustomExceptionResponse(Exception):
    def __init__(self, status_code: int, content: str):
        self.status_code = status_code
        self.content = content

@app.middleware("http")
async def log_request(request: Request, call_next):
    if logging_mode == "Y":
        logger.info(f"Request: {request.method} {request.url}")
    response = await call_next(request)
    
    if logging_mode == "Y":
        logger.info(f"Response: {response.status_code}")
    return response

@app.options("/{rest_of_path:path}")
async def preflight_handler():
    return {"message": "Preflight check passed"}

@app.exception_handler(CustomExceptionResponse)
def custom_exception_handler(request, exc: CustomExceptionResponse):
    return JSONResponse(
        content={"status_code": exc.status_code, "content": exc.content}
    )

@app.post('/api/signup')
def signup_request(data: SignUpRequest):
    id = data.id
    password = data.password

    if id in users_db:
        raise CustomExceptionResponse(
            status_code=HTTPStatus.CONFLICT.value,
            content="이미 사용 중인 ID입니다."
        )
    
    hashed_password = sha256(password.encode()).hexdigest()

    users_db[id] = hashed_password
    return {
        "status_code": HTTPStatus.CREATED.value,
        "content": "회원가입 성공"
    }

if __name__ == "__main__":
    import uvicorn
    uvicorn.run("main:app", host="127.0.0.1", port=8000)
  
            
        

작업순서

        
from fastapi import FastAPI
        
    

import을 이용하여 사용할 패키지를 선언합니다.

fastapi중 Fastapi만 사용해보겠습니다.

        
app = FastAPI()

@app.get("/")
def test():
    return "test"

if __name__ == "__main__":
    import uvicorn
    uvicorn.run("main:app", host="127.0.0.1", port=8000)
        
    

app이라는 변수에 FastAPI를 넣고 실행해봅니다.

서버가 잘 작동되는지 확인하고

스웨거 문서도 확인해봅니다.

http://127.0.0.1:8000/docs

http://127.0.0.1:8000/redoc

        
class SignUpRequest(BaseModel):
    id: str
    password: str
        
    

서버에서 받을 데이터를 정의해줍니다.

        
from pydantic import BaseModel
        
    

BaseModel을 사용하기 위해 선언이 필요합니다.

        
@app.post('/api/signup')
def signup_request(data: SignUpRequest):
    id = data.id
    password = data.password
    return "성공"
        
    

다시 실행하여 스웨거문서에서 테스트를 해봅니다.

        
            
from typing import Dict

users_db: Dict[str, str] = {}
  
        
    

중복을 오류확인을 위해 문자열을 키(key)와 값(value)으로 가지는 딕셔너리를 선언하고

        
if id in users_db:
    return "중복"

users_db[id] = password
return "성공"
        
    

중복가입확인이 잘되는지 테스트합니다.

        
from hashlib import sha256

hashed_password = sha256(password.encode()).hexdigest()

users_db[id] = hashed_password
        
    

패스워드 암호화를 위해 hashlib에서 sha256을 사용하기로 선언하고

암호화되어 잘 들어가는지 확인합니다.

        
            
from http import HTTPStatus

return {
    "status_code": HTTPStatus.CREATED.value,
    "content": "회원가입 성공"
}
  
        
    

status_code를 위해 http에서 HTTPStatus를 선언하고

return을 json형태로 변경하여 확인해봅니다.

        
class CustomExceptionResponse(Exception):
    def __init__(self, status_code: int, content: str):
        self.status_code = status_code
        self.content = content

raise CustomExceptionResponse(
    status_code=HTTPStatus.CONFLICT.value,
    content="이미 사용 중인 ID입니다."
)
        
    

예외처리를 위해 CustomExceptionResponse을 작성하고

실제 중복확인이 잘되는지 확인해봅니다.

        
            
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
import logging

logging_mode = "Y"

if logging_mode == "Y":
    logging.basicConfig(level=logging.DEBUG)
    logger = logging.getLogger(__name__)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


@app.middleware("http")
async def log_request(request: Request, call_next):
    if logging_mode == "Y":
        logger.info(f"Request: {request.method} {request.url}")
    response = await call_next(request)
    
    if logging_mode == "Y":
        logger.info(f"Response: {response.status_code}")
    return response

@app.options("/{rest_of_path:path}")
async def preflight_handler():
    return {"message": "Preflight check passed"}
  
        
    

fastapi에서 추가로 Request를 가져오고

미들웨어 사용에 필요한 패키지도 넣어줍니다

logging은 디버깅하면서 구경하실수있도록 추가했습니다.

add_middleware를 통해 cors설정을 다 허용해줍니다.

테스트환경시 url에 :8000 이런식으로 port가들어감으로

출처가 다른 프론트쪽에서 통신할수있도록 허용해주어야합니다.

실제 운영환경에서는 잘 셋팅해주셔야합니다.

middleware("http")에서 실제로 들어오는 요청을 확인할 수 있고

post api의 경우 요청시 preflight로 확인하는데

허용이 안되면 post통신을 하지못합니다.

options 요청에 응답을 보내줍니다.

이 구성을 기준으로 pynest, nestjs, java springboot를 구성했으니

설계하고 테스트하고 실행하는것을 하나씩 해보시고 본인것으로 만들면 좋겠습니다.

프론트는 백엔드가 하나라도 실행되어있어야 하며

별도설정하지 않도록 백엔드는 8000 port로 설정해놨습니다.

Related Pages

© 2024 Coding Stairs. All rights reserved.