最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

mongodb - My FastAPI wont connect to my database when deploying with Render - Stack Overflow

programmeradmin0浏览0评论

I've tried to deploy my FastAPI code using Render, but I get errors when I try to send a POST request, stating that the database failed to connect. I have executed my FastAPI code using the terminal, and it connects to the database fine when I send a POST request. This is my first time using Render, so I am unfamiliar with how it works. I am currently using this as my start command: uvicorn main:app --reload --host 0.0.0.0 --port $PORT

Here is the code:

from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel, EmailStr, Field
from fastapi.security import OAuth2PasswordRequestForm, OAuth2PasswordBearer
from fastapi.middleware.cors import CORSMiddleware
from motor.motor_asyncio import AsyncIOMotorClient
from passlib.context import CryptContext
from jose import JWTError, jwt
from datetime import datetime, timedelta, timezone


class User(BaseModel):
    name: str = Field(..., min_length=1) # requires name length of at least 1
    email: EmailStr
    password: str

class Login(BaseModel):
   email: EmailStr
   password: str

class Token(BaseModel):
   access_token: str
   token_type: str

class TokenData(BaseModel):
   email: EmailStr

# password hashing setup
pwd_cxt = CryptContext(schemes = ["bcrypt"], deprecated = "auto")

# hashing functions
class Hash():
    @staticmethod
    # Accepts password(str) and returns hashed password(str)
    def bcrypt(password:str) -> str:
        return pwd_cxt.hash(password)
    
    @staticmethod
    # Accepts plaintext password, hashed password, and returns bool for verification
    def verify(hashed: str, plain: str) -> bool:
        return pwd_cxt.verify(plain, hashed)
    
# token setup
SECRET_KEY = "secret key" 
ALGORITHM = "numbers"
ACCESS_TOKEN_EXPIRE_MINUTES = 30 

# Ceate JWT token
def create_access_token(data: dict, expires_delta: timedelta = None):
    to_encode = data.copy() # copy input data
    if expires_delta: # set expiration time
        expire = datetime.now(timezone.utc) + expires_delta
    else:
        expire = datetime.now(timezone.utc) + timedelta(minutes = ACCESS_TOKEN_EXPIRE_MINUTES)
        to_encode.update({"exp": expire}) # update expiration time 
        return jwt.encode(to_encode, SECRET_KEY, algorithm = ALGORITHM) # encode token


def verify_token(token:str,credentials_exception: HTTPException):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        email: EmailStr = payload.get("sub")
        if email is None: # exception if no username
            raise credentials_exception
        return TokenData(email=email) # return TokenData instance
    except JWTError: # exception if token invalid/expired
        raise credentials_exception

# Users post credentials to the /login endpoint to obtain access token
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")

#checks if token is valid to return user 
async def get_current_user(token: str = Depends(oauth2_scheme)) -> TokenData:
    credentials_exception = HTTPException(
        status_code=401,
        detail= "Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"}
    )
    return verify_token(token, credentials_exception)


app = FastAPI()

origins = [
    "http://localhost:3000",
    "http://localhost:8000"
]

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

# MongoDB Connection
mongodb_uri = '<my_mongoDB_uri>'
client = AsyncIOMotorClient(mongodb_uri)
database = client["Cluster"]
users = database["Collection"]


@app.post('/register')
async def create_user(request: User):
    # check if email already in use
    existing_user = await users.find_one({"email": request.email})
    if existing_user:
        raise HTTPException(status_code=400, detail="Email already registered")

    # hash the password
    hashed_pass = Hash.bcrypt(request.password)

    # create User object
    user_object = dict(request)
    user_object["password"] = hashed_pass

    # Insert the new user into the database
    result = await users.insert_one(user_object)
    if result.inserted_id:
        return {"res": "created"}
    else:
        raise HTTPException(status_code=500, detail="User registration failed")

@app.post('/login')
async def login(request: OAuth2PasswordRequestForm = Depends()):
    # find user with given email
    user = await users.find_one({"email": request.username})
    if not user:
        raise HTTPException(status_code=404, detail="No user found with this email")

    # checks given password is correct
    if not Hash.verify(user["password"], request.password):
        raise HTTPException(status_code=403, detail="Incorrect email or password")
    # creates access token
    access_token = create_access_token(data={"sub": user["email"]})
    
    return {"access_token": access_token, "token_type": "bearer"}

this is my error:

pymongo.errors.ServerSelectionTimeoutError: localhost:27017: [Errno 111] Connection refused (configured timeouts: socketTimeoutMS: 20000.0ms, connectTimeoutMS: 20000.0ms), Timeout: 30s, Topology Description: <TopologyDescription id: 673d3b500f19ce930ab7ddcf, topology_type: Unknown, servers: [<ServerDescription ('localhost', 27017) server_type: Unknown, rtt: None, error=AutoReconnect('localhost:27017: [Errno 111] Connection refused (configured timeouts: socketTimeoutMS: 20000.0ms, connectTimeoutMS: 20000.0ms)')>]>

I've tried changing the start command and it resulted in the same thing.

发布评论

评论列表(0)

  1. 暂无评论