انتقل إلى المحتوى الرئيسي

معالجة الأخطاء

تستخدم واجهة TakeTheme البرمجية رموز استجابة HTTP المتعارف عليها للدلالة على نجاح الطلبات أو فشلها. ويشرح هذا الدليل صيغ استجابات الأخطاء وأفضل الممارسات للتعامل معها.

رموز حالة HTTP

نطاق الرمزالمعنى
2xxنجاح — اكتمل الطلب بنجاح
4xxخطأ من العميل — هناك مشكلة في طلبك
5xxخطأ من الخادم — حدث خلل لدينا

رموز الحالة الشائعة

الرمزالحالةالوصف
200OKنجح الطلب
201Createdأُنشئ المورد بنجاح
204No Contentنجح الطلب دون إعادة محتوى
400Bad Requestمعاملات طلب غير صالحة
401Unauthorizedمصادقة مفقودة أو غير صالحة
403Forbiddenصلاحيات غير كافية
404Not Foundالمورد غير موجود
409Conflictتعارض في حالة المورد
429Too Many Requestsتجاوز حد المعدل
500Internal Server Errorخطأ من جانب الخادم
503Service Unavailableانقطاع مؤقت

صيغة استجابة الخطأ

تتبع كل الأخطاء بنية JSON بسيطة تضم الحقلين status وmessage:

{
"status": 400,
"message": "\"email\" is required"
}

حقول كائن الخطأ

الحقلالنوعالوصف
statusرقمرمز حالة HTTP
messageنصوصف الخطأ بصيغة مقروءة

وقد تتضمن بعض استجابات الأخطاء حقولًا إضافية حسب نوع الخطأ.

أنواع الأخطاء

أخطاء المصادقة

عند فشل المصادقة بمفتاح الـ API:

{
"status": 401,
"message": "API key is required. Provide it via tt-api-key header or Authorization: Bearer header"
}

صيغة مفتاح غير صالحة:

{
"status": 401,
"message": "API key must start with tt_ prefix"
}

مفتاح مُبطل أو غير صالح:

{
"status": 401,
"message": "API key not found or has been revoked"
}

مفتاح منتهي الصلاحية:

{
"status": 401,
"message": "API key has expired"
}

أخطاء التفويض

صلاحيات غير كافية:

{
"status": 403,
"message": "API key does not have access to PRODUCTS"
}

الإجراء المطلوب غير ممنوح:

{
"status": 403,
"message": "API key cannot perform WRITE on PRODUCTS"
}

عنوان IP غير مدرج في القائمة المسموحة:

{
"status": 403,
"message": "Your IP address is not authorized to use this API key"
}

أخطاء التحقق

عند فشل التحقق من الطلب:

{
"status": 400,
"message": "\"email\" must be a valid email"
}
{
"status": 400,
"message": "\"price\" must be greater than or equal to 0"
}

أخطاء عدم الوجود

عندما لا يوجد المورد أو المسار:

{
"name": "Resource not found",
"message": "The page you are trying to access does not exist"
}

أخطاء حد المعدل

عند تجاوز حد المعدل:

{
"message": "Rate limit exceeded",
"code": "RATE_LIMIT_EXCEEDED",
"status": 429
}

أخطاء الخادم

عند وقوع خطأ داخلي في الخادم:

{
"status": 500,
"message": "INTERNAL_SERVER_ERROR"
}

أخطاء التكرار

عند محاولة إنشاء مورد موجود بالفعل:

{
"status": 400,
"message": "slug and storeId combination with my-product and 65abc123def already exists."
}

التعامل مع الأخطاء

JavaScript/TypeScript

interface ApiError {
status: number;
message: string;
code?: string;
name?: string;
}

async function apiRequest<T>(
endpoint: string,
options?: RequestInit
): Promise<T> {
const response = await fetch(`https://api.taketheme.com/api/v1${endpoint}`, {
...options,
headers: {
"tt-api-key": API_KEY,
"Content-Type": "application/json",
...options?.headers,
},
});

const data = await response.json();

if (!response.ok) {
const error = data as ApiError;

switch (response.status) {
case 401:
throw new AuthenticationError(error.message);
case 403:
throw new ForbiddenError(error.message);
case 404:
throw new NotFoundError(error.message || error.name);
case 429:
throw new RateLimitError(error.message);
default:
throw new ApiError(error.message, error.status);
}
}

return data as T;
}

// Usage
try {
const product = await apiRequest("/products/prod_123");
} catch (error) {
if (error instanceof RateLimitError) {
// Wait and retry
await sleep(60000);
// Retry request...
} else if (error instanceof NotFoundError) {
console.log("Product not found");
} else if (error instanceof AuthenticationError) {
console.log("Check your API key");
} else {
console.error("Unexpected error:", error.message);
}
}

