2009-07-16 15 views
5

Ho una modalità di esecuzione nella mia app web CGI::Application che mi piacerebbe essere in grado di attivare dalla riga di comando in modo da poter automatizzare. Dal punto di vista dell'app Web, l'elaborazione esegue quindi l'invio dei risultati in un'e-mail.Come posso eseguire una modalità di esecuzione CGI :: Application dalla riga di comando?

Quando viene chiamato dall'interfaccia web in entrata che in una serie di parametri (indirizzo e-mail, che query da eseguire, data, ecc) in modo da questi devono essere passati in.

Come posso costruire una chiamata al CGI :: Applicazione che sarà la stessa di quando l'ho eseguita dal web?

risposta

3

Scavando ulteriormente nella documentazione CGI::App e nella documentazione CGI, sembrava più semplice di quanto pensassi. Il caso più semplice (senza vera gestione degli argomenti o trattare con l'uscita dalla chiamata corsa webapp) è:

#!/usr/bin/perl 

use strict; 
use warnings; 

use CGI; 
use WebApp; 

my $cgi = new CGI(\%{@ARGV}); 

my $webapp = WebApp->new(QUERY => $cgi); 
$webapp->run(); 

Si richiede solo una serie di spazi separati coppie di valori nome per creare CGI. È necessario passare nella modalità di esecuzione e tutti gli argomenti.

+1

È ancora più semplice di così; vedi http://search.cpan.org/perldoc/CGI#DEBUGGING – ysth

+0

Vero, il modulo 'your_script.pl name1 = value1 name2 = value2' funziona per eseguire il file CGI :: App .cgi di base, tuttavia perderò qualsiasi possibilità di controllare l'input, impostare i valori predefiniti ecc. –

+0

Questo esempio verrebbe comunque stampato su STDOUT, incluse le intestazioni HTTP, che non è desiderabile. Inoltre, non è necessario coinvolgere CGI.pm. Semplicemente confonde le cose quando passi ed elabori gli argomenti direttamente dalla riga di comando con uno strumento di elaborazione degli argomenti standard come Getopt :: Long. –

0

Questa convenzione:

$ perl yourscript.pl field1=value1 field2=value2 

libreria CGI di Perl si prende cura della magia per voi, e sembra che CGI :: Application si basa su CGI (a giudicare dal loro codice di esempio).

+0

Avrai anche bisogno di impostare varie variabili di ambiente per simulare le cose che il server web avrebbe impostato. CGI.pm cerca quelli in modo che sappia cosa fare. –

+0

@brian d foy: a meno che il codice per qualche motivo non dipenda da quelli; CGI.pm va bene senza di loro. – ysth

+0

@ysth: se questa modalità di esecuzione ha effetti collaterali, dovrebbe utilizzare POST poiché non è una richiesta idempotente. In tal caso, devi aggiungere -debug all'Importazione di CGI.pm per consentire a questa roba di funzionare. Questa è una modifica al codice che ha anche effetti collaterali. È molto più facile farlo come dice George. –

0

Invece di dover passare attraverso CGI :: Application ogni volta che si desidera ottenere qualcosa, imporre un appropriato separation of concerns, magari usando una configurazione MVC. Tutte le funzionalità dovrebbero esistere al di fuori della roba CGI :: Application dal momento che dovrebbero funzionare solo come controller. Una volta separati i bit, è possibile scrivere facilmente altri controller per altri metodi di input.

Non scrivere un'applicazione Web; scrivi un'applicazione che ha un'interfaccia web. Quando hai questo, puoi facilmente dare alla tua applicazione altri tipi di interfacce.

+0

Sono completamente d'accordo, c'è una libreria che fa il vero lavoro che genera il risultato e ho cercato di limitare la quantità di codice nella parte 'Controller' del CGI :: A al punto in cui è appena la sua formattazione. È solo la parte di me "Pigrizia" che pensa che potrei usare CGI :: App per inviare l'e-mail piuttosto che scrivere un altro script per chiamare la libreria. –

+0

Bene, la pigrizia con la L maiuscola ti consente di svolgere facilmente altre attività senza lavoro futuro: che la pigrizia non è l'evitamento del lavoro, ma il lavoro immediato per risparmiare tempo dopo. –

+0

(riferimento obbligatorio a YAGNI, sebbene io tenda ad operare in modalità L maiuscola per la maggior parte del tempo) – markh

6

L'originale CGI specification semplifica l'esecuzione di operazioni dalla riga di comando ed è stato concepito non come un'interfaccia specifica solo HTTP ma qualcosa che potrebbe gestire FTP e gopher nonché nuovi schemi URL di primo livello. So cosa volevo quando ho aiutato a specificarlo.

Le specifiche a cui ho fatto riferimento dovrebbero darti tutto ciò di cui hai bisogno, ma per la maggior parte è solo una raccolta di variabili di ambiente. Se si vede una richiesta di:

http://some.server.com/some/path?a=b&c=d 

Le variabili di ambiente escono cercando in questo modo:

SERVER_PROTOCOL=http 
REQUEST_METHOD=GET 
HTTP_HOST=some.server.com 
SERVER_PORT=80 
PATH_INFO=/some/path 
QUERY_INFO=a=b&c=d 

Per invertire la polarità che in Perl sarebbe andato qualcosa come questo:

$ENV{'SERVER_PROTOCOL'} = 'http'; 
$ENV{'REQUEST_METHOD'} = 'GET'; 
$ENV{'SERVER_PORT'} = 80; 
$ENV{'PATH_INFO'} = '/some/path'; 
$ENV{'QUERY_INFO'} = 'a=b&c=d'; 
system("perl your-CGI-script.pl"); 

Le cose diventano un po 'più complicate nella gestione delle interrogazioni POST e ci sono più possibili variabili d'ambiente che possono essere richieste. Nel peggiore dei casi si li può enumerare con un rapido qualcosa di script CGI come:

print "Content-Type: text/plain\r\n\r\n"; 
foreach (keys(%ENV)) 
{ 
    print "$_=$ENV{$_}\r\n"; 
} 

Ora mettete che sul server web al posto del tuo script CGI e vedrete tutto l'ambiente che viene passato a (e la ambiente originale quindi dovrai effettuare alcune chiamate di giudizio).

+0

Quando lo faccio, normalmente uso un exec. Nessun grande urlo però. –

+0

Fantastico, hai aiutato a specificare CGI. :) –

