AnyEvent-HTTPD-ExtDirect

 view release on metacpan or  search on metacpan

lib/AnyEvent/HTTPD/ExtDirect.pm  view on Meta::CPAN

use File::Temp;
use File::Basename;

use AnyEvent::HTTPD::Request;

use RPC::ExtDirect::Util;
use RPC::ExtDirect::Util::Accessor;
use RPC::ExtDirect::Config;
use RPC::ExtDirect::API;
use RPC::ExtDirect;

#
# This module is not compatible with RPC::ExtDirect < 3.0
#

croak __PACKAGE__." requires RPC::ExtDirect 3.0+"
    if $RPC::ExtDirect::VERSION lt '3.0';

### PACKAGE GLOBAL VARIABLE ###
#
# Version of the module
#

our $VERSION = '3.20';

### PUBLIC CLASS METHOD (CONSTRUCTOR) ###
#
# Instantiate a new AnyEvent::HTTPD::ExtDirect object
#

sub new {
    my $class = shift;
    
    my %arg = @_ == 1 && 'HASH' eq ref $_[0] ? %{ $_[0] }
            :                                  @_
            ;
    
    my $api    = delete $arg{api}    || RPC::ExtDirect->get_api();
    my $config = delete $arg{config} || $api->config;
    
    $config->add_accessors(
        overwrite => 1,
        complex   => [{
            accessor => 'router_class_anyevent',
            fallback => 'router_class',
        }, {
            accessor => 'eventprovider_class_anyevent',
            fallback => 'eventprovider_class',
        }],
    );
    
    for my $var ( qw/ router_class eventprovider_class / ) {
        my $method = "${var}_anyevent";
        
        $config->$method( delete $arg{$var} ) if exists $arg{$var};
    }
    
    # AnyEvent::HTTPD wants only IP addresses
    $arg{host} = '127.0.0.1' if $arg{host} =~ /localhost/io;

    my $self = $class->SUPER::new(%arg);
    
    $self->config($config);
    $self->api($api);

    return $self;
}

### PUBLIC INSTANCE METHOD ###
#
# Run the server
#

sub run {
    my ($self) = @_;
    
    my $config = $self->config;

    $self->set_callbacks(
        api_path    => $config->api_path,
        router_path => $config->router_path,
        poll_path   => $config->poll_path,
    );

    $self->SUPER::run();
}

### PUBLIC INSTANCE METHOD ###
#
# Handle Ext.Direct API calls
#

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

    # Get the API JavaScript chunk
    my $js = eval {
        $self->api->get_remoting_api( config => $self->config )
    };

    # If JS API call failed, return error
    return $self->_error_response if $@;

    # Content length should be in octets
    my $content_length = do { use bytes; my $len = length $js };

    $req->respond([
        200,
        'OK',
        {
            'Content-Type'   => 'application/javascript',
            'Content-Length' => $content_length,
        },
        $js
    ]);

    $self->stop_request;
}

### PUBLIC INSTANCE METHOD ###
#
# Handle Ext.Direct method requests
#

sub handle_router {
    my ($self, $req) = @_;
    
    if ( $req->method ne 'POST' ) {
        $req->respond( $self->_error_response );
        $self->stop_request;
        
        return;
    }
    
    my $config = $self->config;
    my $api    = $self->api;

    # Naked AnyEvent::HTTPD::Request object doesn't provide several
    # utility methods we'll need down below, and we will need it as
    # an environment object, too
    my $env = bless $req, __PACKAGE__.'::Env';

    # We're trying to distinguish between a raw POST and a form call
    my $router_input = $self->_extract_post_data($env);



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