是否可以将服务器端事件用于新的 POST 处理程序?我有一个很长的服务器端进程,并且想同时向客户端返回一些事件更新?
简单的回答是否定的,因为SSE不支持POST,只支持GET。 (参见https://stackoverflow.com/a/34285526/841830)
import { Handlers } from "$fresh/server.ts";
import { ServerSentEventStream } from "https://deno.land/[email protected]/http/server_sent_event_stream.ts";
export const handler: Handlers = {
async POST(req: Request) {
const payload = await req.json()
// todo: can check payload / auth check here
// if you use client npm package "fetch-event-source"
/*
if (!authorized) {
return Response.json({
message: 'not allowed'
}, { status: 403 })
}
*/
const db = await Deno.openKv()
return new Response(new ReadableStream({
async start(controller) {
for await (const [{ value: message }] of db.watch([['your-key']])) {
controller.enqueue({
data: JSON.stringify(message),
id: Date.now(),
event: 'message'
})
}
},
cancel() {
console.log('cancel')
},
}).pipeThrough(new ServerSentEventStream()), {
headers: {
"Content-Type": "text/event-stream",
},
})
}
}
建议在客户端使用 npm
fetch-event-source
,因为它允许标头。像这样采购:
import { fetchEventSource } from "https://esm.sh/@microsoft/[email protected]"
为我工作。然后我可以使用标头调用它并设置授权等。
fetchEventSource('/api/listen',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${session?.access_token}`
},
body: JSON.stringify({
whatever: 123
}),
onopen(resp: Response) {
console.log('on open')
return Promise.resolve()
},
onmessage(ev) {
console.log('on message', ev)
},
onclose() {
console.log('on close')
},
onerror(err) {
console.log('on error', err)
}
})
}