3

我正在编写一个基于 socket.io 的网络摄像头流应用程序,它应该在提要超时时发出一个“streamComplete”事件。问题是,图像资源请求似乎不会发送与普通 AJAX 请求相同的标头/cookie。这似乎使 socket.io 无法使用套接字识别请求,以便以后可以告诉客户端流已完成。

在服务器端,我有一个提供 mjpeg(移动 jpeg)图像的 node.js 代理。当客户端在应用程序中选择一个提要时,DOM 中 img 元素的“src”属性会更改为指向相机提要的路径。

我查看了启用 HTML5 CORS 的图像规范,该规范似乎试图解决此问题,但据我所知,该功能在大多数浏览器中并未完全实现。如果是,我无法弄清楚如何在 node.js 端允许这些请求——每当我将 crossorigin='use-credentials' 添加到图像时,都会出现错误提示

“跨域资源共享策略拒绝了跨域图像加载。”

显然我应该能够解决这个问题,因为我控制了服务器端,但是以下节点标头规则似乎不起作用,即使它们看起来非常放松:

res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With, XMLHttpRequest, X-HTTP-Method-Override, Content-Type");
res.header('Access-Control-Allow-Methods', 'POST, GET, PUT, OPTIONS');

我考虑过的一种选择是将socketID附加到图像请求并在req.io.sockets.sockets [req.body.socketID]上注册监听器。不过,这似乎有点老套,我敢肯定会引发其他问题,例如比赛条件。这是我试图完成此操作的代码部分。

app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({secret: 'blahblahblah'}));

// Allow all cross origin requests.
app.use(allowCrossOrigin);

app.get('/streams/:cam_id/:framerate', function(req, res,next) {
    var camId = req.params.cam_id
      , framerate = req.params.framerate
      , type = (framerate === 0) ? 'jpeg' : 'mjpeg'
      , reqString = 'http://blahblah.com/feeds/'
      , proxy;

    // Query database for stream info.
    var query = new drupalInterface.Query(camId);

    // When query comes back build the URL request string and create proxy.
    query.on('results:available', function(results) {
        var reqArr = [
              results.site_name
            , results.camera_name
            , type
            , framerate
        ];

        reqString = reqString + reqArr.join('/') + '?status_frame=true&random=' + Math.random();

        // Create new proxy for current client.
        req.proxy = new MjpegProxy(reqString);

        // Make request to telepresence server.
        req.proxy.proxyRequest(req, res, next);

        // Forward to express.io route for emitting stream event info to clients.
        req.io.route('initializeProxyStream');
    });
});

app.io.route('initializeProxyStream', function(req) {
    var socket = app.io.sockets.sockets[req.query.socketID];
    // If connecting directly to /stream don't try to listen for socket connection.
    if(req.io) {
        req.proxy.once('streamComplete', function() {
            socket.emit('streamComplete');
        });
    }
});

我不确定我正在做的事情是否需要express.io,但在这种情况下似乎是有道理的。

我是否在跨域属性的正确轨道上?我缺少一些中间件吗?

4

0 回答 0