0

È possibile automatizzare chiamando l'app Web utilizzando curl, wget o uno script GET LWP con i parametri appropriati. Ho usato un sistema simile per attività basate su cron con un'applicazione Catalyst.

che si occupa di tutte le variabili di ambiente per te ..

+0

Questa soluzione aggiunge un ulteriore problema da risolvere: Ora è necessario assicurarsi che l'URI del processo cron sia protetto, in modo che sia possibile accedervi solo dal cron job. –

3

Sono il manutentore di CGI :: Application, e io faccio tutto il tempo-- ho dozzine di script cron costruiti con CGI :: Applicazione perché è conveniente condividere l'infrastruttura con l'applicazione.

L'approccio più semplice è questo:

# There is no browser to return results to. 
$ENV{CGI_APP_RETURN_ONLY} = 1; 

my $app = WebApp->new; 
$app->direct_run_mode_method; 

In questo esempio, si bypassare il flusso normale e chiamare un metodo direttamente. Assicurati di non aver bisogno di nessuna delle azioni di "setup" o "teardown" in quel caso.

Se si dispone di una sola modalità di esecuzione che si sta chiamando, è anche possibile impostare "start_mode" e chiamare run(), in modo che la modalità di esecuzione predefinita venga chiamata per impostazione predefinita.

Un'altra idea: è possibile utilizzare un modulo come Getopt :: Long e passare i valori tramite l'hash PARAM a new() oppure sostituire completamente il processo di selezione della modalità di esecuzione. Ecco un esempio in cui i flag della riga di comando vengono utilizzati per determinare la modalità di esecuzione:

sub setup { 
    my $self = shift; 

    $self->start_mode('send_error_digests'); 
    $self->run_modes([qw/ 
     send_error_digests 
     help 
    /]); 

    my ($dry_run, $help); 
    GetOptions(
     'dry-run' => \$dry_run, 
     'help' => \$help 
    ); 

    $self->param('dry_run' => $dry_run); 

    $self->mode_param(sub { 
     return 'help' if $help; 
     return $self->start_mode(); 
    }); 
} 
Problemi correlati