从服务器获取错误的 SSE 响应

问题描述 投票:0回答:1

使用 Django 开发项目。 DRF已安装。 后端的一些进程生成日志文件。我正在查看文件末尾的目标字符串。当目标字符串被捕获时,它必须显示在 HTML 用户页面上。一切都在动态中发生。

url.py

    path('api/log-stream/', LogStreamAPIView.as_view(), name='log_stream'),

LogStreamAPIView

class LogStreamAPIView(APIView):
    def get(self, request):
        def stream_log():
            f = subprocess.Popen(['tail', '-F', rcvenot_log], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            p = select.poll()
            p.register(f.stdout)

            while TEST_IN_PROGRESS:
                if p.poll(0.1):
                    new_line_log = f.stdout.readline().decode('utf-8').strip()
                    for target_line in RCV_SCENARIO:
                        if target_line in new_line_log:
                            yield f"event: {new_line_log}\n\n"

        return StreamingHttpResponse(stream_log(), content_type='text/event-stream')

用户 HTML 页面上的脚本

        <div style="width: 200px; height: 200px; overflow-y: scroll;">
            <ul id="logList"></ul>
        </div>

        <script>
            document.addEventListener("DOMContentLoaded", function() {
                var logList = document.getElementById('logList');

                function updateLog(newLine) {
                    var listItem = document.createElement('li');
                    listItem.textContent = newLine;
                    logList.appendChild(listItem);
                }

                var source = new EventSource('/api/log-stream/');
                source.onmessage = function(event) {
                    updateLog(event.data);
                };
            });
        </script>

我通过 API 看到了字符串

mysite.ru/api/log-stream/
。一些字符串
event: 2024.03.22 16:16:13:016[INFO ][Thread-0] ************************* - 2

但是我在 HTML 页面上没有看到它们。

在浏览器控制台中,我看到响应代码 406:

GET 127.0.0.1:8000/api/log-stream 406 (Not Acceptable)
回复见
{"detail":"The \"Accept\" request header could not be satisfied."}

我尝试过以不同的格式抛出数据

f"event: {new_line_log}\n\n"
f"data: {new_line_log}\n\n"
。没用。

尝试在

return StreamingHttpResponse(stream_log(), content_type='text/event-stream’s , status=200)
status=202
中添加状态。一样

这是浏览器控制台的一些屏幕截图。

阅读 SSE 的文档,服务器应该用

Content-Type: text/event-stream
进行响应,并且在浏览器控制台中我看到
Content-Type: application/json
。我怀疑错误是否可能在这里......

请帮忙解决问题

python html django django-rest-framework server-sent-events
1个回答
0
投票

您收到错误的原因是 Django Rest Framework 正在尝试执行内容协商。默认情况下,它会查看

DEFAULT_RENDERER_CLASSES
设置来找出它可以返回的可能内容类型,如果没有匹配的内容,则会返回 406 错误。

鉴于您的这个特定视图似乎并未真正使用任何 DRF 特定功能,您的选择之一就是简单地将其转换为不使用 DRF 的普通视图。

另一个解决方案是设置一个“自定义内容协商类”,它会忽略所有内容协商。以下是 DRF 文档中的示例:

from rest_framework.negotiation import BaseContentNegotiation class IgnoreClientContentNegotiation(BaseContentNegotiation): def select_parser(self, request, parsers): """ Select the first parser in the `.parser_classes` list. """ return parsers[0] def select_renderer(self, request, renderers, format_suffix): """ Select the first renderer in the `.renderer_classes` list. """ return (renderers[0], renderers[0].media_type)
然后您可以修改视图以将其用于内容协商:

class LogStreamAPIView(APIView): content_negotiation_class = IgnoreClientContentNegotiation # Rest of your view ...

© www.soinside.com 2019 - 2024. All rights reserved.