Все задачи

Http-демоненок

09 May 2013

Программист читал документацию на модуль HTTP::Daemon, захотел попробовать, и написал небольшой тестовый скрипт (вообще-то он просто взял пример из документации и внес кое-какие изменения).

use HTTP::Daemon;                                            
use HTTP::Status;                                            

# perl http_daemon.pl 10046 
my $d = HTTP::Daemon->new(LocalPort => $ARGV[1]||8080) or die; 
while (my $c = $d->accept) {                                 
    while (my $r = $c->get_request) {                        
        if ($r->method eq 'GET' 
            && $r->uri->path =~ m!^/tmp! 
            && -f $r->uri->path
        ) {
            $c->send_file_response($r->uri->path);
        }
        else {
            $c->send_error(RC_FORBIDDEN);
        }
    } 
    $c->close; 
    undef($c); 
}

Тестовый скриптик на 20 строк! И все равно он работал не совсем так, как предполагал программист.

### Подсказка

Показать

Программист начал изучать Perl недавно, а до этого программировал на C.

Подсказка-2

Показать

Скрипт станет работать лучше, если исправить в нем всего один символ.

Подсказка-3

Показать

А пока скрипт всегда начинает слушать порт 8080, независимо от переданного параметра командной строки.

Разоблачение

Показать

Передача параметров командной строки в программу в Perl очень похожа на таковую в C: программа получает массив строк – каждый параметр в отдельной строке. Но есть небольшое отличие: в C в самом первом элементе (то есть в argv[0]) содержится имя вызываемой программы, а собственно параметры начинаются с argv[1], в то время как в Perl’е параметры начинаются сразу же с $ARGV[0], а имя программы доступно в специальной переменной $0.

Программист использовал $ARGV[1] вместо $ARGV[0], этого параметра скрипт не получал и всегда работал с портом по умолчанию.

Исправление:

use HTTP::Daemon;                                            
 use HTTP::Status;                                            

 # perl http_daemon.pl 10046 
-my $d = HTTP::Daemon->new(LocalPort => $ARGV[1]||8080) or die; 
+my $d = HTTP::Daemon->new(LocalPort => $ARGV[0]||8080) or die; 
 while (my $c = $d->accept) {                                 
     while (my $r = $c->get_request) {                        
         if ($r->method eq 'GET'