Python

import requests
from typing import Optional

class ApiError(Exception):
def __init__(self, message: str, status: int):
super().__init__(message)
self.message = message
self.status = status

class AuthenticationError(ApiError):
pass

class ForbiddenError(ApiError):
pass

class NotFoundError(ApiError):
pass

class RateLimitError(ApiError):
pass

def api_request(endpoint: str, method: str = 'GET', data: Optional[dict] = None) -> dict:
response = requests.request(
method,
f'https://api.taketheme.com/api/v1{endpoint}',
headers={
'tt-api-key': API_KEY,
'Content-Type': 'application/json'
},
json=data
)

result = response.json()

if not response.ok:
message = result.get('message', result.get('name', 'Unknown error'))
status = result.get('status', response.status_code)

if response.status_code == 401:
raise AuthenticationError(message, status)
elif response.status_code == 403:
raise ForbiddenError(message, status)
elif response.status_code == 404:
raise NotFoundError(message, status)
elif response.status_code == 429:
raise RateLimitError(message, status)
else:
raise ApiError(message, status)

return result

# Usage
try:
product = api_request('/products/prod_123')
except RateLimitError as e:
import time
time.sleep(60)
# Retry request...
except NotFoundError as e:
print("Product not found")
except AuthenticationError as e:
print("Check your API key")
except ApiError as e:
print(f"Error: {e.message} (Status: {e.status})")

مرجع رموز الأخطاء

المصادقة والتفويض

رسالة الخطأالرمزالوصف
API key is required...401لم يُقدَّم مفتاح API
API key must start with tt_ prefix401صيغة مفتاح غير صالحة
API key not found or has been revoked401المفتاح غير موجود أو مُبطل
API key has expired401المفتاح تجاوز تاريخ انتهائه
API key usage limit has been reached429استُنفدت حصة الاستخدام
API key does not have access to [RESOURCE]403صلاحية المورد غير ممنوحة
API key cannot perform [ACTION] on [RESOURCE]403إذن الإجراء غير ممنوح
Your IP address is not authorized...403عنوان IP خارج القائمة المسموحة

حدود المعدل

رسالة الخطأالشيفرةالرمزالوصف
Rate limit exceededRATE_LIMIT_EXCEEDED429طلبات أكثر من اللازم

التحقق

تُولَّد رسائل أخطاء التحقق من مخطط الطلب وتصف بدقة الحقل الذي فشل وسبب فشله. ومن الأنماط الشائعة:

النمطالوصف
"[field]" is requiredحقل مطلوب مفقود
"[field]" must be a valid emailصيغة بريد غير صالحة
"[field]" must be greater than [value]القيمة دون الحد الأدنى
"[field]" must be less than [value]القيمة تتجاوز الحد الأقصى
"[field]" must be one of [values]قيمة غير مسموحة في القائمة
"[field]" must be a stringنوع بيانات خاطئ

الموارد

رسالة الخطأالرمزالوصف
The page you are trying to access does not exist404المسار أو المورد غير موجود
[field] combination with [values] already exists.400إدخال مكرر

أفضل الممارسات

1. تحقّق دائمًا من الأخطاء

// ✗ Bad: Ignoring potential errors
const { data } = await fetch("/products");
renderProducts(data);

// ✓ Good: Handling errors explicitly
const response = await fetch("/products");
if (!response.ok) {
const error = await response.json();
console.error("Error:", error.message);
return;
}
const { data } = await response.json();
renderProducts(data);

2. تعامل مع اختلاف رموز الحالة

async function handleApiError(response) {
const error = await response.json();

switch (response.status) {
case 400:
return `Validation error: ${error.message}`;
case 401:
return `Authentication failed: ${error.message}`;
case 403:
return `Permission denied: ${error.message}`;
case 404:
return "Resource not found";
case 429:
return "Rate limit exceeded. Please wait before retrying.";
case 500:
return "Server error. Please try again later.";
default:
return error.message || "An unexpected error occurred";
}
}

3. اعرض رسائل مفهومة للمستخدم

function getUserMessage(error) {
// Don't expose internal error details to users
if (error.status >= 500) {
return "Something went wrong. Please try again later.";
}

if (error.status === 429) {
return "Too many requests. Please wait a moment.";
}

// For client errors, the message is usually safe to show
return error.message;
}

4. طبّق إعادة المحاولة للأخطاء العابرة

async function fetchWithRetry(endpoint, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await apiRequest(endpoint);
return response;
} catch (error) {
// Only retry on server errors or rate limits
if (error.status !== 500 && error.status !== 503 && error.status !== 429) {
throw error; // Don't retry client errors
}

// Exponential backoff
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw new Error("Max retries exceeded");
}

اقرأ أيضًا