آموزش گام به گام استفاده از یک API محبوب (مثال عملی)

فهرست مطالب

آموزش گام به گام استفاده از یک API محبوب: گیت‌هاب (مثال عملی پیشرفته)

در دنیای مدرن توسعه نرم‌افزار، رابط‌های برنامه‌نویسی کاربردی یا همان API (Application Programming Interface) نقش حیاتی را ایفا می‌کنند. APIها دروازه‌هایی هستند که به نرم‌افزارهای مختلف اجازه می‌دهند با یکدیگر ارتباط برقرار کرده و داده‌ها را به اشتراک بگذارند. این قابلیت، پایه‌های اصلی وب مدرن و اپلیکیشن‌های موبایل را تشکیل می‌دهد و امکان ایجاد اکوسیستم‌های پیچیده و قابلیت‌های نوآورانه را فراهم می‌آورد. از یک سو، APIها به توسعه‌دهندگان این امکان را می‌دهند که بدون نیاز به دانستن جزئیات پیاده‌سازی داخلی یک سرویس، از قابلیت‌های آن بهره‌مند شوند. از سوی دیگر، به ارائه‌دهندگان سرویس کمک می‌کنند تا قابلیت‌های خود را به صورت ماژولار و قابل استفاده مجدد در اختیار دیگران قرار دهند.

در میان هزاران API موجود، API گیت‌هاب به دلیل گستردگی استفاده و اهمیت آن در جامعه توسعه‌دهندگان، به عنوان یک نمونه برجسته و بسیار محبوب شناخته می‌شود. گیت‌هاب به عنوان بزرگترین پلتفرم میزبانی کد و کنترل نسخه در جهان، نه تنها برای مدیریت پروژه‌های نرم‌افزاری کاربرد دارد، بلکه API قدرتمند آن نیز امکان خودکارسازی فرآیندها، ایجاد ابزارهای سفارشی، و ادغام با سرویس‌های دیگر را فراهم می‌آورد. این API به توسعه‌دهندگان اجازه می‌دهد تا به اطلاعات مخازن، کاربران، issueها، Pull Requestها و بسیاری دیگر از منابع گیت‌هاب دسترسی پیدا کرده و آن‌ها را مدیریت کنند.

هدف از این مقاله، ارائه یک آموزش جامع و گام به گام برای استفاده از یک API محبوب، با تمرکز ویژه بر API RESTful گیت‌هاب است. ما به تفصیل به مفاهیم بنیادی APIهای RESTful، روش‌های احراز هویت، انجام عملیات CRUD (ایجاد، خواندن، به‌روزرسانی، حذف) بر روی منابع گیت‌هاب، مدیریت محدودیت نرخ (Rate Limiting)، صفحه‌بندی (Pagination) و خطایابی خواهیم پرداخت. در نهایت، با ارائه یک مثال عملی پیشرفته، نحوه پیاده‌سازی یک ابزار کاربردی با استفاده از این API را نشان خواهیم داد. این آموزش برای توسعه‌دهندگان، مهندسان DevOps و هر فردی که به دنبال تسلط بر نحوه تعامل برنامه‌نویسی با سرویس‌های ابری است، طراحی شده و پیش‌نیاز آن تنها آشنایی مقدماتی با برنامه‌نویسی و مفاهیم وب است.

با مطالعه این راهنما، شما نه تنها درک عمیقی از نحوه کار با GitHub API پیدا خواهید کرد، بلکه مهارت‌های لازم برای کار با هر API RESTful دیگری را نیز کسب خواهید کرد. بیایید سفر خود را به دنیای APIها آغاز کنیم!

درک مفاهیم بنیادی RESTful API و HTTP

قبل از اینکه به جزئیات GitHub API بپردازیم، لازم است درک قوی‌ای از مفاهیم بنیادی پشت APIهای RESTful و پروتکل HTTP داشته باشیم. این دانش، ستون فقرات هرگونه تعامل موفق با APIهای وب را تشکیل می‌دهد.

RESTful API چیست؟

REST (Representational State Transfer) یک سبک معماری برای سیستم‌های توزیع شده است که توسط Roy Fielding در سال 2000 معرفی شد. یک API که از اصول REST پیروی می‌کند، “RESTful” نامیده می‌شود. ویژگی‌های کلیدی یک RESTful API عبارتند از:

  • Client-Server (کلاینت-سرور): جداسازی نگرانی‌ها بین رابط کاربری (کلاینت) و ذخیره‌سازی داده (سرور) که قابلیت پرتابل بودن رابط کاربری را افزایش می‌دهد و مقیاس‌پذیری سرور را بهبود می‌بخشد.
  • Stateless (بی‌حالت): هر درخواست از کلاینت به سرور باید حاوی تمام اطلاعات لازم برای پردازش درخواست باشد. سرور نباید هیچ اطلاعاتی درباره وضعیت کلاینت بین درخواست‌ها ذخیره کند. این ویژگی مقیاس‌پذیری و قابلیت اطمینان را افزایش می‌دهد.
  • Cacheable (قابل ذخیره‌سازی): پاسخ‌ها از سرور باید صریحاً یا ضمنی به عنوان قابل کش شدن یا غیرقابل کش شدن تعریف شوند تا از استفاده مجدد از داده‌ها جلوگیری شود.
  • Layered System (سیستم لایه‌ای): یک کلاینت نمی‌تواند تشخیص دهد که آیا مستقیماً به سرور نهایی متصل است یا به یک واسطه. این لایه‌ها می‌توانند شامل پراکسی‌ها، دروازه‌ها یا لود بالانسرها باشند.
  • Uniform Interface (رابط یکپارچه): این مهم‌ترین محدودیت REST است که شامل چهار زیرمحدودیت می‌شود:
    • Identification of Resources (شناسایی منابع): منابع (مانند یک کاربر، یک مخزن) با استفاده از URI (Uniform Resource Identifier) منحصربه‌فرد شناسایی می‌شوند.
    • Manipulation of Resources Through Representations (دستکاری منابع از طریق بازنمایی): کلاینت با یک بازنمایی از منبع تعامل دارد (مثلاً یک سند JSON یا XML). سرور وضعیت منبع را تغییر می‌دهد و بازنمایی جدید را برمی‌گرداند.
    • Self-Descriptive Messages (پیام‌های خودتوصیف‌گر): هر پیام شامل اطلاعات کافی برای تفسیر پیام است. این شامل متدهای HTTP، هدرها و بدنه پیام می‌شود.
    • Hypermedia as the Engine of Application State (HATEOAS) (هایپرمدیا به عنوان موتور وضعیت برنامه): کلاینت‌ها باید بتوانند با استفاده از لینک‌هایی که سرور در پاسخ‌های خود ارائه می‌دهد، وضعیت برنامه را تغییر دهند. این ویژگی کمتر در عمل رعایت می‌شود اما بخش مهمی از مفهوم REST است.

پروتکل HTTP و متدهای آن

HTTP (Hypertext Transfer Protocol) پروتکل ارتباطی اصلی برای انتقال داده‌ها در وب است. RESTful APIها به شدت به HTTP و متدهای آن (که گاهی اوقات افعال HTTP نامیده می‌شوند) متکی هستند تا نوع عملیات مورد نظر را بر روی یک منبع مشخص کنند. متدهای اصلی HTTP که در APIها استفاده می‌شوند عبارتند از:

  • GET: برای بازیابی (خواندن) داده‌ها از یک منبع. درخواست‌های GET نباید هیچ تغییری در سرور ایجاد کنند (Idempotent و Safe).
  • POST: برای ارسال داده‌ها به سرور برای ایجاد یک منبع جدید.
  • PUT: برای به‌روزرسانی کامل یک منبع موجود یا ایجاد آن در صورت عدم وجود (Idempotent).
  • PATCH: برای به‌روزرسانی جزئی یک منبع موجود.
  • DELETE: برای حذف یک منبع مشخص.

