Back-End/Fastapi

9. Middleware (CORS and Custom Logging)

sd4beatles 2024. 10. 27. 03:55

1. Introduction

이번 장에선 CORS와 Custom Loggin에 관해서 간략하게 알아보겠습니다. 그리 어렵지 않은 개념인데, 유튜브의 강의로 인해서 오히려 더 개념이 안잡혀서, 공식문서를 기반으로 정리를 해보았습니다.

2. CORS

👇 더 자세한 정보는 아래의 공식문서를 참고 하세요.

CORS는 Cross Origin Resource Sharing의 약어로, 한 도메인의 웹페이지가 다른 Domain의 resource를 요청 및 상호 작용하는 방식을 제어하기 위한 웹 브라우저에 구현된 "보안"기능입니다. 다시 말해, 한 출처(Origin)이 실행중인 웹 어플리케이션이 다른 출처의 자원에 접근을 제어 및 허용할 수 있는 권한을 부여하도록 브라우저에게 알려주는 것 입니다.

출처:https://developer.mozilla.org/en-us/docs/HTTP/CORPS

위 그림에서 Web Document의 origin은 "domain-a.com"입니다. 이때, 두 개의 web-sever가 현재 운영중인데, Web Document와 동일한 origin(출처)을 갖는 Web Server와의 request를 Same-Origin Request라 합니다.이와 반대로, 출처가 다른 Web-Server의 requst는 Cross-Origin Request라 합니다.

그림을 통해서 대략적으로 "Same-Origin" 과 "Cross-Origin"의 차이는 알 수 있었습니다. 이때, 우리는 origin이라는 정의를 좀 더 자세하게 살펴볼 필요가 있습니다.

2.1 What is Origin?

여기서 말하는 Origin이란 무엇일까요? Origin은 protocol(Http,Https) 와 dmain(goole.com,naver.com 등) 및 port의 조합을 칭합니다.

여기서 헷갈리지 말아야 하는 점은, 세 개중에 하나라도 틀린, 두 개의 도메인은 같은 origin이라고 말할 수 없다는 점입니다.

예를 들어보면, 아래의 예시는 '놀랍게도' 서로 다른 origin입니다.

즉 CORS는 이러한 Cross Origin을 지원해주는 일종의 안전 장치라고 보시면 됩니다.

2.2 FAST API Example

root endpoin에 아래와 같이 접속하면, "{"message":"Hello,world"}"이 웹브라우저에게 보일 수 있게 파이썬 코드를 작성해보겠습니다.

@app.get("/")
def root():
  return {"message":"Hello,world"}

우리가 server-test용으로 쓰는 프로그램(postman 등)에선 아래와 같이 정상적으로 작동하는 것을 알 수 있습니다.

그러나, google chrome의 개발자 도구에서 아래와 같이 request를 보내면, 아래와 같이 "failed to fetch" 라는 오류 문구를 발견할 수 있습니다. 이는, 위의 origin을 안다면, 아주 쉽게 오류를 발견할 수 있습니다.

Fast API는 server가 작동하는 domain만 request를 받을 수 있도록 지정되어있습니다. 즉, 우리가 현재 google console에서 보내는 request는 domain( 'google.com'으로 접속)과 server의 domain는 서로 다르기 때문에, fastapi는 보안상 우리의 접근을 막고 있었던 것이였습니다.

만약 아래와 같이 코드를 추가적으로 작성해준다면, 바로 requst를 수용해주고 원하는response를 받을 수 있습니다.

  origins=[
    "https://www.google.com",
  ]

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

추가적으로, 만약 app/web application을 배포시에, "GET/POST"만 허용하게 끔 할 수 있습니다. DELETE를 원천적으로 배제하고 싶다면, 아래의 "allow_method"에다가 명시를 해주면 됩니다.

  origins=[
    "https://www.google.com",
  ]

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

3. Custom Logging

대형학원에서 근무할 때, 백엔드 개발자 분들이 계속 logging을 커스텀해서 적재하는 것을 본적이 있습니다. 훗날, 이 loggin 정보가 데이터분석가분들에게 전달되어서, 마케팅이나 고객들의 행동패턴 분석에 도움이 되는 것을 알 수 있었습니다. 이러한 customizing된 logging을 전달할 수 있는 하나의 방법이 FASTAPI에선 @app.middleware를 통해서 가능합니다.

우리가 만약 "processing_time/requset_mdethod/url_path" 정보를 출력하고 싶다면, 아래와 같이 코드를 작성하면 됩니다.


 @app.middleware("http")
  async def custom_loggin(request:Request,call_next):
    start_time=time.time()
    print("before",start_time)

    response=await call_next(request)
    processing_time=time.time()-start_time
    message=f"{request.method}-{request.url.path}-completed after {processing_time}"
    print(message)
    return response