2024-08-20 TUE
ch10_Authentication
sha256(id + pw + ip + secret_key) => 암호화authentication.py
from fastapi import FastAPI, Request
from starlette.middleware.sessions import SessionMiddleware
app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key="fastapi_secret_key")
# add_middleware를 통해 middleware 추가
# secret_key : 최소 200이상, 환경변수에서 저장, key를 관리하는 서비스, 반복적 수정
@app.post("/set")
async def set_session(request: Request):
# 그냥 관습적인 비동기처리 async 안써도 지원은 됨.
request.session['username'] = 'ham'
return {"message" : "Session value(id) set"}
@app.get("/get")
async def get_session(request: Request):
username = request.session.get("username", "Guest")
return {"username":username}
app.add_middleware(SessionMiddleware, secret_key="fastapi_secret_key") : add_middleware를 통해 middleware 추가-m uvicorn authentication:app --reload 실행 하면??


login.py, request.py
#login.py
from fastapi import FastAPI, Request, HTTPException, Form
from starlette.middleware.sessions import SessionMiddleware
from pydantic import BaseModel
app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key="fastapi_secret_key")
class Item(BaseModel):
username: str
password: str
@app.post("/login")
async def login(request: Request, user: Item):
if user.username == 'ham' and user.password == '1234':
request.session['username'] = user.username
return {"message" : "Login success"}
else:
raise HTTPException(status_code=401, detail="Login failed")
@app.get("/dashboard/")
async def dashboard(request: Request):
username = request.session.get("username")
if not username: # if username is None
raise HTTPException(status_code=401, detail="Unauthenticated")
return {"message":f"welcome to the dashboard, {username}"}
#request.py
import requests
url = "http://localhost:8000/login"
data = {
"username": "ham",
"password": "1234"
}
res = requests.post(url, json=data)
print(res)
print(res.text)
터미널에서 실행하면 python request.py

나는 되는데 강사님 cmd 안쳐서 그런거 같은뎅...
하지만 말 할 용기가 없다
✏ 참고
curl -X POST http://localhost:8000/set이런식으로 터미널에 입력해야 볼 수 있음.ch11_middleware
# main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:5000"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
def read_root():
return {"message" : "Hello, root ham!"}
@app.get("/hello")
def hello():
return {"message" : "Hello, hello ham!"}
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CORS 테스트</title>
<!-- 아래에서 호출 할 함수 makeRequest()를 비동기 식으로 정의 해줌-->
<script type = 'text/javascript'>
async function makeRequest(){
try{
const response = await fetch('http://localhost:8000/hello',
{
method : "GET",
credentials : 'include'
});
// fetch: 자바의 request와 비슷한 역할
if(!response.ok){
throw new Error('서버 상태 오류!!');
}
const data = await response.json()
<!-- api 요청에 대한 응답 받아서 json형식으로 변환후 data에 저장 -->
console.log(data);
document.getElementById('result').innerHTML = JSON.stringify(data);}
<!-- data 변수에 저장된 json 데이터를 html 요소의 innerhtml 속성에 출력-->
catch(error){
console.error('error: ', error);
document.getElementById('result').innerHTML = '!!에러 발생!!';
}
}
</script>
</head>
<body>
<h1> cors 테스트 페이지</h1>
<button onclick="makeRequest()">서버에 요청하기</button> <!--- 자바스크립트로 서버에 요청을 보내는 버튼-->
<div id = "result"></div>
</body>
</html>
<!-- cmd : python -m http.server 5000 -->



python -m http.server 5000으로 실행
안되는데염.....
ch12_fileupload
pip install python-multipart==0.0.9
파일 전송 시, 잘게 잘라서 나누어서 전송하게 하는 패키지

설치 완

이런 기능을 제공한다고 합니다.
코드
from fastapi import FastAPI, File, UploadFile
import shutil # 파일 관리하는 모듈
from pathlib import Path
app = FastAPI()
@app.post("/uploadfile/") # 파일을 올려야 하니까 post 방식으로
async def create_upload_file(file: UploadFile = File(...)): #(...) : 필수 매개변수 라는 뜻. 파일 반드시 올려야 에러 안남.
folder_name = "file_uploaded"
Path(folder_name).mkdir(exist_ok=True)
file_location = f"{folder_name}/{file.filename}"
file.file.seek(0) #파일의 첫부분을 시작 위치로 설정. (0)에 시작 위치 넣어주면 됨.(= 파일 초기화)
with open(file_location, "wb+") as file_object: # wb+(write binary +) : 파일이 없으면 생성(쓰기모드)
shutil.copyfileobj(file.file, file_object)
return {'uploaded filename' : file.filename}
🍀Clova says🍀

요약하면 w는 쓰기만 w+는 쓰기 읽기 둘다
b는 바이너리 모드
텍스트 모드와 다르게 줄바꿈문자를 따로 처리 하지 않음
텍스트 파일인 경우는 'b' 빼고 text 모드로 설정해도 됨.
python -m uvicorn main:app --reload실행

docs 페이지에서 바로 테스트도 가능

파일 선택 후 execute!

이렇게 내가 그린그림이 올라갑니다~!
ch13_Async
# main.py
from fastapi import FastAPI
import asyncio
app = FastAPI()
async def fetch_data():
await asyncio.sleep(2)
return {"data": "some_data"}
# async와 await를 사용하여 비동기 처리
@app.get("/")
async def read_root():
data = await fetch_data()
return {"message": "Hello Ham", "fetch_data": data}
- 함수를 비동기 처리하기 위해 async 써줌
- 함수 내에서 비동기 처리할 부분에 await 써줌

# main1.py
import asyncio
async def func1():
print("func1 : Start")
await asyncio.sleep(3) #asyncio는 비동기 처리 class
print("func1 end")
return {"data": "some_data"}
async def func2():
print("func2 : Start")
await asyncio.sleep(1) #asyncio는 비동기 처리 class
print("func2 end")
return {"data": "some_data"}
#비동기 처리 class를 한번에 실행시키는 함수 gather
async def main():
await asyncio.gather(func1(), func2())
if __name__ == "__main__":
asyncio.run(main())
asyncio.gather() : 여러 비동기함수를 한번에 실행
asyncio.run(main()) : 비동기 함수 실행시키는 명령
실행은 python main1.py 왜? fastapi 아니니까~!~!

실행시켜 보면 func1은 시작하고 3초 걸리고 func2는 1초 이기 때문에 순서는 아래처럼!
func1 시작 -> func2시작 -> func2 1초 걸림 -> func2 끝 -> func1도 3초 후에 끝
이것이 비동기처리다!
# main2.py
import asyncio
from fastapi import FastAPI
from time import sleep, time
import requests
import asyncio
import aiohttp
app = FastAPI()
default_url = "https://nate.com"
# 동기방식
@app.get("/sync/{times}")
def sync_call(times: int, url: str=default_url):
start_time = time()
sleep(1)
for _ in range(times):
requests.get(url)
elapsed_time_sync = time()
return {"elasped_time_sync": round(elapsed_time_sync, 3)}
# 비동기식
@app.get("/async/{times}")
async def async_call(times: int, url: str= default_url):
start_time = time()
async with aiohttp.ClientSession() as session: #비동기 세션 생성
tasks = []
for _ in range(times):
task = session.get(url)
tasks.append(task)
await asyncio.gather(*tasks)
elapsed_time_async = time() - start_time
return ['elapsed_time_async', round(elapsed_time_async, 3)]
aiohttp.ClientSession() : 비동기 세션 생성
실행결과