علاوه بر متدها، درک کدهای وضعیت HTTP نیز بسیار حیاتی است. این کدها اطلاعاتی درباره نتیجه یک درخواست ارائه می‌دهند. برخی از مهم‌ترین آن‌ها عبارتند از:

  • 200 OK: درخواست با موفقیت انجام شد.
  • 201 Created: یک منبع جدید با موفقیت ایجاد شد (معمولاً پس از POST).
  • 204 No Content: درخواست با موفقیت انجام شد اما هیچ پاسخی برای بازگشت وجود ندارد (معمولاً پس از DELETE).
  • 400 Bad Request: درخواست به دلیل نحو نادرست یا پارامترهای نامعتبر قابل پردازش نیست.
  • 401 Unauthorized: درخواست نیاز به احراز هویت دارد و کلاینت احراز هویت نشده یا اطلاعات احراز هویت نامعتبر است.
  • 403 Forbidden: سرور درخواست را درک کرده اما از اجرای آن خودداری می‌کند (به دلیل عدم دسترسی).
  • 404 Not Found: منبع درخواستی پیدا نشد.
  • 429 Too Many Requests: کلاینت درخواست‌های زیادی را در یک بازه زمانی خاص ارسال کرده (محدودیت نرخ).
  • 500 Internal Server Error: یک خطای عمومی در سمت سرور رخ داده است.

URL/Endpoint: هر منبع در یک RESTful API با یک URL منحصربه‌فرد (که در زمینه APIها اغلب “endpoint” نامیده می‌شود) شناسایی می‌شود. به عنوان مثال، https://api.github.com/users/octocat یک endpoint برای دسترسی به اطلاعات کاربر ‘octocat’ در GitHub API است.

JSON (JavaScript Object Notation): فرمت استاندارد برای تبادل داده در اکثر APIهای RESTful است. JSON یک فرمت سبک‌وزن و قابل خواندن توسط انسان برای نمایش ساختارهای داده‌ای است. GitHub API نیز عمدتاً از JSON برای درخواست‌ها و پاسخ‌های خود استفاده می‌کند.

با این درک بنیادی، اکنون آماده‌ایم تا به سراغ احراز هویت و نحوه تعامل عملی با GitHub API برویم.

آماده‌سازی محیط و احراز هویت (Authentication) با گیت‌هاب API

برای شروع کار با GitHub API، اولین و مهم‌ترین گام، احراز هویت است. بدون احراز هویت، اکثر درخواست‌ها به API با خطا مواجه خواهند شد، زیرا گیت‌هاب برای محافظت از داده‌های کاربران و مدیریت دسترسی، احراز هویت را الزامی می‌داند. در این بخش، بر روی استفاده از Personal Access Token (PAT) تمرکز خواهیم کرد که ساده‌ترین و رایج‌ترین روش برای دسترسی برنامه‌نویسی به GitHub API برای مقاصد شخصی یا اسکریپت‌های کوچک است.

Personal Access Token (PAT) چیست و چگونه آن را ایجاد کنیم؟

Personal Access Token یک رشته الفبایی-عددی طولانی است که به عنوان یک رمز عبور جایگزین برای دسترسی به GitHub API استفاده می‌شود. مزیت PATها این است که می‌توان به آن‌ها اسکوب (scope) یا مجوزهای خاصی را اختصاص داد، به این معنی که شما می‌توانید دقیقاً مشخص کنید که یک توکن به چه منابعی دسترسی داشته باشد (مثلاً فقط خواندن مخازن، یا توانایی ایجاد issueها). این کار امنیت را در مقایسه با استفاده از رمز عبور اصلی شما افزایش می‌دهد.

مراحل ایجاد Personal Access Token:

  1. وارد حساب کاربری خود در GitHub شوید.
  2. در گوشه بالا سمت راست، روی تصویر پروفایل خود کلیک کنید و سپس “Settings” را انتخاب کنید.
  3. در نوار کناری سمت چپ، به پایین اسکرول کنید و روی “Developer settings” کلیک کنید.
  4. در “Developer settings”، روی “Personal access tokens” و سپس “Tokens (classic)” کلیک کنید. (گیت‌هاب توکن‌های Fine-grained را نیز معرفی کرده که دقیق‌تر هستند، اما برای شروع، Classic Tokens ساده‌ترند.)
  5. روی “Generate new token” و سپس “Generate new token (classic)” کلیک کنید.
  6. یک نام توصیفی برای توکن خود وارد کنید (مثلاً “API Tutorial Token”).
  7. یک تاریخ انقضا برای توکن خود انتخاب کنید. توصیه می‌شود برای امنیت بیشتر، توکن‌ها را برای مدت طولانی منقضی نکنید.
  8. انتخاب Scopes: این مرحله بسیار مهم است. بسته به عملیاتی که می‌خواهید با API انجام دهید، باید اسکوب‌های مناسب را انتخاب کنید. برای مثال، اگر می‌خواهید مخازن را بخوانید، نیاز به اسکوب repo یا public_repo دارید. اگر می‌خواهید issue ایجاد کنید، repo لازم است. برای این آموزش، می‌توانید repo کامل را انتخاب کنید تا به تمام قابلیت‌های مخازن دسترسی داشته باشید، اما در محیط واقعی، همیشه حداقل مجوزهای لازم را انتخاب کنید.
    • برای دسترسی به اطلاعات عمومی کاربر و مخازن عمومی: public_repo
    • برای دسترسی کامل به مخازن خصوصی و عمومی (شامل خواندن، نوشتن، ایجاد، حذف): repo
    • برای مدیریت issueها: repo یا issue (اگر اسکوب issue در دسترس بود)
    • برای خواندن اطلاعات کاربر: read:user
  9. پس از انتخاب اسکوب‌ها، روی “Generate token” کلیک کنید.
  10. توکن را کپی کنید! توکن فقط یک بار نمایش داده می‌شود. اگر آن را از دست بدهید، باید یک توکن جدید ایجاد کنید. توکن خود را در یک مکان امن نگهداری کنید و هرگز آن را در کد منبع یا کنترل نسخه عمومی قرار ندهید.

آماده‌سازی محیط و ابزارهای مورد نیاز

برای تعامل با API، از ابزارهای مختلفی می‌توان استفاده کرد. در این آموزش، ما از curl (یک ابزار خط فرمان برای انتقال داده‌ها با URLها) برای مثال‌های ساده و از پایتون به همراه کتابخانه requests برای مثال‌های برنامه‌نویسی پیچیده‌تر استفاده خواهیم کرد. اطمینان حاصل کنید که پایتون و pip (مدیر بسته پایتون) بر روی سیستم شما نصب هستند. اگر نیستند، می‌توانید آن‌ها را از وب‌سایت رسمی پایتون دانلود و نصب کنید.

برای نصب کتابخانه requests:

pip install requests

انجام اولین درخواست API با Personal Access Token

برای اولین تست، اطلاعات کاربر احراز هویت شده را بازیابی می‌کنیم. این اطلاعات شامل نام کاربری، شناسه، و URL آواتار است. از curl استفاده می‌کنیم:

curl -H "Authorization: token YOUR_PERSONAL_ACCESS_TOKEN" \
     https://api.github.com/user

به جای YOUR_PERSONAL_ACCESS_TOKEN، توکن واقعی خود را قرار دهید. دقت کنید که بین token و توکن شما باید یک فاصله باشد.
پاسخ باید یک شیء JSON حاوی اطلاعات شما باشد، مشابه:

{
  "login": "your_username",
  "id": 123456,
  "node_id": "MDQ6VXNlcjEyMzQ1Ng==",
  "avatar_url": "https://avatars.githubusercontent.com/u/123456?v=4",
  "gravatar_id": "",
  "url": "https://api.github.com/users/your_username",
  "html_url": "https://github.com/your_username",
  "followers_url": "https://api.github.com/users/your_username/followers",
  // ... سایر اطلاعات
}

اگر پاسخ 401 Unauthorized یا 403 Forbidden دریافت کردید، توکن شما اشتباه است، منقضی شده، یا اسکوب‌های لازم را ندارد. حتماً توکن را بررسی کنید.

با موفقیت احراز هویت شدیم و اولین درخواست API را انجام دادیم! اکنون می‌توانیم به سراغ عملیات پیچیده‌تر برویم.

کاوش Endpointsهای گیت‌هاب API: عملیات CRUD

حالا که با موفقیت احراز هویت را انجام داده‌اید، زمان آن رسیده است که به کاوش Endpointsهای مختلف GitHub API بپردازیم و عملیات اصلی CRUD (Create, Read, Update, Delete) را با مثال‌های عملی مرور کنیم.

Reading (GET) Data: بازیابی اطلاعات

عملیات GET پرکاربردترین متد برای بازیابی اطلاعات از API است. GitHub API دارای هزاران endpoint GET برای دسترسی به انواع منابع است.

بازیابی اطلاعات یک کاربر خاص:

برای دریافت اطلاعات عمومی یک کاربر خاص (مثلاً octocat):

curl https://api.github.com/users/octocat

این درخواست نیازی به احراز هویت ندارد زیرا اطلاعات کاربر عمومی است.

لیست کردن مخازن عمومی یک کاربر:

برای مشاهده تمام مخازن عمومی متعلق به یک کاربر (مثلاً octocat):

curl https://api.github.com/users/octocat/repos

بازیابی اطلاعات یک مخزن خاص:

برای دریافت اطلاعات یک مخزن خاص (مثلاً octocat/Spoon-Knife):

curl https://api.github.com/repos/octocat/Spoon-Knife

لیست کردن Issueهای یک مخزن:

برای مشاهده issueهای باز (open) یک مخزن (مثلاً octocat/Spoon-Knife):

curl -H "Authorization: token YOUR_PERSONAL_ACCESS_TOKEN" \
     https://api.github.com/repos/octocat/Spoon-Knife/issues

برای دسترسی به issueها، حتی اگر مخزن عمومی باشد، ممکن است نیاز به توکن داشته باشید، به خصوص اگر بخواهید به جزئیات بیشتری دسترسی پیدا کنید یا به وضعیت‌های مختلف Issueها فیلتر کنید. اسکوب repo یا public_repo (اگر مخزن عمومی باشد) لازم است.

Creating (POST) Data: ایجاد منابع جدید

متد POST برای ایجاد منابع جدید در سرور استفاده می‌شود. برای این عملیات، معمولاً باید داده‌ها را در قالب JSON در بدنه درخواست ارسال کنید.

ایجاد یک مخزن جدید:

برای ایجاد یک مخزن خصوصی جدید تحت حساب کاربری خودتان، نیاز به اسکوب repo دارید. (نام مخزن باید منحصربه‌فرد باشد.)

curl -X POST \
     -H "Authorization: token YOUR_PERSONAL_ACCESS_TOKEN" \
     -H "Accept: application/vnd.github+json" \
     -d '{
       "name": "my-new-repo",
       "description": "This is my first repo created via API",
       "private": true,
       "auto_init": true
     }' \
     https://api.github.com/user/repos
  • -X POST: مشخص می‌کند که این یک درخواست POST است.
  • -H "Authorization: ...": توکن احراز هویت شما.
  • -H "Accept: application/vnd.github+json": این هدر توصیه شده توسط GitHub است تا مطمئن شوید که پاسخ JSON دریافت می‌کنید.
  • -d '{...}': بدنه درخواست JSON که حاوی داده‌های مخزن جدید است.
    • "name": نام مخزن (ضروری).
    • "description": توضیحات مخزن (اختیاری).
    • "private": true برای مخزن خصوصی، false برای عمومی.
    • "auto_init": true برای ایجاد فایل README اولیه.

در صورت موفقیت، پاسخ شامل اطلاعات کامل مخزن ایجاد شده خواهد بود و کد وضعیت 201 Created را دریافت خواهید کرد.

ایجاد یک Issue جدید در یک مخزن:

برای ایجاد یک issue جدید در مخزنی که به آن دسترسی دارید:

curl -X POST \
     -H "Authorization: token YOUR_PERSONAL_ACCESS_TOKEN" \
     -H "Accept: application/vnd.github+json" \
     -d '{
       "title": "Bug: Login button not working",
       "body": "The login button on the homepage does not respond when clicked.",
       "assignees": ["your_github_username"],
       "labels": ["bug", "frontend"]
     }' \
     https://api.github.com/repos/YOUR_USERNAME/YOUR_REPO_NAME/issues

به جای YOUR_USERNAME و YOUR_REPO_NAME، نام کاربری و نام مخزن خود را قرار دهید. اطمینان حاصل کنید که اسکوب repo را برای توکن خود فعال کرده‌اید.

Updating (PATCH/PUT) Data: به‌روزرسانی منابع

متدهای PATCH و PUT برای به‌روزرسانی منابع استفاده می‌شوند. PUT برای جایگزینی کامل یک منبع و PATCH برای به‌روزرسانی جزئی آن است. GitHub API اغلب برای به‌روزرسانی‌ها از PATCH استفاده می‌کند.

به‌روزرسانی یک Issue موجود:

برای به‌روزرسانی عنوان یا بدنه یک issue، یا تغییر وضعیت آن به “بسته شده” (closed):

curl -X PATCH \
     -H "Authorization: token YOUR_PERSONAL_ACCESS_TOKEN" \
     -H "Accept: application/vnd.github+json" \
     -d '{
       "title": "Fix: Login button responsiveness issue",
       "state": "closed"
     }' \
     https://api.github.com/repos/YOUR_USERNAME/YOUR_REPO_NAME/issues/ISSUE_NUMBER

به جای ISSUE_NUMBER، شماره issue مورد نظر را وارد کنید. پاسخ، اطلاعات به‌روز شده issue را شامل خواهد شد و کد وضعیت 200 OK را دریافت خواهید کرد.

به‌روزرسانی توضیحات یک مخزن:

curl -X PATCH \
     -H "Authorization: token YOUR_PERSONAL_ACCESS_TOKEN" \
     -H "Accept: application/vnd.github+json" \
     -d '{
       "description": "Updated description for my new API-created repo.",
       "private": false
     }' \
     https://api.github.com/repos/YOUR_USERNAME/my-new-repo

این مثال توضیحات مخزن را به‌روز می‌کند و آن را از خصوصی به عمومی تغییر می‌دهد.

Deleting (DELETE) Data: حذف منابع

متد DELETE برای حذف یک منبع استفاده می‌شود. این عملیات برگشت‌ناپذیر است و باید با احتیاط فراوان انجام شود.

حذف یک مخزن:

هشدار: این عملیات، مخزن و تمام محتویات آن را به صورت دائمی حذف می‌کند. در محیط واقعی، همیشه از خودتان بپرسید آیا واقعاً به حذف نیاز دارید یا خیر و مطمئن شوید که هیچ اطلاعات مهمی از بین نمی‌رود.

curl -X DELETE \
     -H "Authorization: token YOUR_PERSONAL_ACCESS_TOKEN" \
     -H "Accept: application/vnd.github+json" \
     https://api.github.com/repos/YOUR_USERNAME/my-new-repo

در صورت موفقیت‌آمیز بودن حذف، کد وضعیت 204 No Content را دریافت خواهید کرد، به این معنی که درخواست موفق بوده اما سرور هیچ محتوایی برای بازگشت ندارد.

