From ef72429af4694ceb7b72a71008ac1e9d9e71b035 Mon Sep 17 00:00:00 2001 From: Manodeepray Date: Thu, 19 Jun 2025 19:12:48 +0530 Subject: [PATCH 1/3] update --- fastapi-twilio/.gitignore copy | 3 ++ fastapi-twilio/main.py | 90 +++++++++++++++++++++++---------- fastapi-twilio/requirements.txt | 2 + fastapi-twilio/run_test.sh | 5 ++ 4 files changed, 72 insertions(+), 28 deletions(-) create mode 100644 fastapi-twilio/.gitignore copy create mode 100644 fastapi-twilio/run_test.sh diff --git a/fastapi-twilio/.gitignore copy b/fastapi-twilio/.gitignore copy new file mode 100644 index 0000000..1021ac9 --- /dev/null +++ b/fastapi-twilio/.gitignore copy @@ -0,0 +1,3 @@ +./venv +./__pycache__ +.env \ No newline at end of file diff --git a/fastapi-twilio/main.py b/fastapi-twilio/main.py index 4cbb40c..4f31d16 100644 --- a/fastapi-twilio/main.py +++ b/fastapi-twilio/main.py @@ -1,45 +1,79 @@ -from fastapi import FastAPI -import requests -from dotenv import load_dotenv -from pydantic import BaseModel +from fastapi import FastAPI, Form, Response +from contextlib import asynccontextmanager +import logging import os -import asyncio +import httpx +from dotenv import load_dotenv +from pydantic import BaseModel, Field +from twilio.twiml.messaging_response import MessagingResponse +from fastapi.responses import JSONResponse -# Load environment variables from a .env file load_dotenv() +# Setup logging +logging.basicConfig(level=logging.INFO) + + +# Pydantic model for request validation class Message(BaseModel): - Body: str - To: str + Body: str = Field(..., min_length=1, max_length=160) + To: str = Field(..., pattern=r"^\+\d{10,15}$") + + + + + +# Lifespan handler (replaces @app.on_event("startup")) +@asynccontextmanager +async def lifespan(app: FastAPI): + logging.info("Starting FastAPI app...") + yield + logging.info("Shutting down gracefully...") -app = FastAPI() -@app.post('/send-sms/') -def send_sms(data: Message): + +app = FastAPI(lifespan=lifespan) + + + + +@app.post("/send-sms/") +async def send_sms(data: Message): + twilio_account_sid = os.getenv('TWILIO_ACCOUNT_SID') twilio_auth_token = os.getenv('TWILIO_AUTH_TOKEN') twilio_phone_number = os.getenv('TWILIO_NUMBER') - url = f'https://api.twilio.com/2010-04-01/Accounts/{twilio_account_sid}/Messages.json' + if not all([twilio_account_sid, twilio_auth_token, twilio_phone_number]): + logging.error("Missing Twilio environment variables.") + return JSONResponse(status_code=500, content={"message": "Twilio credentials are not set properly."}) + url = f"https://api.twilio.com/2010-04-01/Accounts/{twilio_account_sid}/Messages.json" payload = { 'Body': data.Body, 'From': twilio_phone_number, 'To': data.To } - - try: - response = requests.post(url=url, data=payload, auth=(twilio_account_sid, twilio_auth_token)) - if response.status_code == 201: - return {"message": "SMS sent successfully!"} - else: - return {"message": "Failed to send SMS. Please check the provided phone number."} - except Exception as e: - return {"message": str(e)} - -# Graceful shutdown -@app.on_event("shutdown") -async def shutdown_event(): - print("Shutting down gracefully...") - # Perform any additional cleanup here if needed - # For example, closing database connections or other resources \ No newline at end of file + + async with httpx.AsyncClient() as client: + try: + response = await client.post( + url=url, + data=payload, + auth=(twilio_account_sid, twilio_auth_token) + ) + if response.status_code in [200, 201]: + return {"message": "SMS sent successfully!"} + else: + logging.error(f"Twilio error: {response.status_code} - {response.text}") + return JSONResponse(status_code=response.status_code, content={ + "message": "Failed to send SMS", + "details": response.text + }) + except httpx.RequestError as e: + logging.error(f"HTTPX error: {e}") + return JSONResponse(status_code=500, content={"message": f"An error occurred: {str(e)}"}) + +@app.get("/") +async def health_check(): + return {"status": "ok"} diff --git a/fastapi-twilio/requirements.txt b/fastapi-twilio/requirements.txt index 7a9ca73..33a05ba 100644 --- a/fastapi-twilio/requirements.txt +++ b/fastapi-twilio/requirements.txt @@ -51,3 +51,5 @@ PyYAML==6.0 rich==13.3.1 six==1.16.0 ssh-import-id==5.10 +httpx +pydantic \ No newline at end of file diff --git a/fastapi-twilio/run_test.sh b/fastapi-twilio/run_test.sh new file mode 100644 index 0000000..4ff5a89 --- /dev/null +++ b/fastapi-twilio/run_test.sh @@ -0,0 +1,5 @@ +#!bin/bash + +curl -X POST "http://localhost:8000/send-sms/" \ + -H 'Content-Type: application/json' \ + -d '{"Body": "Keploy test!", "To": "+919999999999"}' \ No newline at end of file From 516b7dd04af7d2f3967ec8260db33ab30d34552d Mon Sep 17 00:00:00 2001 From: Manodeepray Date: Thu, 19 Jun 2025 19:14:56 +0530 Subject: [PATCH 2/3] changes to main.py and readme --- fastapi-twilio/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fastapi-twilio/README.md b/fastapi-twilio/README.md index d1d5ca9..d990d71 100644 --- a/fastapi-twilio/README.md +++ b/fastapi-twilio/README.md @@ -38,9 +38,9 @@ Make API Calls using Hoppscotch, Postman or cURL command. Keploy with capture th 1. Replace the place holder below i.e. `YOUR_REGISTERED_PERSONAL_PHONE_NUMBER` with your registered personal phone number that you linked with Twilio. ```bash -curl --location 'http://127.0.0.1:8000/send-sms/' \ - --header 'Content-Type: application/json' \ - --data-raw '{ +curl -X 'http://127.0.0.1:8000/send-sms/' \ + -H 'Content-Type: application/json' \ + -d '{ "Body": "Test", "To": "" }' @@ -49,9 +49,9 @@ curl --location 'http://127.0.0.1:8000/send-sms/' \ 2. Replace the place holder below i.e. `SOME_WRONG_PHONE_NUMBER` with any wrong phone number and make the request. ```bash -curl --location 'http://127.0.0.1:8000/send-sms/' \ - --header 'Content-Type: application/json' \ - --data-raw '{ +curl -X 'http://127.0.0.1:8000/send-sms/' \ + -H 'Content-Type: application/json' \ + -d '{ "Body": "Test, testtt, testttttttssss :)", "To": "", }' From 163d74cd0f00787d29b67159dd725defb80edda8 Mon Sep 17 00:00:00 2001 From: Manodeepray Date: Thu, 19 Jun 2025 19:15:28 +0530 Subject: [PATCH 3/3] changes to main.py and readme --- fastapi-twilio/.gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fastapi-twilio/.gitignore b/fastapi-twilio/.gitignore index bdd515a..1021ac9 100644 --- a/fastapi-twilio/.gitignore +++ b/fastapi-twilio/.gitignore @@ -1,2 +1,3 @@ ./venv -./__pycache__ \ No newline at end of file +./__pycache__ +.env \ No newline at end of file