可以通过 POST 使用 EventSource 传递参数的服务器发送事件 (SSE)

Posted

技术标签:

【中文标题】可以通过 POST 使用 EventSource 传递参数的服务器发送事件 (SSE)【英文标题】:Can Server Sent Events (SSE) with EventSource pass parameter by POST 【发布时间】:2016-03-19 15:10:41 【问题描述】:

我正在使用 html5 服务器发送事件。服务器端是 Java Servlet。 我有一个 json 数组数据想要传递给服务器。

var source = new EventSource("../GetPointVal?id=100&jsondata=" + JSON.stringify(data));

如果数组大小很小,服务器端可以获取查询字符串。 但是如果数组大小很大。 (可能超过数千个字符),服务器无法获取查询字符串。 是否可以在new EventSource(...) 中使用 POST 方法将 json 数组传递给可以避免查询字符串长度限制的服务器?

【问题讨论】:

【参考方案1】:

不,SSE 标准不允许 POST。

(据我所知,没有技术原因 - 我认为只是设计人员从未见过用例:这不仅仅是大数据,而且如果您想进行自定义身份验证方案有安全原因不将密码放入 GET 数据中。)

XMLHttpRequest(即 AJAX)确实允许 POST,因此一种选择是回到旧的长轮询/彗星方法。 (我的书 Data Push Apps with HTML5 SSE 详细介绍了如何做到这一点。)

另一种方法是预先将POST中的所有数据存储在HttpSession中,然后调用可以使用该会话数据的SSE进程。 (SSE 确实支持 cookie,所以 JSESSIONID cookie 应该可以正常工作。)

附: standard 没有明确表示不能使用 POST。但是,与XMLHttpRequest不同的是,没有参数来指定要使用的http方法,也没有办法指定要发布的数据。

【讨论】:

“我认为只是设计人员从未见过用例”如果您想上传文件并获得完成服务器端处理的进度,则另一种。 我 90% 的 SSE 用例是 POST。在服务器上创建某种需要时间来处理的资源。 @BryanLarsen 看起来是一个错误的设计,如果你想向服务器发送一些数据,你应该使用 fetch 或 AJAX Api,HTTP2 效率更高,因为如果你有连接会被重用一个sse打开。请记住,当 sse 请求连接时,cookie 也会被发送,因此您可以识别您的客户端 @JohnBalvinArias 我不想向服务器发送数据,我想在服务器上处理一些数据,并让它向我发送进度通知和结果。 @JohnBalvinArias 由于 bryanLarsen 不是最初的提问者,而且这偏离了主题(即网络应用程序的设计模式),因此可能应该将其用于聊天。【参考方案2】:

或者,您可以从使用另一个 php 自定义的文件中读取数据

http://..../command_receiver.php?command=blablabla

command_receiver.php

<?php
$cmd = $_GET['command'];
$fh = fopen("command.txt","w");
fwrite($fh, $cmd);
fclose($fh);
?>

demo2_sse.php

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

//$a = $_GET["what"];
$time = microtime(true); //date('r');

$fa = fopen("command.txt", "r");
$content = fread($fa,filesize("command.txt"));
fclose($fa);

echo "data: [$content][$time]\n\n";
flush();
?>

并且 EventSource 包含在任意命名的 html 中,如下所示

<!DOCTYPE html>
<html>
<body>
<h1>Getting server updates</h1>
var source = new EventSource("demo2_sse.php");
source.onmessage = function (event) 
        mycommand = event.data.substring(1, event.data.indexOf("]"));
       mytime = event.data.substring(event.data.lastIndexOf("[") + 1, event.data.lastIndexOf("]"));

</script>
</body>
</html>

【讨论】:

【参考方案3】:

虽然您不能使用 EventSource API 来执行此操作,但服务器无法实现 POST 请求并没有技术原因。诀窍是让客户端发送请求。例如 This answer discusses sse.js 作为 EventSource 的替代品。

【讨论】:

以上是关于可以通过 POST 使用 EventSource 传递参数的服务器发送事件 (SSE)的主要内容,如果未能解决你的问题,请参考以下文章

EventSource / 服务器通过 Nginx 发送的事件

如何使用 Windows 性能分析器查看 EventSource 创建的 ETW 事件?

服务器发送事件; `EventSource.onmessage`没有触发

所有事件的 HTML5 EventSource 侦听器?

Azure SDK 2.6 中缺少 ETW EventSource 表

EventSource 与轮询 ajax 的效率/开销?