این بخش، عملیات پایه CRUD را پوشش داد. GitHub API دارای هزاران endpoint دیگر برای تعامل با Pull Requestها، Gistها، Hooks، سازمان‌ها و بسیاری موارد دیگر است. همیشه به مستندات رسمی GitHub API مراجعه کنید تا دقیق‌ترین و به‌روزترین اطلاعات را در مورد endpointها و پارامترهای آن‌ها دریافت کنید.

مدیریت محدودیت نرخ (Rate Limiting) و صفحه‌بندی (Pagination)

در هنگام کار با APIهای عمومی مانند GitHub API، دو مفهوم حیاتی که برای اطمینان از عملکرد روان و پایدار برنامه‌های شما باید به آن‌ها توجه کنید، محدودیت نرخ (Rate Limiting) و صفحه‌بندی (Pagination) هستند. نادیده گرفتن این موارد می‌تواند منجر به مسدود شدن موقت درخواست‌های شما یا بازیابی ناقص داده‌ها شود.

محدودیت نرخ (Rate Limiting)

APIها برای جلوگیری از سوءاستفاده، حملات DDoS و اطمینان از دسترسی عادلانه برای همه کاربران، تعداد درخواست‌هایی را که یک کلاینت می‌تواند در یک بازه زمانی مشخص ارسال کند، محدود می‌کنند. GitHub API نیز از این قاعده مستثنی نیست. برای درخواست‌های احراز هویت نشده، محدودیت نرخ به طور قابل توجهی پایین‌تر است (مثلاً 60 درخواست در ساعت). برای درخواست‌های احراز هویت شده با Personal Access Token یا OAuth، محدودیت بسیار بالاتر است (مثلاً 5000 درخواست در ساعت).

درک هدرهای محدودیت نرخ:

پاسخ‌های API گیت‌هاب شامل هدرهای خاصی هستند که اطلاعات مربوط به محدودیت نرخ شما را ارائه می‌دهند:

  • X-RateLimit-Limit: حداکثر تعداد درخواست‌هایی که می‌توانید در یک بازه زمانی خاص (مثلاً 60 دقیقه) ارسال کنید.
  • X-RateLimit-Remaining: تعداد درخواست‌های باقی‌مانده در بازه زمانی فعلی.
  • X-RateLimit-Reset: زمان (در قالب Unix epoch seconds) که محدودیت نرخ فعلی شما بازنشانی می‌شود.
  • X-RateLimit-Used: تعداد درخواست‌هایی که در بازه زمانی فعلی استفاده شده‌اند.

مثال پاسخ هدرها:

HTTP/1.1 200 OK
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4999
X-RateLimit-Reset: 1678886400 // March 15, 2023 12:00:00 AM UTC
X-RateLimit-Used: 1
...

مدیریت محدودیت نرخ:

وقتی X-RateLimit-Remaining به صفر برسد، درخواست‌های بعدی شما تا زمان بازنشانی (reset) با کد وضعیت 429 Too Many Requests مواجه می‌شوند. برای جلوگیری از این اتفاق، بهترین شیوه‌ها عبارتند از:

  1. بررسی هدرها: همیشه هدرهای محدودیت نرخ را در پاسخ‌های API بررسی کنید.
  2. مکث (Sleep): اگر X-RateLimit-Remaining به مقدار کمی رسید، یا اگر کد 429 دریافت کردید، برنامه خود را تا زمان X-RateLimit-Reset متوقف کنید (sleep). زمان X-RateLimit-Reset یک Timestamp است که باید آن را به زمان محلی تبدیل کرده و مکث را بر اساس آن تنظیم کنید.
  3. استفاده از Exponential Backoff: اگر با خطای 429 مواجه شدید، به جای تلاش مجدد فوری، با یک تأخیر فزاینده (مثلاً 2 ثانیه، 4 ثانیه، 8 ثانیه و…) درخواست را تکرار کنید. این کار به سرور اجازه می‌دهد تا بازیابی شود و از بدتر شدن وضعیت جلوگیری می‌کند.
  4. کش کردن داده‌ها: داده‌هایی که به طور مکرر استفاده می‌شوند یا تغییر نمی‌کنند را کش کنید تا تعداد درخواست‌های API را کاهش دهید.
  5. درخواست‌های مشروط (Conditional Requests): از هدرهای If-None-Match (با ETag) و If-Modified-Since استفاده کنید تا فقط در صورتی داده‌ها را بازیابی کنید که تغییر کرده باشند. این کار تعداد درخواست‌ها را کاهش می‌دهد و استفاده از پهنای باند را بهینه می‌کند.

صفحه‌بندی (Pagination)

بسیاری از Endpointsهای API (مانند لیست کردن مخازن، issueها یا کاربران) ممکن است حجم زیادی از داده‌ها را برگردانند. برای مدیریت این داده‌ها و جلوگیری از ارسال پاسخ‌های بسیار بزرگ، APIها از صفحه‌بندی (Pagination) استفاده می‌کنند. به این معنی که نتایج به صفحات کوچک‌تر تقسیم می‌شوند.

پارامترهای صفحه‌بندی:

GitHub API از دو پارامتر کوئری برای کنترل صفحه‌بندی استفاده می‌کند:

  • per_page: تعداد آیتم‌ها در هر صفحه (حداکثر 100). پیش‌فرض معمولاً 30 است.
  • page: شماره صفحه‌ای که می‌خواهید بازیابی کنید (شروع از 1).

مثال: بازیابی 50 مخزن در صفحه دوم:

curl "https://api.github.com/users/octocat/repos?page=2&per_page=50"

هدر Link: پیمایش صفحات

روش استاندارد و توصیه شده برای پیمایش صفحات در GitHub API استفاده از هدر Link در پاسخ‌های HTTP است. این هدر شامل URLهای صفحات بعدی (next)، قبلی (prev)، اول (first) و آخر (last) است، اگر وجود داشته باشند.

Link: <https://api.github.com/user/repos?page=2&per_page=100>; rel="next",
      <https://api.github.com/user/repos?page=1&per_page=100>; rel="prev",
      <https://api.github.com/user/repos?page=1&per_page=100>; rel="first",
      <https://api.github.com/user/repos?page=5&per_page=100>; rel="last"

شما باید این هدر را پارس کرده و URLهای مربوطه را برای پیمایش خودکار به صفحات بعدی استخراج کنید. این روش مقاوم‌تر از حدس زدن شماره صفحه بعدی است، زیرا سرور خود مدیریت می‌کند که کدام صفحات در دسترس هستند.

نمونه پیاده‌سازی پیمایش صفحه‌بندی (پایتون):

در کد نویسی، معمولاً با استفاده از یک حلقه تا زمانی که هدر Link شامل rel="next" باشد، صفحات را یکی یکی بازیابی می‌کنید.

import requests
import time

def get_all_repos(username, token):
    repos = []
    url = f"https://api.github.com/users/{username}/repos?per_page=100"
    headers = {
        "Authorization": f"token {token}",
        "Accept": "application/vnd.github+json"
    }

    while url:
        response = requests.get(url, headers=headers)
        
        # Handle rate limiting
        if response.status_code == 429:
            reset_time = int(response.headers.get('X-RateLimit-Reset', time.time() + 60))
            sleep_duration = reset_time - int(time.time()) + 1 # Add 1 second buffer
            print(f"Rate limit exceeded. Sleeping for {sleep_duration} seconds.")
            time.sleep(sleep_duration)
            continue # Retry the same URL

        response.raise_for_status() # Raises an HTTPError for bad responses (4xx or 5xx)
        
        repos.extend(response.json())
        
        # Check for next page link
        if 'Link' in response.headers:
            links = requests.utils.parse_header_links(response.headers['Link'])
            next_link = next((link['url'] for link in links if link['rel'] == 'next'), None)
            url = next_link
        else:
            url = None
            
    return repos

# Example usage:
# YOUR_USERNAME = "your_github_username"
# YOUR_TOKEN = "your_personal_access_token"
# all_repos = get_all_repos(YOUR_USERNAME, YOUR_TOKEN)
# print(f"Total repositories fetched: {len(all_repos)}")

با درک و پیاده‌سازی صحیح محدودیت نرخ و صفحه‌بندی، برنامه‌های شما می‌توانند به طور کارآمد و مطمئن با GitHub API (و سایر APIها) تعامل داشته باشند.

خطایابی (Error Handling) و بهترین شیوه‌ها در کار با API

در دنیای برنامه‌نویسی API، خطاهای غیرمنتظره اجتناب‌ناپذیرند. یک برنامه قوی باید بتواند این خطاها را به درستی شناسایی، مدیریت و به کاربر اطلاع‌رسانی کند. همچنین، رعایت بهترین شیوه‌ها در استفاده از API نه تنها به پایداری برنامه شما کمک می‌کند، بلکه تضمین می‌کند که از منابع API به صورت بهینه و مسئولانه استفاده می‌کنید.

خطایابی (Error Handling)

هنگام تعامل با API، همیشه انتظار داشته باشید که با خطاها مواجه شوید. GitHub API از کدهای وضعیت HTTP استاندارد برای نشان دادن نوع خطا استفاده می‌کند، و اغلب اطلاعات بیشتری را در بدنه پاسخ JSON ارائه می‌دهد.

کدهای خطای رایج و نحوه برخورد با آن‌ها:

  • 400 Bad Request: نشان‌دهنده این است که درخواست شما به درستی فرمت نشده یا شامل پارامترهای نامعتبر است.

    مدیریت: لاگ کردن درخواست و پاسخ، بررسی مستندات API برای اطمینان از صحت پارامترها و فرمت داده‌ها.
  • 401 Unauthorized: به این معنی است که درخواست شما نیاز به احراز هویت دارد اما توکن شما نامعتبر است یا اصلا ارسال نشده.

    مدیریت: اطمینان از ارسال توکن صحیح و فعال. بررسی اسکوب‌های توکن برای اطمینان از داشتن مجوزهای لازم. ممکن است توکن منقضی شده باشد.
  • 403 Forbidden: شما احراز هویت شده‌اید، اما برای انجام عملیات درخواستی مجوز لازم را ندارید. این ممکن است به دلیل محدودیت‌های سازمانی، یا عدم داشتن اسکوب مناسب در توکن باشد.

    مدیریت: بررسی اسکوب‌های توکن، بررسی دسترسی کاربر به منبع درخواستی. پیام خطا در بدنه پاسخ می‌تواند جزئیات بیشتری ارائه دهد.
  • 404 Not Found: منبع درخواستی (URL) وجود ندارد.

    مدیریت: بررسی دقیق URL و اطمینان از املای صحیح و وجود منبع.
  • 422 Unprocessable Entity: درخواست شما از نظر معنایی اشتباه است. مثلاً سعی در ایجاد یک مخزن با نامی که از قبل وجود دارد.

    مدیریت: بررسی پیام‌های خطا در بدنه پاسخ JSON برای درک مشکل خاص (مثلاً: “Repository already exists”). اصلاح داده‌های ارسالی.
  • 429 Too Many Requests: محدودیت نرخ شما فرا رسیده است.

    مدیریت: همانطور که در بخش قبل توضیح داده شد، از استراتژی‌های مکث و Exponential Backoff استفاده کنید.
  • 500 Internal Server Error: یک خطای ناشناخته در سمت سرور API رخ داده است.

    مدیریت: این خطا خارج از کنترل شماست. معمولاً با یک تلاش مجدد پس از یک تأخیر کوتاه ممکن است مشکل حل شود. اگر ادامه داشت، به وضعیت سرویس API (status page) مراجعه کنید.
  • 503 Service Unavailable: سرور در حال حاضر قادر به رسیدگی به درخواست نیست (مثلاً در حال نگهداری است یا بیش از حد بارگذاری شده).

    مدیریت: مانند 500، تلاش مجدد با تأخیر یا بررسی وضعیت سرویس.

پارس کردن پیام‌های خطا در JSON:

وقتی خطایی رخ می‌دهد، GitHub API اغلب یک شیء JSON با جزئیات خطا برمی‌گرداند. این پیام‌ها معمولاً شامل فیلدهایی مانند message و documentation_url هستند.

{
  "message": "Validation Failed",
  "errors": [
    {
      "resource": "Repository",
      "code": "custom",
      "field": "name",
      "message": "name already exists on this account"
    }
  ],
  "documentation_url": "https://docs.github.com/rest/repos/repos#create-a-repository-for-the-authenticated-user"
}

برنامه شما باید این پاسخ‌ها را پارس کند و پیام‌های خطا را به صورت خوانا به کاربر ارائه دهد یا بر اساس آن‌ها تصمیم‌گیری کند.

بهترین شیوه‌ها (Best Practices) در کار با API

برای توسعه برنامه‌های کارآمد، مقیاس‌پذیر و مسئولانه که از APIها استفاده می‌کنند، رعایت بهترین شیوه‌ها ضروری است:

  1. حداقل کردن درخواست‌ها:
    • کش کردن (Caching): داده‌هایی که به ندرت تغییر می‌کنند را کش کنید تا از درخواست‌های تکراری جلوگیری کنید.
    • درخواست‌های مشروط (Conditional Requests): از هدرهای If-None-Match (با ETag) و If-Modified-Since استفاده کنید. اگر منبع از آخرین باری که آن را درخواست کرده‌اید تغییری نکرده باشد، سرور پاسخ 304 Not Modified را برمی‌گرداند که باعث صرفه‌جویی در پهنای باند و جلوگیری از شمارش محدودیت نرخ می‌شود.
    • درخواست‌های دسته‌ای (Batching – اگر API پشتیبانی کند): برخی APIها اجازه می‌دهند چندین عملیات را در یک درخواست ادغام کنید. (GitHub REST API این قابلیت را به صورت گسترده ندارد، اما GraphQL API آن را پشتیبانی می‌کند.)
  2. مدیریت امنیتی توکن‌ها:
    • هرگز توکن‌ها را در کد منبع یا کنترل نسخه عمومی قرار ندهید. از متغیرهای محیطی، فایل‌های پیکربندی خارج از کنترل نسخه، یا سرویس‌های مدیریت Secrets استفاده کنید.
    • کمترین امتیاز (Least Privilege): همیشه کمترین اسکوب (مجوز) لازم را به توکن‌های خود بدهید.
    • انقضای توکن: توکن‌ها را با تاریخ انقضا محدود کنید.
    • چرخش توکن: به صورت دوره‌ای توکن‌ها را تغییر دهید.
  3. پیام‌های کاربردی:
    • User-Agent Header: یک هدر User-Agent شامل نام برنامه و اطلاعات تماس (مثلاً ایمیل) خود را ارسال کنید. این به ارائه‌دهنده API کمک می‌کند تا در صورت بروز مشکل با شما تماس بگیرد. مثال: User-Agent: MyGitHubApp/1.0 (contact@example.com)
  4. پایبندی به مستندات:
    • همیشه به مستندات رسمی API مراجعه کنید. APIها دائماً در حال تغییر و تکامل هستند.
    • به هشدارها و deprecation noticeها توجه کنید.
  5. آزمایش و لاگ‌برداری:
    • برنامه‌هایی که با APIها کار می‌کنند را به دقت تست کنید تا مطمئن شوید که خطاهای مختلف را به درستی مدیریت می‌کنند.
    • لاگ‌برداری دقیق از درخواست‌ها، پاسخ‌ها و خطاها برای عیب‌یابی ضروری است.
  6. استفاده از SDK/Libraries:
    • برای زبان‌های برنامه‌نویسی محبوب، اغلب SDKها یا کتابخانه‌هایی وجود دارند که کار با API را ساده‌تر می‌کنند. این SDKها معمولاً مدیریت احراز هویت، محدودیت نرخ و صفحه‌بندی را برای شما انجام می‌دهند. برای مثال، برای پایتون، کتابخانه‌هایی مانند PyGithub وجود دارد.

