可以通过 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`没有触发