[英]How to setup cherrypy server sent events
我正在開發一個簡單的Web應用程序,該應用程序已完成了Angular和Cherrypy(目前是原型)。 我正在上傳兩個文件,然后使用子進程(popen)在cherrypy中調用外部python程序來處理它們。 到目前為止,我已經能夠做到。 我要實現的是傳遞給客戶端的外部程序(我通過popen捕獲)的輸出。 我的問題是,我試圖在cherrypy上設置服務器發送的事件,但沒有成功。
這是我要公開的cherrypy方法(來自網絡的一個示例):
@cherrypy.expose
def getUpdate(self):
#Set the expected headers...
cherrypy.response.headers["Content-Type"] = "text/event-stream;charset=utf-8"
def content():
yield "Hello,"
yield "world"
return content()
這是javascript客戶端代碼(我啟用了CORS並且可以正常工作):
var sseEvent = new EventSource('http://localhost:8090/getUpdate');
sseEvent.onmessage = function (event) {
console.log(event);
};
sseEvent.onopen = function (event) {
//console.log("I have started...");
};
我已經看過這個問題,並在這個博客中 。 但是,從服務器端調用函數時,EventSource對象上的onmessage事件未觸發。 我的理解是,您可以從服務器端調用該函數,它將捕獲來自瀏覽器的事件。 我錯了或者設置錯了?
因此,我發現使用SSE時,我需要以特定格式發送數據。 即
或json
data: "{\\n data: "msg" : "foo", \\n data: "id" : "boo", \\n data: "}\\n\\n
我想要的是一種重試格式,以在n秒后繼續輪詢服務器。 因此,cherrypy函數現在是:
@cherrypy.expose
def getUpdate(self, _=None):
cherrypy.response.headers["Content-Type"] = "text/event-stream;charset=utf-8"
if _:
data = 'retry: 200\ndata: ' + str( self.prog_output) + '\n\n'
return data
else:
def content():
data = 'retry: 200\ndata: ' + str( self.prog_output) + '\n\n'
return data
return content()
getUpdate._cp_config = {'response.stream': True, 'tools.encode.encoding':'utf-8'}
,現在發送的消息帶有
“重試:n微秒”
這將每n微秒發送一次數據。 現在,EventSource onmessage事件被觸發,我很高興地從服務器發送的程序中讀取輸出。 :)
上SSE的好書(在許多帖子中都提到過): 這里
為了補充這個自我回答的問題,我制作了這個功能齊全的示例,其中包含兩個文件。
該文檔非常有幫助。
祝大家開心!
的index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>title</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div>server-sent events</div>
<h3>sse_handler.onmessage()</h3>
<ul id="sse_message"></ul>
<script>
// create a sse handler
var sse_handler = new EventSource('http://localhost:8080/getUpdate');
sse_handler.onmessage = function (event) {
console.log("-- sse_handler.onmessage()", event);
/* the onmessage method catch all generic message, those with no event field
*/
var h_ul = document.getElementById('sse_message');
var h_li = document.createElement("li");
h_li.innerHTML = event.data;
h_ul.appendChild(h_li);
};
sse_handler.onopen = function (event) {
console.log("-- sse_handler.onopen()", event);
};
</script>
</body>
</html>
和server.py
#!/usr/bin/env python3
import datetime
import cherrypy
from pathlib import Path
class TestServerSentEvent(object):
@cherrypy.expose
def index(self):
return Path("index.html").read_text()
@cherrypy.expose
def getUpdate(self, * pos, ** nam):
cherrypy.response.headers["Content-Type"] = "text/event-stream;charset=utf-8"
return 'retry: 1200\ndata: {0}\n\n'.format(self.output())
def output(self) :
d = datetime.datetime.now()
return f"TEST - {d}"
getUpdate._cp_config = {'response.stream': True, 'tools.encode.encoding':'utf-8'}
if __name__ == '__main__':
cherrypy.quickstart(TestServerSentEvent())
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.