كيفية بث استجابات API باستخدام أحداث مرسلة من الخادم (SSE)؟

Ashley Innocent

Ashley Innocent

13 مارس 2026

كيفية بث استجابات API باستخدام أحداث مرسلة من الخادم (SSE)؟

موجز

استخدم الأحداث المرسلة من الخادم (SSE) لتدفق استجابات واجهة برمجة التطبيقات عبر HTTP. أرسل Content-Type: text/event-stream واكتب الأحداث كـ data: {json}\n\n. تعمل SSE لتدفق استجابات الذكاء الاصطناعي، وتحديثات التقدم، والموجزات المباشرة. تستخدم واجهة برمجة تطبيقات متجر الحيوانات الأليفة الحديثة (Modern PetstoreAPI) SSE لتوصيات الحيوانات الأليفة بالذكاء الاصطناعي وتحديثات حالة الطلب.

مقدمة

تُنشئ واجهة برمجة التطبيقات الخاصة بك توصيات حيوانات أليفة بالذكاء الاصطناعي. تستغرق الاستجابة 10 ثوانٍ. هل تجعل المستخدمين ينتظرون، أم تدفق النتائج فور إنشائها؟

باستخدام الأحداث المرسلة من الخادم (SSE)، يمكنك تدفق الاستجابات في الوقت الفعلي. يرى المستخدمون النتائج فورًا عند إنشائها بواسطة الذكاء الاصطناعي، مما يخلق تجربة أفضل.

تستخدم واجهة برمجة تطبيقات متجر الحيوانات الأليفة الحديثة الأحداث المرسلة من الخادم (SSE) لتوصيات الحيوانات الأليفة بالذكاء الاصطناعي، وتحديثات حالة الطلب، وتغييرات المخزون.

إذا كنت تختبر واجهات برمجة التطبيقات المتدفقة، فإن Apidog يدعم اختبار SSE والتحقق منها.

button

أساسيات SSE

تعتبر SSE تدفقًا أحادي الاتجاه يعتمد على HTTP من الخادم إلى العميل.

تنسيق SSE

Content-Type: text/event-stream
Cache-Control: no-cache

data: {"message":"First chunk"}\n\n
data: {"message":"Second chunk"}\n\n
data: {"message":"Third chunk"}\n\n

كل حدث:

الأحداث المسماة

event: recommendation
data: {"petId":"019b4132","score":0.95}

event: recommendation
data: {"petId":"019b4127","score":0.89}

event: complete
data: {"total":2}

معرفات الأحداث

id: 1
data: {"message":"First"}

id: 2
data: {"message":"Second"}

يمكن للعميل استئناف الاتصال من آخر معرف إذا انقطع الاتصال.

تطبيق خادم SSE

مثال Node.js/Express

app.get('/v1/pets/recommendations/stream', async (req, res) => {
  // Set SSE headers
  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');

  // Send recommendations as they're generated
  const recommendations = await generateRecommendations(req.query.userId);

  for (const rec of recommendations) {
    res.write(`data: ${JSON.stringify(rec)}\n\n`);
    await sleep(100); // Simulate streaming delay
  }

  // Send completion event
  res.write(`event: complete\ndata: {"total":${recommendations.length}}\n\n`);
  res.end();
});

مثال Python/FastAPI

from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import json
import asyncio

app = FastAPI()

@app.get("/v1/pets/recommendations/stream")
async def stream_recommendations(user_id: str):
    async def generate():
        recommendations = await get_recommendations(user_id)

        for rec in recommendations:
            yield f"data: {json.dumps(rec)}\n\n"
            await asyncio.sleep(0.1)

        yield f"event: complete\ndata: {json.dumps({'total': len(recommendations)})}\n\n"

    return StreamingResponse(
        generate(),
        media_type="text/event-stream",
        headers={
            "Cache-Control": "no-cache",
            "Connection": "keep-alive"
        }
    )

تطبيق عميل SSE

جافاسكريبت/المتصفح

const eventSource = new EventSource(
  'https://petstoreapi.com/v1/pets/recommendations/stream?userId=user-456'
);

eventSource.onmessage = (event) => {
  const data = JSON.parse(event.data);
  displayRecommendation(data);
};

eventSource.addEventListener('complete', (event) => {
  const data = JSON.parse(event.data);
  console.log(`Received ${data.total} recommendations`);
  eventSource.close();
});

eventSource.onerror = (error) => {
  console.error('SSE error:', error);
  eventSource.close();
};

خطاف React (React Hook)

import { useEffect, useState } from 'react';

function useSSE(url) {
  const [data, setData] = useState([]);
  const [complete, setComplete] = useState(false);

  useEffect(() => {
    const eventSource = new EventSource(url);

    eventSource.onmessage = (event) => {
      const item = JSON.parse(event.data);
      setData(prev => [...prev, item]);
    };

    eventSource.addEventListener('complete', () => {
      setComplete(true);
      eventSource.close();
    });

    return () => eventSource.close();
  }, [url]);

  return { data, complete };
}

// الاستخدام
function Recommendations({ userId }) {
  const { data, complete } = useSSE(
    `https://petstoreapi.com/v1/pets/recommendations/stream?userId=${userId}`
  );

  return (
    <div>
      {data.map(rec => (
        <PetCard key={rec.petId} pet={rec} />
      ))}
      {!complete && <Spinner />}
    </div>
  );
}

كيف تستخدم Modern PetstoreAPI تقنية SSE

توصيات الحيوانات الأليفة بالذكاء الاصطناعي

تدفق التوصيات التي أنشأها الذكاء الاصطناعي:

GET /v1/pets/recommendations/stream?userId=user-456
Accept: text/event-stream

event: recommendation
data: {"petId":"019b4132","name":"Fluffy","score":0.95,"reason":"Matches your preference for cats"}

event: recommendation
data: {"petId":"019b4127","name":"Buddy","score":0.89,"reason":"Similar to pets you liked"}

event: complete
data: {"total":2,"processingTime":850}

تحديثات حالة الطلب

تدفق خطوات معالجة الطلب:

GET /v1/orders/019b4132/status/stream
Accept: text/event-stream

data: {"status":"payment_processing","timestamp":"2026-03-13T10:30:00Z"}

data: {"status":"payment_confirmed","timestamp":"2026-03-13T10:30:02Z"}

data: {"status":"preparing_shipment","timestamp":"2026-03-13T10:30:05Z"}

event: complete
data: {"status":"shipped","trackingNumber":"1Z999AA10123456784"}

تغييرات المخزون

تدفق تحديثات المخزون في الوقت الفعلي:

GET /v1/inventory/stream
Accept: text/event-stream

event: stock-change
data: {"petId":"019b4132","oldStock":5,"newStock":4}

event: price-change
data: {"petId":"019b4127","oldPrice":299.99,"newPrice":279.99}

انظر وثائق Modern PetstoreAPI SSE.

اختبار SSE باستخدام Apidog

Apidog يدعم اختبار SSE:

  1. إنشاء طلب SSE
  2. تعيين Accept: text/event-stream
  3. الاتصال وعرض الأحداث في الوقت الفعلي
  4. التحقق من صحة تنسيق الحدث
  5. اختبار إعادة الاتصال

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

1. تعيين رؤوس (Headers) مناسبة

res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
res.setHeader('X-Accel-Buffering', 'no'); // Disable nginx buffering

2. إرسال نبضات القلب (Heartbeats)

للحفاظ على الاتصال نشطًا:

const heartbeat = setInterval(() => {
  res.write(': heartbeat\n\n');
}, 15000);

res.on('close', () => clearInterval(heartbeat));

3. التعامل مع الأخطاء برشاقة

eventSource.onerror = (error) => {
  if (eventSource.readyState === EventSource.CLOSED) {
    // Connection closed, will auto-reconnect
  } else {
    // Other error
    console.error('SSE error:', error);
  }
};

4. استخدام معرفات الأحداث للاستئناف

let lastEventId = 0;

app.get('/stream', (req, res) => {
  const startId = parseInt(req.headers['last-event-id'] || '0');

  for (let i = startId + 1; i <= 100; i++) {
    res.write(`id: ${i}\ndata: {"message":"Event ${i}"}\n\n`);
  }
});

5. إغلاق الاتصالات

// العميل
eventSource.addEventListener('complete', () => {
  eventSource.close();
});

// الخادم
res.on('close', () => {
  // Cleanup resources
});

الخاتمة

SSE مثالية لتدفق استجابات واجهة برمجة التطبيقات. إنها أبسط من WebSocket للاتصال أحادي الاتجاه، وتعمل عبر HTTP، وتتعامل مع إعادة الاتصال تلقائيًا.

تستخدم واجهة برمجة تطبيقات متجر الحيوانات الأليفة الحديثة SSE لتدفق الذكاء الاصطناعي، وتحديثات الطلبات، والموجزات المباشرة. اختبر نقاط نهاية SSE باستخدام Apidog.

الأسئلة الشائعة

هل يمكن لـ SSE العمل عبر جدران الحماية للشركات؟

نعم، تستخدم SSE بروتوكول HTTP/HTTPS القياسي، لذا فهي تعمل عبر معظم جدران الحماية والوكلاء (proxies).

كم من الوقت يمكن أن تظل اتصالات SSE مفتوحة؟

إلى أجل غير مسمى، ولكن استخدم "نبضات القلب" كل 15-30 ثانية للحفاظ على الاتصالات نشطة عبر الوكلاء.

هل يمكنني إرسال بيانات ثنائية عبر SSE؟

لا، SSE مخصصة للنص فقط. قم بتشفير البيانات الثنائية باستخدام Base64 أو استخدم WebSocket بدلاً من ذلك.

هل تدعم SSE الاتصال ثنائي الاتجاه؟

لا، SSE هي من الخادم إلى العميل فقط. يستخدم العملاء طلبات HTTP العادية للاتصال من العميل إلى الخادم.

كم عدد اتصالات SSE التي يمكن أن يمتلكها المتصفح؟

تحد المتصفحات عدد اتصالات SSE لكل نطاق (عادةً 6). استخدم التعدد (multiplexing) أو WebSocket للعديد من الاتصالات.

ممارسة تصميم API في Apidog

اكتشف طريقة أسهل لبناء واستخدام واجهات برمجة التطبيقات