Alice

 view release on metacpan or  search on metacpan

lib/Alice/HTTP/Server.pm  view on Meta::CPAN

    $res->send;
  }

  # we have credentials
  elsif (my $user = $req->param('username')
     and my $pass = $req->param('password')) {

    $self->authenticate($user, $pass, sub {
      my $app = shift;
      if ($app) {
        $req->env->{"psgix.session"} = {
          is_logged_in => 1,
          username     => $user,
          userid       => $app->user,
        };
        $res->redirect($dest);
      }
      else {
        $req->env->{"psgix.session"}{is_logged_in} = 0;
        $req->env->{"psgix.session.options"}{expire} = 1;
        $res->content_type("text/html; charset=utf-8");
        $res->body($self->render("login", $dest, "bad username or password"));
      }
      $res->send;
    });
  }

  # render the login page
  else {
    $res->content_type("text/html; charset=utf-8");
    $res->body($self->render("login", $dest));
    $res->send;
  }
}

sub logout {
  my ($self, $req, $res) = @_;
  $_->close for @{$self->app->streams};
  if (!$self->auth_enabled) {
    $res->redirect("/");
  } else {
    $req->env->{"psgix.session"}{is_logged_in} = 0;
    $req->env->{"psgix.session.options"}{expire} = 1;
    $res->redirect("/login");
  }
  $res->send;
}

sub setup_xhr_stream {
  my ($self, $req, $res) = @_;
  my $app = $self->app;

  AE::log debug => "opening new stream";

  $res->headers([@Alice::HTTP::Stream::XHR::headers]);
  my $stream = Alice::HTTP::Stream::XHR->new(
    writer     => $res->writer,
    start_time => $req->param('t'),
    # android requires 4K updates to trigger loading event
    min_bytes  => $req->user_agent =~ /android/i ? 4096 : 0,
    on_error => sub { $app->purge_disconnects },
  );

  $stream->send([$app->connect_actions]);
  $app->add_stream($stream);
}

sub setup_ws_stream {
  my ($self, $req, $res) = @_;
  my $app = $self->app;

  AE::log debug => "opening new websocket stream";

  if (my $fh = $req->env->{'websocket.impl'}->handshake) {
    my $stream = Alice::HTTP::Stream::WebSocket->new(
      start_time => $req->param('t') || time,
      fh      => $fh,
      on_read => sub { $app->handle_message(@_) },
      on_error => sub { $app->purge_disconnects },
      ws_version => $req->env->{'websocket.impl'}->version,
    );

    $stream->send([$app->connect_actions]);
    $app->add_stream($stream);
  }
  else {
    my $code = $req->env->{'websocket.impl'}->error_code;
    $res->send([$code, ["Content-Type", "text/plain"], ["something broke"]]);
  }
}

sub handle_message {
  my ($self, $req, $res) = @_;

  my $msg = $req->param('msg');
  my $html = $req->param('html');
  my $source = $req->param('source');
  my $stream = $req->param('stream');

  $self->app->handle_message({
    msg    => defined $msg ? $msg : "",
    html   => defined $html ? $html : "",
    source => defined $source ? $source : "",
    stream => defined $stream ? $stream : "",
  });
  
  $res->ok;
}

sub send_safe_index {
  my ($self, $req, $res) = @_;
  $req->parameters->{images} = "hide";
  $req->parameters->{avatars} = "hide";
  $self->send_index($req, $res);
}

sub send_index {
  my ($self, $req, $res) = @_;
  my $options = $self->merged_options($req);
  my $app = $self->app;

  $res->headers(["Content-type" => "text/html; charset=utf-8"]);
  my $writer = $res->writer;
  my @windows = $app->sorted_windows;

  my @queue;
    
  push @queue, sub {$app->render('index_head', @windows)};
  for my $window (@windows) {
    push @queue, sub {$app->render('window_head', $window)};
    push @queue, sub {$app->render('window_footer', $window)};
  }
  push @queue, sub {
    my $html = $app->render('index_footer', $options, @windows);
    $app->config->first_run(0);
    $app->config->write;
    return $html;
  };

  my $idle_w; $idle_w = AE::idle sub {
    if (my $cb = shift @queue) {
      my $content = encode "utf8", $cb->();
      $writer->write($content);
    } else {
      $writer->close;
      undef $idle_w;
    }



( run in 1.645 second using v1.01-cache-2.11-cpan-39bf76dae61 )