1

我有一个使用 expressjs 实现的 Web 服务器 api,它在 REST api 处提供用于记录连接到 Web 服务器机器的网络摄像机。

网络摄像头和编码使用 C++ 编写的 dll 处理,互操作使用node-ffi库完成。

我遇到的问题是我在响应中混合了原生 ffi 句柄和 JSON 字符串化。

例如,我有一个Stream带有原型的类:

Stream.prototype.id = '';
Stream.prototype.url = '':
Stream.prototype.parent = null;
Stream.prototype.filePtr = null;

哪里Stream.filePtr将包含一个 ffi 句柄,例如ref.refType(ref.types.void)

然后在我的 expressjs POSTstart调用中,我执行以下操作:

impl.start = function(req, res){
    var camera = cameras.find(function(camera) {
        return camera.id === req.params.camera;
    });

    res.send(camera.startStream()); // startStream returns a new 'Stream' object.
};

如您所见,我只是将Stream对象按原样发送到响应中。这就是我通常实现 REST API 的方式。问题是filePtr不应真正包含本机句柄,我不确定最佳实践是什么,或者我是否在做一些根本错误的事情?

注意:一般来说,我是 web、nodejs、expressjs 和 javascript 的新手。因此,如果我正在做的事情没有意义或可以做得更好,请指出。

一个更完整的例子:

// dll bindings

var fileType = ref.types.void;
var filePtrType = ref.refType(fileType);
var cameraType = ref.types.void;
var cameraPtrType = ref.refType(cameraType);

var myLib = ffi.Library(/* Stuff */):

// expressjs api definitions

app.post('api/cameras/:camera/streams', impl.start);
app.delete('api/cameras/:camera/streams/:stream', impl.stop);
app.get('api/cameras', impl.cameras);
app.get('api/cameras/:camera', impl.camera);
app.get('api/cameras/:camera/streams', impl.streams);
app.get('api/cameras/:camera/streams/:stream', impl.stream);

// objects definitions

function Stream() {
    this.id = Date.now();
    this.url = this.id + '.mp4';
};

Stream.prototype.id = '';
Stream.prototype.url = '':
Stream.prototype.parent = null;
Stream.prototype.filePtr = null;

function Camera(id, device){
    this.id = id;
    this.device = device;
    this.cameraPtr = myLib.openCamera(device);  
};

Camera.prototype.id = '';
Camera.prototype.device = 0;
Camera.prototype.cameraPtr = null;

Camera.prototype.startStream = function() {
    var stream = new Stream(this);
    stream.filePtr = myLib.openFile(this.cameraPtr, stream.url);
    return stream;
};

Camera.prototype.stopStream = function(stream) {
    myLib.closeFile(stream.filePtr);
    this.streams.slice(this.streams.indexOf(stream), 1);
};

// object declaration

var cameras = [];

var numCameras = myLib.num_cameras();

for (var n = 0; n < numCameras; ++n) {
    cameras.push(new Camera(n, n));
}

// express api implementation

var impl = {};

impl.streams = function(req, res) {
    var camera = cameras.find(function(camera) {
        return camera.id === req.params.camera;
    });
    res.send(camera.streams);
};

impl.start = function(req, res){
    var camera = cameras.find(function(camera) {
        return camera.id === req.params.camera;
    });

    res.send(camera.startStream());
};

impl.stop = function(req. res) {
    var camera = cameras.find(function(camera){
        return camera.id === req.params.camera;
    });
    var stream = camera.streams.find(function(stream) {
        return stream.id === req.params.stream:
    });
    camera.stopStream(stream);
};

/* Stuff */
4

1 回答 1

1

我相信您希望将流数据通过管道传递给响应,而不是直接返回流。尝试这个。这是有关管道的文档。

var readableStream = camera.startStream();
readableStream.pipe(res);

编辑

好吧,实际上,您可能不想在数据用完后立即结束 writableStream(响应是 writableStream)(因为您正在流式传输),所以如果上述方法不起作用,请尝试以下操作:

   var readableStream = camera.startStream();
   readableStream.on('data', function(chunk) {
     res.write(chunk);
   })

其他想法

如果您想一次返回多个流,您可能需要为每个流分别发出 http 请求。一次返回多个流(除非你做了一些非常聪明的事情)可能只会发回一堆混杂的数据。

尝试回答实际问题

当客户端请求流时,显然您不能将原始数据作为 JSON 返回,因为 JSON 不允许这样做。我建议当客户端请求流资源时返回客户端应请求的资源位置(URL)。我相信这是正确的 REST 方式,但我不是这方面的专家。这就是交互的方式:

客户:(通过 GET)请给我流

服务器:响应(json)这里是你需要去的地方(加上元数据[可选])

客户:请给我 jsonResponse.streamURL

服务器:(响应的流)....

于 2014-04-03T12:34:02.933 回答