چگونه یک API در پایتون ایجاد کنیم
API یک واسط برنامهنویسی کاربردی یا API که به مخفف “application programming interface” معروف است، ارتباط بین دو سیستم کامپیوتری را تسهیل میکند. بیایید یک برنامه هواشناسی موبایل را در نظر بگیریم که به کاربران به روز رسانیهای هواشناسی در زمان واقعی را ارائه میدهد. این برنامه دادههای هواشناسی خود را ندارد، بلکه برای اطلاعات دقیق و بهروز خود از منابع خارجی استفاده میکند.
وقتی کاربر برنامه را باز کرده و درخواست هوای فعلی مکان خود را میدهد، برنامه با استفاده از یک API با یک سرویس هواشناسی از راه دور ارتباط برقرار میکند. این API ممکن است توسط یک سازمان هواشناسی یا یک شرکت داده هوا ارائه شود. برنامه یک درخواست را از طریق API ارسال میکند و مکان کاربر را مشخص میکند. سرویس هواشناسی سپس با دادههایی مانند دما، رطوبت، سرعت باد و اطلاعات پیشبینی پاسخ میدهد.
این دادهها به تلفن کاربر ارسال میشود، جایی که برنامه آن را پردازش کرده و در یک قالب آسان برای مشاهده نمایش میدهد. تمام این اتفاقات به طور بیدرنگ در پسزمینه رخ میدهد و API به عنوان پلی بین برنامه هواشناسی و سرویس هواشناسی خارجی عمل میکند.
API چیست؟
یک API مخفف “application programming interface” یا واسط برنامهنویسی کاربردی است که ارتباط بین دو سیستم کامپیوتری را تسهیل میکند.
آغاز کار
برای ایجاد یک API در زبان برنامهنویسی پایتون روشهای مختلفی وجود دارد. اما امروزه به شما یک روش ساده که برای مبتدیان عالی است را نشان میدهم. ما از FastAPI استفاده خواهیم کرد.
FastAPI چیست؟
FastAPI یک چارچوب وب پایتون با عملکرد بالا است که توسط Sebastián Ramírez در سال 2018 توسعه یافته و به دلیل سرعت و کارایی خود شناخته شده است. این چارچوب از پایتون 3.8+ استفاده میکند تا اعتبارسنجی دادهها و تولید مستندات را به صورت خودکار ارائه دهد. FastAPI با ارائه پشتیبانی OAuth2 و JWT داخلی و سینتکس سادهاش به همراه مستندات تعاملی خودکار، انتخاب مناسبی برای توسعه API قوی است.
پیشنیازها
- نصب Python 3.6+.
- نصب کتابخانه FastAPI با دستور
pip install fastapi
- نصب کتابخانه Uvicorn با دستور
pip install uvicorn[standard]
پس از نصب بستههای لازم، مرحله بعدی ما ایجاد یک فایل پایتون مخصوص به تعریف API خود است. این فایل پایهای برای ایجاد یک برنامه است که شامل APIهای ما، همراه با نقاط پایانی، پارامترها و سایر جزئیات مربوطه، میشود.
در این برنامه، ما عناصر اساسی مورد نیاز توسط API را مشخص خواهیم کرد، از جمله نقطه پایانی، متد HTTP، آرگومانهای ورودی مورد نیاز و عملکردی که API در پسزمینه انجام میدهد.
بیایید به این کد را خط به خط بررسی کنیم:
from fastapi import FastAPI
در این خط، کلاس FastAPI از ماژول fastapi وارد میشود. FastAPI یک چارچوب وب است که ایجاد APIها را ساده میکند و اطمینان میدهد که آنها با استانداردهای OpenAPI برای REST APIها هماهنگ هستند.
app = FastAPI()
در اینجا، یک نمونه از کلاس FastAPI ایجاد شده و به متغیر app اختصاص داده شده است. این نمونه هسته برنامه وب شماست که درخواستهای ورودی را مدیریت کرده و آنها را به توابع نقاط پایانی مناسب مسیردهی میکند.
@app.get("/get-message")
این خط یک decorators مسیر است که به FastAPI میگوید که یک نقطه پایانی برای درخواستهای HTTP GET در مسیر URL /get-message ایجاد کند.
قسمت @app.get مشخص میکند که این نقطه پایانی به درخواستهای HTTP GET پاسخ خواهد داد. FastAPI همچنین از طریق decorators مشابه، مانند POST، PUT و DELETE، از متدهای HTTP دیگر پشتیبانی میکند.
مسیر “/get-message” محل قابل دسترسی این نقطه پایانی است. به عنوان مثال، اگر سرور شما روی localhost و پورت 8000 در حال اجرا باشد، این نقطه پایانی را از طریق http://localhost:8000/get-message قابل دسترسی خواهید داشت.
async def read_root()
این خط یک تابع ناهمزمان به نام read_root تعریف میکند. کلمه کلیدی async نشان میدهد که تابع یک تابع ناهمزمان است که میتواند عملیات ناهمزمان را انجام دهد و با عملیات ورودی-خروجی ناهمزمان خوب کار میکند. FastAPI برای پشتیبانی از کد ناهمزمان ساخته شده است، که این امر باعث بهینهسازی عملیات محدود به ورودی-خروجی میشود.
این تابع به نقطه پایانی /get-message ارتباط دارد. هر زمان که یک درخواست GET به این نقطه پایانی ارسال میشود، FastAPI این تابع را اجرا میکند.
return {"Message": "Congrats! This is your first API!"}
تابع read_root یک دیکشنری پایتونی را برمیگرداند: {“Message”: “Congrats! This is your first API!”}.حالا برنامه را به این شکل اجرا میکنیم uvicorn fapi:app –reload توجه کنید که اسم فایل برنامه من fapi.py هست به عنوان مثال، فرض کنید که فایل شما به نام “main.py” و متغیر برنامه “app” باشد. در این صورت، دستور اجرایی به شکل زیر خواهد بود:
uvicorn main:app --reload
در زمینه FastAPI، دیکشنری برگرداندهشده به طور خودکار به یک پاسخ JSON تبدیل میشود. بنابراین، هنگامی که یک مشتری (مانند مرورگر وب یا ابزاری مانند curl یا Postman) یک درخواست GET به نقطه پایانی /get-message میفرستد، یک پاسخ JSON شامل پیام “Congrats! This is your first API!” دریافت خواهد کرد.
انتقال پارامتر
API ما میتواند آرگومانها را در توابع خود قبول کند. اما مهم است که نوع هر آرگومان (مانند عدد یا متن) را هنگام ارسال آنها مشخص کنیم. این نوع مشخصه یک ویژگی کلیدی است.
توجه: FastAPI تاکید میکند که انواع دادههای دریافتی در تماس API با انواع تعریف شده همخوانی داشته باشند. این اعتبارسنجی برای عملکرد صحیح API بسیار حیاتی است. این یک ویژگی اساسی است که FastAPI را از چارچوبهای دیگر API مانند Flask که این نوع اعتبارسنجی را در خود ندارند، متمایز میکند.
بیایید این مفهوم را از طریق یک مثال بررسی کنیم:
ما کد خودمان را به شکل زیر تغییر می دهیم تا وقتی پارامتر name را کاربر ارسال کرد داخل پیام ما هم نمایش داده شود.
from fastapi import FastAPI app = FastAPI() @app.get("/get-message") def hello(name: str): return {"Message": "Congrats " + name + '! This is your first API!'}
حال که API خود را تغییر دادهایم تا یک پارامتر نام را نیاز داشته باشد، این پارامتر باید حتما در درخواستها وجود داشته باشد.
قبلاً، فقط مراجعه به http://127.0.0.1:8000/get-message کافی بود. اما با تغییر جدید وقتی پارامتر نام اضافه شده است، آدرس درخواست باید این الزامات جدید را دربرگیرد.
به عنوان مثال، برای استفاده از پارامتر ‘Saeed’، آدرس URL باید به این صورت باشد: http://127.0.0.1:8000/get-message?name=Saeed
خروجی چیزی شبیه به متن JSON زیر خواهد بود:
{"Message":"Congrats Saeed! This is your first API!"}
ایجاد نقاط پایانی POST، PUT و DELETE
فرض کنید یک رشته استاتیک وجود دارد و میخواهیم نقاط پایانی API را ایجاد کنیم تا متنی به این رشته اضافه کنیم (POST)، تمام رشته را تغییر دهیم (PUT) و رشته را حذف کنیم (DELETE). ما از پایگاه داده یا ساختارهای داده پیچیده استفاده نخواهیم کرد – فقط یک متغیر رشته ساده.
پس کد خودمان را به صورت زیر بروز میکنیم:
# Initial static string static_string = "Initial Text" @app.post("/add") async def add_text(text: str): global static_string static_string += text return {"message": "Text added", "current_string": static_string} @app.put("/change") async def change_text(new_text: str): global static_string static_string = new_text return {"message": "Text changed", "current_string": static_string} @app.delete("/remove") async def remove_text(): global static_string static_string = "" return {"message": "Text removed"}
- نقطه پایانی
/get-message
:- این نقطه پایانی یک درخواست GET را پشتیبانی میکند و یک پارامتر
name
را به عنوان ورودی دریافت میکند. - با دریافت این پارامتر، یک پیام تبریک با استفاده از این پارامتر و متن ثابت “This is your first API!” تشکیل میشود و به عنوان یک JSON بازگردانده میشود.
- این نقطه پایانی یک درخواست GET را پشتیبانی میکند و یک پارامتر
- متغیر استاتیک اولیه:
- یک متغیر به نام
static_string
با مقدار “Initial Text” ایجاد میشود. این متغیر برای نگهداری متن استفاده میشود که توسط نقاط پایانی بعدی تغییر داده میشود.
- یک متغیر به نام
- نقاط پایانی
/add
:- این نقطه پایانی یک درخواست POST را پشتیبانی میکند و یک پارامتر
text
را به عنوان ورودی دریافت میکند. - متن دریافتی به متن استاتیک اضافه میشود و پیامی با اطلاعات مربوط به عملیات اضافه شدن متن به همراه متن فعلی رشته استاتیک به عنوان یک JSON بازگردانده میشود.
- این نقطه پایانی یک درخواست POST را پشتیبانی میکند و یک پارامتر
- نقاط پایانی
/change
:- این نقطه پایانی یک درخواست PUT را پشتیبانی میکند و یک پارامتر
new_text
را به عنوان ورودی دریافت میکند. - متن استاتیک را با متن جدید جایگزین میکند و پیامی با اطلاعات مربوط به عملیات تغییر متن به همراه متن فعلی رشته استاتیک به عنوان یک JSON بازگردانده میشود.
- این نقطه پایانی یک درخواست PUT را پشتیبانی میکند و یک پارامتر
- نقاط پایانی
/remove
:- این نقطه پایانی یک درخواست DELETE را پشتیبانی میکند و هیچ ورودی اضافی نمیپذیرد.
- متن استاتیک را با خالی کردن رشته جایگزین میکند و پیامی با اطلاعات مربوط به عملیات حذف متن به عنوان یک JSON بازگردانده میشود.
این مثال عملیات اولیه با یک رشته تکی با استفاده از متدهای مختلف HTTP را در FastAPI نشان میدهد. در یک سناریوی واقعی، شما به طور معمول با دادههای پیچیدهتر مدیریت میکنید و شامل اعتبارسنجی خطا، اعتبارسنجی و احتمالاً تعامل با یک پایگاه داده یا سیستم ذخیرهسازی دیگر میشوید.
مستندات اتوماتیک API با FastAPI
یکی از ویژگیهای برجسته FastAPI ایجاد مستندات اتوماتیک برای API شماست. با استفاده از این ویژگی، FastAPI به صورت خودکار مستندات API شما را ایجاد میکند، از جمله جزئیاتی مانند نقاط پایانی، پارامترها، نوعهای داده، و توضیحاتی که در کد شما قرار دادهاید.
چرا مستندات مهم هستند؟
مستندات API نقش بسیار مهمی در فهم و استفاده از یک API دارند. این مستندات به توسعهدهندگان کمک میکنند تا با عملکرد API آشنا شوند و از آن به درستی استفاده کنند، بدون اینکه نیاز به مطالعه کدها یا پرسوجوی اطلاعات در مستندات غیر رسمی باشد. به علاوه، مستندات API باعث میشوند تا فرآیند توسعه، تست و ادغام API سریعتر و موثرتر انجام شود.
استفاده از مستندات اتوماتیک با FastAPI
با FastAPI، شما نیازی به نوشتن مستندات جداگانه برای API خود ندارید. به جای آن، FastAPI مستندات را برای شما ایجاد میکند، بر اساس کدهایی که شما نوشتهاید. برای دسترسی به مستندات اتوماتیک، کافی است به آدرس http://127.0.0.1:8000/docs
در مرورگر خود مراجعه کنید (با فرض اجرای سرور FastAPI در localhost و پورت 8000).
با باز شدن این صفحه، شما یک رابط کاربری تعاملی برای مشاهده مستندات API خود خواهید دید. این صفحه شامل اطلاعاتی در مورد هر نقطه پایانی، پارامترها، نوعهای داده، و توضیحات مربوط به آنها است. همچنین شما میتوانید با استفاده از این رابط کاربری تعاملی، درخواستهایی به API خود ارسال کرده و پاسخها را مشاهده کنید.
تست API با Postman
چند روش برای تست API ما وجود دارد، اما مورد مورد علاقه من استفاده از Postman و یا پلاگین Talend API Tester است. یکی از دلایلی که من Postman را ترجیح میدهم این است که بسیار کارآمد است. همچنین به من اطلاعات بسیاری در مورد خود API، اجرا، زمانی که برای بازگشت یک پاسخ طول میکشد، هدرهای درخواست و پاسخ، کوکیها و سایر تنظیمات را میدهد.