Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: разработка для Web > SSI технология и скрипты Perl


Автор: FlyBird 28.3.2007, 04:38
Здравствуйте!
По общему принципу сайт использует технологию SSI, т.е. в каждом файле с расширением *.shtml имеется код 
<!--Include Virtual= "_header.inc"-->
< .... код страницы...
>
<!--Include Virtual= "_footer.inc"-->
На сайте функционирует гостевая книга (обычный скрипт, который пишет в базу отзыв посетителя и требует правильного заполнения полей в форме отзыва). Собственно проблема в ней. Если пользователь ошибается в каком-либо поле, скрипт выполняется и выдает пользователю новую форму с указанием ошибки в поле(ях). Чтобы повторить структуру сайта использования шаблонной технологии, сейчас приходится открывать файлы  _header.inc и _footer.inc из скрипта и читать их содержимое, а только потом отдавать клиенту. Если пользователей больше 20, то такие тормоза. 
Что-нибудь можно предпринять в данном случае?

Автор: korob2001 1.4.2007, 06:40
А зачем открывать файлы .inc, если они выводятся через SSI?
Если я правильно понимаю, то примерно так выглядит файл SSI, гостевой книги?
Код

<!--#include virtual="./_header.inc"-->
<!--#include virtual="/cgi-bin/guest.pl"-->
<!--#include virtual="./_footer.inc"-->

Проблема скорее всего в том, что в теге <form> в атрибуте action указан путь не на сам SSI файл, а на Perl программу. Потому именно в этот момент приходится генерировать весь контент именно программой Perl.

Для примера пишем простейшую готевую книгу:
В каталоге www создадим каталог guest, в него положим три файла _header.inc, _footer.inc и .guest.shtml. Вот так будут выглядеть эти файлы:
_header.inc
Код

<html>
    <head>
        <title>Гостевая книга</title>
    </head>
    <body>


_footer.inc
Код

    </body>
</html>


guest.shtml
Код

<!--#include virtual="./_header.inc"-->
<!--#include virtual="/cgi-bin/guest/guest.pl?$QUERY_STRING"-->
<!--#include virtual="./_footer.inc"-->


Теперь перейдём к Perl программе. Для неё создадим каталог /cgi-bin/guest и в него положим файл guest.pl, вот так он будет выглядеть:
Код

#!/usr/bin/perl -w
use strict;
use CGI;
use Fcntl qw(:flock);

my $cgi = new CGI();

sub start_lock {
    open(BLOCK, "> locked_file.sem") or die "Can't open lock file: $!";
    flock(BLOCK, LOCK_EX);
}

sub stop_lock {
    close(BLOCK);
}

sub success {
    return $cgi->b({-style => "color: #0000cc"}, "Данные успешно добавлены в гостевую книгу");
}

sub error {
    my $field = shift;
    return $cgi->b({-style => "color: #cc0000"}, "Не верно заполнено поле \"$field\"");
}

sub form {
    my $message = shift || "Все поля обязательны для заполнения";
    print $cgi->div({-style => "width: 450;border-color: #000000;border-style: solid;border-width: 1px"}, $message);
    print $cgi->start_form(-method => "GET");
    print $cgi->b("Ваше имя: ");
    print $cgi->textfield(-name => "name");
    print $cgi->br();
    print $cgi->b("Ваш Email: ");
    print $cgi->textfield(-name => "mail");
    print $cgi->br();
    print $cgi->textarea(-name => "mess",
                         -rows => 5,
                         -columns => 30);
    print $cgi->br(), $cgi->br();
    print $cgi->submit(-name => "send", -value => "Отправить");
    print $cgi->end_form();

    show_content();
}

sub userControl {
    my $name = $cgi->param('name');
    my $mail = $cgi->param('mail');
    my $mess = $cgi->param('mess');

    return error("Ваше имя")  if ($name !~ /^[A-Za-zА-Яа-я ]+$/);
    return error("Ваш Email") if ($mail !~ /^(?:[A-Za-z0-9]+?(?:\.|-|_)?)*(?:[A-Za-z0-9]+)?\@(?:[A-Za-z0-9]+?\.)*?[A-Za-z0-9]{2,4}$/);

    $mess =~ s/\|//g;
    $mess =~ s/\n/<br\/>/g;

    # Сообщение прошло проверку, запишем в базу данных. В нашем случае в файл
    save_message($name, $mail, $mess);
    return success();
}

sub save_message {
    my($name, $mail, $mess) = @_;
    start_lock();  # Начало блокировки

    open my $fh, ">>", "guest.txt" or die "Can't open file 'guest.txt': $!";
    print $fh "$name|$mail|$mess\n";
    close $fh;

    stop_lock();   # Конец блокировки
}

sub show_content {
    my($name,$mail,$mess);
    open my $fh, "<", "guest.txt" or return;
    while (chomp(my $line = <$fh>)) {
          ($name,$mail,$mess) = split(/\|/, $line);
          print $cgi->br(), $cgi->br();
          print $cgi->start_table({-width => 450, -border => 1});
          print $cgi->start_Tr();
          print $cgi->td({-bgcolor => "#cccccc"}, $cgi->a({-href => "mailto:$mail"},$name));
          print $cgi->end_Tr();
          print $cgi->start_Tr();
          print $cgi->td({-bgcolor => "#ffffff"}, $cgi->p($mess));
          print $cgi->end_Tr();
          print $cgi->end_table();
    }
    close $fh;
}

print $cgi->header(-charset => "windows-1251");
if (defined $cgi->param("send")) {
    form(userControl());
} else {
    form();
}

Теперь запускаем наш SSI файл: http://localhost/guest/guest.shtml
Если всё сделал правильно увидешь форму, которую нам генерирует Perl программа. В неё введи сообщение и попробуй сделать ошибку. Скажем укажи Email без @. Заметь, что после получения ошибки мы остались всё на той же SSI страничке, на которой и были перед отправкой сообщения.

Теперь поправь поле в котором была обнаружена ошибка и отправь данные снова. Если ошибок больше нет, то программа запишет их в файл и сгенерирует форму+сообщения, которые были успешно добавлены, всё на тойже SSI страничке.

PS: Если книга которая тормозит, работает по такому же принципу, то Perl программа вообще не должна даже знать о существовании файлов _header.inc и _footer.inc и уж тем более не должна открывать их при каждом запросе.

PSS: Если ничего не понятно, то могу прокоментировать код. Просто у нас уже 5:40 утра, а я ещё не ложился, потому не написал коментарии сразу.

Автор: FlyBird 2.4.2007, 08:21
Спасибо, огромное! Мир не без добрых людей!
Именно так и хотелось сделать, только не знал как именно. Код не проверял пока в реальности, но проверю обязательно! Принцип основной именно такой.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)