#!/usr/local/bin/perl -w
###########################################
# apache-peek
# Mike Schilli, 2011 (m@perlmeister.com)
###########################################
use strict;
use Mojolicious::Lite;
use ApacheLog::Parser 
    qw(parse_line_to_hash);
use Mojo::IOLoop;
use POSIX;
use Socket;
use JSON qw(encode_json);

my $listen = "http://localhost:8083";
@ARGV = (qw(daemon --listen), $listen);

my $base_url = "http://website.com";

my $file = "access.log";
sysopen my $fh, "$file", 
    O_NONBLOCK|O_RDONLY or die $!;

my $loop = Mojo::IOLoop->singleton();

###########################################
websocket "/myws" => sub {
###########################################
  my($self) = @_;

  my $timer_cb;
  $timer_cb = sub {
    for my $line ( @{ tail( $fh ) } ) {
      my %fields = 
        parse_line_to_hash( $line );

      if( $fields{ request } eq "GET" and
          $fields{ file } =~ /\.html?$/ and
            # skip our own requests
          $fields{ client } ne 
            $self->tx->remote_address
        ) {
        my $url = $base_url . 
                  $fields{ file };
        my $data = { 
          url  => $url,
          host => 
            revlookup( $fields{ client } ),
        };
        $self->send_message( 
            encode_json( $data ) );
        last;
      }
    }
    $loop->timer( 5, $timer_cb);
  };
  $timer_cb->();
};

###########################################
get '/' => sub {
###########################################
  my ($self) = @_;

  (my $ws_url = $listen) =~ s/http/ws/;
  $ws_url .= "/myws";
  $self->{stash}->{ws_url} = $ws_url;
} => 'index';

app->start();

###########################################
sub tail {
###########################################
  my($fh) = @_;

  my($buf, $chunk, $result);

  while( $result = sysread $fh, 
                           $chunk, 1024 ) {
    $buf .= $chunk;
  }

  if( defined $result ) {
    chomp $buf;
    my @lines = map { s/\s+$//g; $_; } 
                split /\n/, $buf;
    return \@lines;
  }

  return undef;
}

###########################################
sub revlookup {
###########################################
  my($ip) = @_;

  my $host = (gethostbyaddr( 
          inet_aton($ip), AF_INET ))[0];
  $host = $ip unless defined $host;
  return $host;
}

__DATA__
@@ index.html.ep
% layout 'default';

Host: <em id="host"></em>
URL: <em id="url"></em>

<iframe width=100% height=800 src="" 
        id="pageview"></iframe>

@@ layouts/default.html.ep
<!doctype html><html>
  <head><title>Apache Peek</title>
    <script type="text/javascript">
      var socket = new WebSocket( 
                     "<%== $ws_url %>" );
      socket.onmessage = function (msg) {
        var data = eval( "(" + 
                          msg.data + ")" );
        document.getElementById( 
          "host").innerHTML = data.host;
        document.getElementById( 
          "url").innerHTML = data.url;
        document.getElementById( 
          "pageview").setAttribute( "src", 
                                data.url );
      };
    </script>
  </head>
  <body> <%== content %> </body>
</html>