با رعایت این اصول، می‌توانید برنامه‌هایی بسازید که نه تنها کارآمد هستند، بلکه به خوبی با سرویس‌های API تعامل می‌کنند و در برابر مشکلات احتمالی مقاومند.

مثال عملی پیشرفته: ساخت یک ابزار ساده با گیت‌هاب API

تا اینجای کار با مفاهیم نظری و عملیات پایه API آشنا شدیم. اکنون زمان آن رسیده است که تمام آموخته‌های خود را در یک مثال عملی و کمی پیشرفته‌تر ترکیب کنیم. در این بخش، یک اسکریپت پایتون خواهیم نوشت که با استفاده از GitHub API، لیست تمام مخازن (هم عمومی و هم خصوصی) یک کاربر/سازمان را بازیابی کرده و برای هر مخزن، تعداد Issueهای باز (Open Issues) را شمارش می‌کند.

این مثال شامل موارد زیر خواهد بود:

  • احراز هویت با Personal Access Token.
  • مدیریت صفحه‌بندی برای بازیابی تمام مخازن.
  • بازیابی اطلاعات Issueها برای هر مخزن.
  • مدیریت خطاهای رایج (مانند محدودیت نرخ).

سناریو: گزارشگر وضعیت مخازن

هدف ما ساخت ابزاری است که بتواند خلاصه‌ای از وضعیت مخازن یک کاربر یا سازمان را ارائه دهد. این ابزار برای مدیران پروژه یا توسعه‌دهندگانی که می‌خواهند دید کلی از پروژه‌های خود داشته باشند، مفید خواهد بود.

پیش‌نیازها:

  • پایتون 3 نصب شده باشد.
  • کتابخانه requests نصب شده باشد (pip install requests).
  • یک Personal Access Token گیت‌هاب با اسکوب repo (برای دسترسی به مخازن خصوصی و عمومی و issueهای آن‌ها).

کد پایتون: github_repo_reporter.py

کد زیر را در یک فایل با نام github_repo_reporter.py ذخیره کنید:

import requests
import os
import time
from datetime import datetime

# --- تنظیمات ---
# توکن دسترسی شخصی گیت‌هاب شما
# توصیه می‌شود این توکن را از متغیرهای محیطی یا یک فایل پیکربندی امن بخوانید.
# برای سادگی در این مثال، مستقیماً قرار داده شده است، اما در محیط تولید این کار توصیه نمی‌شود.
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN", "YOUR_PERSONAL_ACCESS_TOKEN_HERE") # از متغیر محیطی بخوانید
TARGET_ENTITY = "your_github_username_or_org" # نام کاربری گیت‌هاب یا سازمان مورد نظر

# --- توابع کمکی برای API ---

def make_github_api_request(url, token, params=None):
    """
    درخواستی به GitHub API ارسال می‌کند و هدرها و مدیریت محدودیت نرخ را انجام می‌دهد.
    """
    headers = {
        "Authorization": f"token {token}",
        "Accept": "application/vnd.github+json",
        "X-GitHub-Api-Version": "2022-11-28", # برای اطمینان از سازگاری API
        "User-Agent": "GitHubRepoReporter/1.0 (contact@example.com)" # شناسه برنامه شما
    }
    
    while True: # حلقه برای مدیریت محدودیت نرخ
        try:
            response = requests.get(url, headers=headers, params=params)
            response.raise_for_status() # اگر وضعیت پاسخ 4xx یا 5xx باشد، HTTPError ایجاد می‌کند.
            return response
        except requests.exceptions.HTTPError as e:
            if e.response.status_code == 403 and 'X-RateLimit-Remaining' in e.response.headers:
                remaining = int(e.response.headers['X-RateLimit-Remaining'])
                if remaining == 0:
                    reset_time_epoch = int(e.response.headers['X-RateLimit-Reset'])
                    reset_datetime = datetime.fromtimestamp(reset_time_epoch)
                    sleep_duration = (reset_datetime - datetime.now()).total_seconds() + 5 # اضافه کردن 5 ثانیه بافر
                    if sleep_duration > 0:
                        print(f"!!! Rate limit exceeded. Remaining: {remaining}. Reset at: {reset_datetime.strftime('%Y-%m-%d %H:%M:%S')}. Sleeping for {int(sleep_duration)} seconds...")
                        time.sleep(sleep_duration)
                        continue # تلاش مجدد درخواست
                print(f"Error {e.response.status_code} for URL: {url} - {e.response.json().get('message', 'No specific message')}")
                return None # در صورت خطای 403 غیر از Rate Limit یا خطا در Rate Limit
            elif e.response.status_code == 404:
                print(f"Resource not found: {url}")
                return None
            else:
                print(f"An HTTP error occurred: {e.response.status_code} for URL: {url} - {e.response.json().get('message', 'No specific message')}")
                return None
        except requests.exceptions.RequestException as e:
            print(f"An error occurred during the request: {e}")
            return None

def get_all_repos_for_entity(entity_name, token):
    """
    لیست تمام مخازن (عمومی و خصوصی) برای یک کاربر یا سازمان را بازیابی می‌کند.
    """
    repos = []
    
    # بررسی کنید آیا entity_name یک کاربر است یا یک سازمان
    user_check_url = f"https://api.github.com/users/{entity_name}"
    org_check_url = f"https://api.github.com/orgs/{entity_name}"

    user_resp = make_github_api_request(user_check_url, token)
    if user_resp and user_resp.status_code == 200:
        print(f"Fetching repositories for user: {entity_name}")
        url = f"https://api.github.com/users/{entity_name}/repos"
    else:
        org_resp = make_github_api_request(org_check_url, token)
        if org_resp and org_resp.status_code == 200:
            print(f"Fetching repositories for organization: {entity_name}")
            url = f"https://api.github.com/orgs/{entity_name}/repos"
        else:
            print(f"Error: Entity '{entity_name}' not found or no access.")
            return []

    # شروع صفحه‌بندی
    current_url = url + "?per_page=100" # حداکثر آیتم در هر صفحه

    while current_url:
        response = make_github_api_request(current_url, token)
        if not response:
            break
        
        page_repos = response.json()
        repos.extend(page_repos)
        
        # بررسی هدر Link برای URL صفحه بعدی
        if 'Link' in response.headers:
            links = requests.utils.parse_header_links(response.headers['Link'])
            next_link = next((link['url'] for link in links if link['rel'] == 'next'), None)
            current_url = next_link
        else:
            current_url = None
            
        print(f"Fetched {len(page_repos)} repositories from current page. Total: {len(repos)}. {'Moving to next page...' if current_url else 'No more pages.'}")
            
    return repos

def get_open_issues_count(owner, repo_name, token):
    """
    تعداد issueهای باز برای یک مخزن را بازیابی می‌کند.
    """
    url = f"https://api.github.com/repos/{owner}/{repo_name}/issues"
    params = {"state": "open", "per_page": 1} # فقط 1 آیتم در هر صفحه برای گرفتن total_count
    
    response = make_github_api_request(url, token, params=params)
    if not response:
        return 0 # یا مدیریت خطا مناسب‌تر
    
    # GitHub API تعداد کل آیتم‌ها را در هدر Link 'last' و 'total' (گاهی) برمی‌گرداند.
    # یا می‌توانیم `X-Total-Count` را بررسی کنیم (اگر وجود داشته باشد).
    # راه مطمئن‌تر، بررسی 'Link' header و پیدا کردن آخرین صفحه است.
    if 'Link' in response.headers:
        links = requests.utils.parse_header_links(response.headers['Link'])
        last_link = next((link['url'] for link in links if link['rel'] == 'last'), None)
        if last_link:
            # پارس کردن last_link برای استخراج شماره صفحه آخر
            # Example: https://api.github.com/repos/octocat/Spoon-Knife/issues?page=5&per_page=1
            from urllib.parse import urlparse, parse_qs
            parsed_url = urlparse(last_link)
            query_params = parse_qs(parsed_url.query)
            last_page = int(query_params.get('page', ['1'])[0])
            # (last_page - 1) * per_page + count_on_last_page
            # برای ساده‌سازی و جلوگیری از درخواست اضافی برای آخرین صفحه،
            # فرض می‌کنیم هر صفحه پر است به جز آخرین صفحه.
            # یک راه دیگر، استخراج شماره صفحه 'last' و ضرب در per_page است
            # اما این روش دقیق نیست اگر صفحه آخر کامل نباشد.
            # راه دقیق‌تر این است که endpoint دیگری را برای issueها بررسی کنیم که total_count را برمی‌گرداند
            # یا تا زمانی که next_link وجود دارد، iterate کنیم و تعداد را بشماریم.
            # برای این مثال، سریعترین راه استفاده از X-Total-Count است اگر وجود داشته باشد،
            # یا count خودمان در طول صفحه‌بندی در حالت معمول.
            
            # بهترین روش: GitHub API یک هدر X-Total-Count برای issueها ندارد.
            # بهترین راه برای گرفتن تعداد کل issueها این است که endpoint خاصی را فراخوانی کنیم 
            # که متادیتای issueها را برمی‌گرداند یا تمام issueها را صفحه به صفحه بخوانیم و شمارش کنیم.
            # برای سادگی، و فرض اینکه تعداد issueها خیلی زیاد نیست، می‌توانیم تمام issueها را بخوانیم و شمارش کنیم.
            # اما این می‌تواند به Rate Limit برخورد کند.
            # راه مطمئن‌تر برای issue count: endpoint search/issues را با state=open و repo:owner/repo فراخوانی کنیم
            # آن endpoint شامل total_count است.
            # اما برای حفظ سادگی این مثال و تمرکز بر CRUD اصلی:
            
            # روش جایگزین:
            # تعداد آیتم‌های بازگشتی در صفحه اول (اگر <= per_page باشد)
            # و اگر لینک 'last' وجود دارد، شماره صفحه آخر را بگیرید و ضرب در per_page کنید.
            # این روش ممکن است همیشه دقیق نباشد.
            
            # برای دقت، از endpoint search/issues استفاده می‌کنیم که total_count را برمی‌گرداند
            search_url = "https://api.github.com/search/issues"
            search_params = {
                "q": f"repo:{owner}/{repo_name} is:issue is:open",
                "per_page": 1 # فقط برای گرفتن total_count
            }
            search_response = make_github_api_request(search_url, token, params=search_params)
            if search_response:
                search_data = search_response.json()
                return search_data.get('total_count', 0)
            return 0
    return len(response.json()) # اگر لینک 'last' وجود نداشت و فقط یک صفحه بود

# --- منطق اصلی برنامه ---
def main():
    if GITHUB_TOKEN == "YOUR_PERSONAL_ACCESS_TOKEN_HERE" or not GITHUB_TOKEN:
        print("Error: Please set your GitHub Personal Access Token in GITHUB_TOKEN variable or environment.")
        print("You can get one from: https://github.com/settings/tokens")
        print("Make sure it has 'repo' scope.")
        return
    
    if TARGET_ENTITY == "your_github_username_or_org":
        print("Error: Please set the TARGET_ENTITY (your GitHub username or organization name).")
        return

    print(f"--- Fetching repositories for {TARGET_ENTITY} ---")
    repos = get_all_repos_for_entity(TARGET_ENTITY, GITHUB_TOKEN)

    if not repos:
        print("No repositories found or an error occurred during fetching.")
        return

    print(f"\nTotal repositories found: {len(repos)}")
    print("\n--- Repository Report ---")

    for repo in repos:
        repo_name = repo['name']
        repo_owner = repo['owner']['login']
        is_private = " (Private)" if repo['private'] else " (Public)"
        
        print(f"\nRepository: {repo_owner}/{repo_name}{is_private}")
        print(f"  Description: {repo['description'] if repo['description'] else 'N/A'}")
        
        # تنها برای مخازن قابل دسترسی issueها را بررسی کنید
        # این ممکن است در صورت عدم دسترسی به issueهای خاص مخازن خصوصی خطا بدهد.
        # اما با اسکوب 'repo' باید به همه دسترسی داشته باشیم.
        
        print(f"  Fetching open issues for {repo_name}...")
        open_issues_count = get_open_issues_count(repo_owner, repo_name, GITHUB_TOKEN)
        print(f"  Open Issues: {open_issues_count}")
        print("-" * 30)

    print("\n--- Report Complete ---")

if __name__ == "__main__":
    main()

توضیحات کد:

  • GITHUB_TOKEN و TARGET_ENTITY: این متغیرها را با توکن دسترسی شخصی و نام کاربری/سازمان خود جایگزین کنید. توصیه می‌شود برای امنیت بیشتر، توکن را از متغیرهای محیطی بخوانید (همانطور که در کد نشان داده شده است).
  • make_github_api_request(url, token, params=None):
    • این تابع یک wrapper برای ارسال درخواست‌های HTTP به GitHub API است.
    • هدرهای ضروری مانند Authorization، Accept و User-Agent را اضافه می‌کند.
    • یک مکانیزم ساده برای مدیریت 429 Too Many Requests (محدودیت نرخ) پیاده‌سازی می‌کند. در صورت دریافت 429، برنامه تا زمان بازنشانی محدودیت نرخ متوقف شده و سپس درخواست را تکرار می‌کند.
    • خطاهای HTTP دیگر (404، 403 و سایر HTTPError) را مدیریت می‌کند.
  • get_all_repos_for_entity(entity_name, token):
    • این تابع ابتدا بررسی می‌کند که entity_name یک کاربر است یا یک سازمان، سپس URL صحیح API را برای لیست کردن مخازن آن entity می‌سازد.
    • از صفحه‌بندی استفاده می‌کند. با ارسال per_page=100 حداکثر تعداد مخازن را در هر صفحه درخواست می‌کند.
    • با بررسی هدر Link در پاسخ‌های API، به طور خودکار صفحات بعدی را بازیابی می‌کند تا زمانی که هیچ صفحه دیگری وجود نداشته باشد.
  • get_open_issues_count(owner, repo_name, token):
    • این تابع تعداد issueهای باز یک مخزن را بازیابی می‌کند.
    • برای به دست آوردن تعداد دقیق Issueهای باز، از endpoint /search/issues استفاده می‌کند. این endpoint پارامتر total_count را در پاسخ برمی‌گرداند که تعداد کل نتایج را نشان می‌دهد، بدون اینکه نیاز باشد تمام Issueها را صفحه به صفحه بخوانیم که به سرعت به محدودیت نرخ برخورد خواهیم کرد.
  • main():
    • تابع اصلی که جریان برنامه را مدیریت می‌کند.
    • مخازن را بازیابی کرده و برای هر مخزن، تعداد issueهای باز را دریافت و چاپ می‌کند.

نحوه اجرا:

  1. فایل github_repo_reporter.py را ذخیره کنید.
  2. مهم: مقدار YOUR_PERSONAL_ACCESS_TOKEN_HERE را با Personal Access Token واقعی خود جایگزین کنید.
  3. مهم: مقدار your_github_username_or_org را با نام کاربری یا نام سازمان گیت‌هاب خود جایگزین کنید.
  4. برنامه را از طریق خط فرمان اجرا کنید:
    python github_repo_reporter.py

شما باید خروجی مشابه زیر را مشاهده کنید (بسته به مخازن شما):

--- Fetching repositories for your_github_username_or_org ---
Fetching repositories for user: your_github_username_or_org
Fetched X repositories from current page. Total: Y. Moving to next page...
...
Total repositories found: Z

--- Repository Report ---

Repository: your_github_username_or_org/repo-name-1 (Public)
  Description: A sample public repository.
  Fetching open issues for repo-name-1...
  Open Issues: 2
------------------------------

Repository: your_github_username_or_org/another-private-repo (Private)
  Description: My private project.
  Fetching open issues for another-private-repo...
  Open Issues: 0
------------------------------
...
--- Report Complete ---

این مثال نه تنها عملیات خواندن اطلاعات از API را نشان می‌دهد، بلکه مفاهیم مهمی مانند صفحه‌بندی، مدیریت خطا و محدودیت نرخ را در یک سناریوی واقعی به کار می‌گیرد. این یک نقطه شروع عالی برای ساخت ابزارهای پیچیده‌تر با GitHub API است.

نتیجه‌گیری و گام‌های بعدی

در طول این آموزش جامع، ما به سفری در دنیای APIها، با تمرکز ویژه بر GitHub API RESTful، پرداختیم. از مفاهیم بنیادی REST و HTTP گرفته تا جزئیات احراز هویت با Personal Access Token، و انجام عملیات CRUD (ایجاد، خواندن، به‌روزرسانی، حذف) بر روی منابع گیت‌هاب، هر یک از این مراحل را با مثال‌های عملی و توضیحات دقیق پوشش دادیم. همچنین، اهمیت مدیریت محدودیت نرخ و صفحه‌بندی را برای اطمینان از پایداری و کارایی برنامه‌های خود درک کردیم و با نحوه پیاده‌سازی مکانیزم‌های خطایابی مناسب آشنا شدیم.

مثال عملی پیشرفته‌ای که ارائه شد، به شما نشان داد که چگونه تمام این مفاهیم را می‌توان در یک اسکریپت پایتون واقعی برای ایجاد یک ابزار کاربردی ترکیب کرد. این اسکریپت، گزارشی از وضعیت مخازن یک کاربر یا سازمان ارائه داد و به شما امکان داد تا به طور ملموس با چالش‌ها و راهکارهای کار با یک API در دنیای واقعی روبرو شوید.

تسلط بر APIها یک مهارت ضروری برای هر توسعه‌دهنده مدرن است. GitHub API به دلیل پیچیدگی‌ها و قابلیت‌های فراوانش، یک بستر آموزشی عالی برای این منظور است و مهارت‌هایی که در اینجا کسب کرده‌اید، به راحتی قابل تعمیم به سایر APIهای RESTful هستند.

گام‌های بعدی برای یادگیری بیشتر:

یادگیری API یک مسیر بی‌پایان است. در ادامه، برخی از گام‌های بعدی را پیشنهاد می‌کنیم تا دانش خود را عمیق‌تر کنید:

  1. کاوش بیشتر مستندات GitHub API: GitHub API بسیار گسترده است. به مستندات رسمی آن مراجعه کنید و Endpointsهای دیگر (مانند Pull Requests, Gists, Webhooks, GitHub Actions) را بررسی کنید. یاد بگیرید چگونه با OAuth Apps احراز هویت کنید که برای برنامه‌های عمومی که نیاز به تعامل با کاربران دیگر دارند، مناسب‌تر است.
  2. GitHub GraphQL API: GitHub علاوه بر REST API، یک GraphQL API قدرتمند نیز ارائه می‌دهد. GraphQL به شما امکان می‌دهد دقیقاً داده‌های مورد نیاز خود را در یک درخواست واحد بازیابی کنید و از دریافت اطلاعات اضافی (over-fetching) جلوگیری کنید. یادگیری GraphQL یک مهارت ارزشمند دیگر در کنار REST است.
  3. پیاده‌سازی Webhooks: Webhooks به شما امکان می‌دهند تا به رویدادهای خاصی در گیت‌هاب (مانند ایجاد یک issue جدید یا push شدن کد) به صورت لحظه‌ای واکنش نشان دهید. این قابلیت برای ساخت سیستم‌های خودکار مانند CI/CD (Continuous Integration/Continuous Delivery) بسیار مهم است.
  4. استفاده از SDKها و کتابخانه‌ها: به جای ارسال درخواست‌های خام HTTP، از SDKهای پایتون (مانند PyGithub)، جاوااسکریپت (Octokit) یا سایر زبان‌ها برای کار با GitHub API استفاده کنید. این کتابخانه‌ها بسیاری از جزئیات پیچیده مانند صفحه‌بندی، احراز هویت و مدیریت خطا را برای شما مدیریت می‌کنند و توسعه را سریع‌تر و راحت‌تر می‌سازند.
  5. پروژه‌های عملی خودتان: بهترین راه برای یادگیری، انجام پروژه‌های واقعی است. ایده‌هایی مانند:
    • ساخت یک ربات گیت‌هاب که به طور خودکار issueها را بر اساس کلمات کلیدی دسته‌بندی می‌کند.
    • توسعه یک داشبورد شخصی برای ردیابی فعالیت‌های گیت‌هاب شما.
    • نوشتن اسکریپت‌هایی برای خودکارسازی کارهای تکراری در مخازن شما (مانند آرشیو کردن مخازن قدیمی).
  6. بررسی سایر APIهای محبوب: پس از تسلط بر GitHub API، به سراغ APIهای دیگر مانند Google Maps API، Stripe API، Twitter API، Slack API یا هر API دیگری که به آن علاقه دارید بروید. اصول کار با آن‌ها مشابه است و می‌توانید دانش خود را به راحتی منتقل کنید.

امیدواریم این آموزش به شما در شروع سفرتان در دنیای APIها کمک کرده باشد. مهارت‌های برنامه‌نویسی با APIها شما را قادر می‌سازد تا قابلیت‌های بی‌پایانی را به برنامه‌های خود اضافه کنید و با سرویس‌های مختلف وب تعامل داشته باشید. با تمرین و کنجکاوی، شما به یک متخصص در این حوزه تبدیل خواهید شد.

“تسلط به برنامه‌نویسی پایتون با هوش مصنوعی: آموزش کدنویسی هوشمند با ChatGPT”

قیمت اصلی 2.290.000 ریال بود.قیمت فعلی 1.590.000 ریال است.

"تسلط به برنامه‌نویسی پایتون با هوش مصنوعی: آموزش کدنویسی هوشمند با ChatGPT"

"با شرکت در این دوره جامع و کاربردی، به راحتی مهارت‌های برنامه‌نویسی پایتون را از سطح مبتدی تا پیشرفته با کمک هوش مصنوعی ChatGPT بیاموزید. این دوره، با بیش از 6 ساعت محتوای آموزشی، شما را قادر می‌سازد تا به سرعت الگوریتم‌های پیچیده را درک کرده و اپلیکیشن‌های هوشمند ایجاد کنید. مناسب برای تمامی سطوح با زیرنویس فارسی حرفه‌ای و امکان دانلود و تماشای آنلاین."

ویژگی‌های کلیدی:

بدون نیاز به تجربه قبلی برنامه‌نویسی

زیرنویس فارسی با ترجمه حرفه‌ای

۳۰ ٪ تخفیف ویژه برای دانشجویان و دانش آموزان