Skip to content

Instantly share code, notes, and snippets.

@kraih
Created March 10, 2012 13:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kraih/2011353 to your computer and use it in GitHub Desktop.
Save kraih/2011353 to your computer and use it in GitHub Desktop.
# StreamingPSGI - Everything is streaming, no special cases
my $env = {
SERVER_NAME => 'localhost',
SERVER_PORT => 80,
SCRIPT_NAME => '',
REQUEST_METHOD => 'GET',
HTTP_CONTENT_LENGTH => 12,
version => 3,
url_scheme => 'http',
read => sub {...},
status => sub {...},
write => sub {...}
};
# Streaming application
my $app = sub {
my $env = shift;
# Request body
my $input = '';
$env->{read} = sub {
my $chunk = shift;
return $input .= $chunk if defined $chunk;
# Response
my $output = "echo: $input";
$env->{status}->(200, 'OK', ['Content-Length' => length($output)]);
$env->{write}->($output);
};
};
# Streaming middleware
my $middleware = sub {
my ($env, $next) = @_;
# Response body
my $write = $env->{write};
$env->{write} = sub {
my $chunk = shift;
say "OUTPUT CHUNK: $chunk";
return $write->($chunk);
};
# Forward to next middleware
$next->();
# Request body
my $read = $env->{read};
$env->{read} = sub {
my $chunk = shift;
say "INPUT CHUNK: $chunk";
return $read->($chunk);
};
};
@judofyr
Copy link

judofyr commented Mar 15, 2012

Ruby version:

env = {
  :read => proc { },
  :write => proc { },
  :status => proc { }
}

app = proc do |env|
  input = ""
  read = env[:read]
  env[:read] = proc do
    # Chunking
    chunk = read.call
    return input << chunk if chunk

    # Response
    body = "Hello World!"
    env[:status].call([200, {'Content-Length' => body.size}])
    env[:write].call(body)
  end
end

class Middleware
  def initialize(app)
    @app = app
  end

  def call(env)
    # Request body
    read = env[:read]
    env[:read] = proc do
      read.call.tap do |chunk|
        puts "INPUT CHUNK: %p" % chunk
      end
    end

    # Response body
    write = env[:write]
    env[:write] = proc do
      write.call.tap do |chunk|
        puts "OUTPUT CHUNK: %p" % chunk
      end
    end

    @app.call(env)
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment