Skip to content

Instantly share code, notes, and snippets.

@maietta
Created July 31, 2024 23:53
Show Gist options
  • Save maietta/69f07388f1d62934f52420acfe495146 to your computer and use it in GitHub Desktop.
Save maietta/69f07388f1d62934f52420acfe495146 to your computer and use it in GitHub Desktop.
Proxy SSE data streams in SvelteKit
<script lang="ts">
import { onMount } from 'svelte';
import { writable } from 'svelte/store';
// Define the type for your message objects
interface Message {
now: number;
created_at: string;
// Add any other properties your message might have
}
// Create the writable store with the correct type
const messages = writable<Message[]>([]);
onMount(() => {
const evtSource = new EventSource('/sse'); // Point to path
evtSource.onmessage = function (event) {
try {
// Remove 'data: ' prefix and parse the JSON
const dataString = event.data.replace(/^data: /, '');
const dataobj: Message = JSON.parse(dataString);
messages.update((arr) => [...arr, dataobj]);
} catch (e) {
console.error('Failed to parse message:', e);
}
};
return () => {
evtSource.close();
};
});
</script>
{#each $messages as m}
{m.now} - {m.created_at} <br />
{/each}
import type { RequestHandler } from '@sveltejs/kit';
export const GET: RequestHandler = async () => {
const response = await fetch('https://sse.dev/test');
if (!response.body) {
return new Response('No body in response', { status: 500 });
}
const reader = response.body.getReader();
const decoder = new TextDecoder('utf-8');
const encoder = new TextEncoder();
const stream = new ReadableStream({
async start(controller) {
try {
while (true) {
const { done, value } = await reader.read();
if (done) {
controller.close();
break;
}
const text = decoder.decode(value, { stream: true });
// Ensure each event data is prefixed with 'data: ' and followed by '\n\n'
const data = `data: ${text}\n\n`;
controller.enqueue(encoder.encode(data));
}
} catch (error) {
console.error('Stream reading error:', error);
controller.error(error);
}
},
cancel() {
console.log('Stream canceled');
}
});
return new Response(stream, {
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
Connection: 'keep-alive'
}
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment