JSGI/ForEachStreaming

From CommonJS Spec Wiki
Jump to: navigation, search

Contents

JSGI Streaming Body Using forEach

Status: Proposed

Reference Implementation: http://github.com/kriszyp/jsgi-node

Rationale

KISS - Make it as simple as possible to return a response.

Read request input and write to the response body without buffering data without requiring extra effort on the part of the programmer.

Consistency between synchronous and asynchronous streaming of the body with backwards compatibility with JSGI 0.3.

Consistency with the API on how asynchronous actions are modeled, keeping in mind that in JSGI, response status and headers are asynchronously provided using promises.

Addition JSGI 0.3

Stream Objects

forEach-able Stream Objects are representations of a stream of data.

Methods

forEach-able Stream Objects have the following method:

Properties

Examples

Simple sync app:

app = function(request){
  return {
    status: 200,
    headers: {},
    body: ["hello", "world"]
  }
};

Streaming app, this could be sync or async, as along as "data" is a forEach-able source data structure:

app = function(request){
  return {
    status: 200,
    headers: {},
    body: {
      forEach: function(write){
        return data.forEach(function(item){
          return serialize(item);
        })
      }
    }
  }
};

Reading input:

app = function(request){
  var file = new File("fileToSave");
  var fileUpload = request.body.forEach(function(data){
    file.write(data);
  }).then(file.close);

  return fileUpload.then(function(){
    return {
      status: 200,
      headers: {},
      body: ["file successfully uploaded"]
    };
  };
};

Streaming app, where the source is an event emitter:

app = function(request){
  return {
    status: 200,
    headers: {},
    body: {
      forEach: function(write){
        var promise = new Promise();
        someEventSource.addListener("data", function(data){ write(data); });
        someEventSource.addListener("finished", function(data){ promise.resolve() });
        return promise;
      }
    }
  }
};

Middleware:

MiddleWare = function(nextApp){
  return function(request){
    var response = nextApp(request);
    var inBody = response.body;
    response.body = {
      forEach: function(write){
        return inBody.forEach(function(block){
          return modify(block);
        })
      }
    }
    return response;
  }
};
Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox