perlfaq9
СОДЕРЖАНИЕ
- НАЗВАНИЕ
- ВЕРСИЯ
- ОПИСАНИЕ
- Стоит ли использовать веб-фреймворк?
- Какой веб-фреймворк следует использовать?
- Что такое Plack и PSGI?
- Как удалить HTML из строки?
- Как извлечь URL-адреса?
- Как получить файл HTML?
- Как автоматизировать отправку HTML-формы?
- Как декодировать или создавать эти кодировки %-символов в веб-приложении?
- Как перенаправить на другую страницу?
- Как добавить пароль на мои веб-страницы?
- Как убедиться, что пользователи не могут вводить значения в форму, которые могут привести к некорректной работе скрипта CGI?
- Как разобрать заголовок электронной почты?
- Как проверить правильность адреса электронной почты?
- Как декодировать строку MIME/BASE64?
- Как найти адрес электронной почты пользователя?
- Как отправить электронную почту?
- Как использовать MIME для добавления вложений к сообщению электронной почты?
- Как читать электронную почту?
- Как узнать имя хоста, имя домена или IP-адрес?
- Как получить/загрузить файл (S)FTP?
- Как выполнить RPC в Perl?
- АВТОР И АВТОРСКИЕ ПРАВА
НАЗВАНИЕ
perlfaq9 - Веб, электронная почта и сетевые приложения
ВЕРСИЯ
версия 5.20200523
ОПИСАНИЕ
Этот раздел посвящен вопросам, связанным с созданием веб-сайтов, отправкой и получением электронной почты, а также общим сетевым операциям.
Стоит ли использовать веб-фреймворк?
Да. Если вы создаёте веб-сайт с каким-либо уровнем интерактивности (формы/пользователи/базы данных), вам следует использовать фреймворк для упрощения обработки запросов и ответов.
Если интерактивности нет, вам всё равно может потребоваться что-то вроде Template Toolkit или Plack::Middleware::TemplateToolkit для упрощения обслуживания HTML-файлов (и других ресурсов).
Какой веб-фреймворк следует использовать?
На этот вопрос нет простого ответа. Perl-фреймворки могут поддерживать всё, от базовых файловых серверов и небольших интрасетей до крупных многонациональных веб-сайтов, являющихся основой международных компаний.
Ниже приведен список нескольких фреймворков с комментариями, которые могут помочь вам в принятии решения в зависимости от ваших конкретных потребностей. Начните с прочтения документации, затем задавайте вопросы на соответствующих списках рассылки или в IRC-канале.
- Catalyst
-
Сильно ориентированный на объектно-ориентированный подход и полностью функциональный, с долгой историей разработки, большой сообществом и экосистемой плагинов. Он отлично подходит для больших и сложных приложений, где вы имеете полный контроль над сервером.
- Dancer2
-
Свободен от старой нагрузки, предоставляя лёгкий и простой в освоении API. Имеет растущую экосистему плагинов. Лучше всего подходит для небольших проектов и очень легко осваивается новичками.
- Mojolicious
-
Самодостаточный и мощный для проектов как небольших, так и больших, с акцентом на HTML5 и технологиях веб-приложений в реальном времени, таких как WebSockets.
- Web::Simple
-
Сильно ориентированный на объектно-ориентированный подход и минималистичный, разработанный для скорости и предназначенный как инструмент для создания микро веб-приложений, пользовательских фреймворков или для объединения существующих совместимых с Plack веб-приложений с одним центральным диспетчером.
Все они взаимодействуют с или используют Plack, понимание основ которого важно при разработке веб-сайта на Perl (есть много полезных Plack::Middleware).
Что такое Plack и PSGI?
PSGI — это спецификация Perl Web Server Gateway Interface. Это стандарт, который используют многие Perl-веб-фреймворки. Вам не обязательно понимать его для создания веб-сайта, но полезно ознакомиться с Plack.
Plack — это набор инструментов для использования стека PSGI. Он содержит компоненты middleware, справочный сервер и утилиты для веб-фреймворков. Plack похож на Ruby's Rack или Python's Paste для WSGI.
Вы могли бы создать веб-сайт с помощью Plack и собственного кода, но для всего, что не является очень простым веб-сайтом, использование веб-фреймворка (который использует https://plackperl.org) является лучшим вариантом.
Как удалить HTML из строки?
Используйте HTML::Strip или HTML::FormatText, которые не только удаляют HTML, но и пытаются немного отформатировать полученный простой текст.
Как извлечь URL-адреса?
HTML::SimpleLinkExtor извлечёт URL-адреса из HTML, обрабатывая якоря, изображения, объекты, фреймы и многие другие теги, которые могут содержать URL. Если вам нужно что-то более сложное, вы можете создать свой собственный подкласс HTML::LinkExtor или HTML::Parser. Вы даже можете использовать HTML::SimpleLinkExtor как пример для чего-то, специально подходящего для ваших потребностей.
Вы можете использовать URI::Find или URL::Search для извлечения URL-адресов из произвольного текстового документа.
Как получить файл HTML?
(внесен brian d foy)
Основной модуль HTTP::Tiny может получать веб-ресурсы и возвращать их содержимое в виде строки:
use HTTP::Tiny;
my $ua = HTTP::Tiny->new;
my $html = $ua->get( "http://www.example.com/index.html" )->{content}; Он также может сохранить ресурс непосредственно в файл:
$ua->mirror( "http://www.example.com/index.html", "foo.html" ); Если вам нужно что-то более сложное, объект HTTP::Tiny можно настроить, задав атрибуты, или использовать LWP::UserAgent из дистрибутива libwww-perl или Mojo::UserAgent из дистрибутива Mojolicious для упрощения общих задач. Если вы хотите смоделировать интерактивный веб-браузер, вы можете использовать модуль WWW::Mechanize.
Как автоматизировать отправку HTML-формы?
Если вы делаете что-то сложное, например, проход по многочисленным страницам и формам или веб-сайту, вы можете использовать WWW::Mechanize. См. документацию для получения всех подробностей.
Если вы отправляете значения с помощью метода GET, создайте URL-адрес и закодируйте форму с помощью метода www_form_urlencode из HTTP::Tiny:
use HTTP::Tiny;
my $ua = HTTP::Tiny->new;
my $query = $ua->www_form_urlencode([ q => 'DB_File', lucky => 1 ]);
my $url = "https://metacpan.org/search?$query";
my $content = $ua->get($url)->{content}; Если вы используете метод POST, метод post_form закодирует содержимое соответствующим образом.
use HTTP::Tiny;
my $ua = HTTP::Tiny->new;
my $url = 'https://metacpan.org/search';
my $form = [ q => 'DB_File', lucky => 1 ];
my $content = $ua->post_form($url, $form)->{content}; Как декодировать или создавать эти кодировки %-символов в веб-приложении?
В большинстве случаев вам не нужно этого делать, так как ваш веб-фреймворк или, если вы делаете запрос, модуль LWP или другой модуль обработают это за вас.
Чтобы закодировать строку самостоятельно, используйте модуль URI::Escape. Функция uri_escape возвращает закодированную строку:
my $original = "Colon : Hash # Percent %";
my $escaped = uri_escape( $original );
print "$escaped\n"; # 'Colon%20%3A%20Hash%20%23%20Percent%20%25' Чтобы декодировать строку, используйте функцию uri_unescape.
my $unescaped = uri_unescape( $escaped );
print $unescaped; # back to original Помните, что не нужно кодировать весь URI, нужно закодировать каждую его часть отдельно, а затем объединить их.
Как перенаправить на другую страницу?
Большинство Perl веб-фреймворков имеют механизм для этого. В фреймворке Catalyst это будет:
$c->res->redirect($url);
$c->detach(); Если вы используете Plack (что большинство фреймворков делают), то Plack::Middleware::Rewrite стоит рассмотреть, если вы мигрируете с Apache или у вас есть URL-адреса, которые вы хотите всегда перенаправлять.
Как добавить пароль на мои веб-страницы?
Проверьте, есть ли в используемом веб-фреймворке система аутентификации и подходит ли она вам.
В качестве альтернативы, посмотрите на Plack::Middleware::Auth::Basic или на другие варианты аутентификации Plack.
Как убедиться, что пользователи не могут вводить значения в форму, которые могут привести к некорректной работе скрипта CGI?
(внесен brian d foy)
Вы не можете предотвратить отправку вашему скрипту неверных данных. Даже если вы добавите некоторые проверки на стороне клиента, пользователи могут их отключить или обойти. Например, кто-то может использовать модуль, такой как LWP, для отправки данных на ваш веб-сайт. Если вы хотите предотвратить данные, которые пытаются использовать SQL-инъекции или другие типы атак (и вы должны этого хотеть), вы не должны доверять любым данным, которые поступают в вашу программу.
Документация perlsec содержит общие рекомендации по обеспечению безопасности данных. Если вы используете модуль DBI, используйте плейсхолдеры для заполнения данных. Если вы запускаете внешние программы с system или exec, используйте списковые формы. Существует множество других мер предосторожности, которые вы должны принять, их слишком много, чтобы их перечислить здесь, и большинство из них относятся к тому, чтобы не использовать какие-либо данные, которые вы не намеревались использовать. Не доверяйте никому.
Как разобрать заголовок электронной почты?
Используйте модуль Email::MIME. Он хорошо протестирован и поддерживает всю сложность, которую вы встретите в реальном мире (отступы комментариев, кодировки, комментарии и т. д.).
use Email::MIME;
my $message = Email::MIME->new($rfc2822);
my $subject = $message->header('Subject');
my $from = $message->header('From'); Если у вас уже есть какой-либо другой тип объекта электронной почты, рассмотрите возможность передачи его в Email::Abstract, а затем использование метода cast для получения объекта Email::MIME:
my $abstract = Email::Abstract->new($mail_message_object);
my $email_mime_object = $abstract->cast('Email::MIME'); Как проверить корректность адреса электронной почты?
(частично предоставлено Aaron Sherman)
Это не такой простой вопрос, как кажется. Есть две части:
a) Как проверить, что адрес электронной почты имеет правильный формат?
b) Как проверить, что адрес электронной почты направлен на действительного получателя?
Без отправки письма на адрес и проверки, есть ли человек на другом конце, который вам ответит, вы не можете полностью ответить на часть b, но модуль Email::Valid выполнит и часть a, и часть b, насколько это возможно в реальном времени.
Наш лучший совет по проверке адреса электронной почты человека – попросить его ввести адрес дважды, как обычно делается при смене пароля. Это обычно позволяет избежать опечаток. Если оба варианта совпадают, отправьте письмо на этот адрес с личным сообщением. Если вы получите письмо обратно и человек выполнил ваши инструкции, вы можете быть достаточно уверены, что адрес действителен.
Связанная стратегия, которая менее уязвима для подделки, заключается в предоставлении личного идентификационного номера (PIN). Запишите адрес и PIN (лучше случайный) для последующей обработки. В отправленном письме укажите ссылку на ваш сайт с указанием PIN. Если письмо вернётся как не доставленное, вы знаете, что адрес недействителен. Если они не перейдут по ссылке, либо адрес поддельный, либо (предполагая, что они получили письмо) продолжение действий не было важным, поэтому можете не беспокоиться об этом.
Как декодировать строку MIME/BASE64?
Пакет MIME::Base64 обрабатывает это, а также кодировку MIME/QP. Декодирование Base64 становится таким же простым, как:
use MIME::Base64;
my $decoded = decode_base64($encoded); Модуль Email::MIME может прозрачно декодировать закодированные в Base64 части сообщения электронной почты, так что разработчику не нужно об этом беспокоиться.
Как найти адрес электронной почты пользователя?
Спросите его. Доступно так много поставщиков электронных почт, что локальная система вряд ли сможет определить адрес электронной почты пользователя.
Исключением является электронная почта, специфичная для организации (например, foo@yourcompany.com), где политика может быть кодифицирована в вашей программе. В этом случае можно посмотреть на $ENV{USER}, $ENV{LOGNAME} и получить getpwuid($&) в скалярном контексте, как показано ниже:
my $user_name = getpwuid($<) Но вы по-прежнему не можете делать предположений о правильности этого, если ваша политика этого не требует. Лучше всего спросить пользователя.
Как отправить электронное письмо?
Используйте модуль Email::Stuffer, например так:
# first, create your message
my $message = Email::Stuffer->from('you@example.com')
->to('friend@example.com')
->subject('Happy birthday!')
->text_body("Happy birthday to you!\n");
$message->send_or_die; По умолчанию Email::Sender::Simple (методы send и send_or_die используют это в качестве подпрограммы) попытается использовать sendmail первым, если он существует в вашем $PATH. Это обычно не так. Если у вас есть удалённый почтовый сервер, который вы используете для отправки почты, рассмотрите один из классов транспорта. На момент написания доступны следующие типы транспорта:
- Email::Sender::Transport::Sendmail
-
Это значение по умолчанию. Если вы можете использовать программу mail(1) или mailx(1) для отправки почты с машины, на которой выполняется ваш код, вы можете использовать этот вариант.
- Email::Sender::Transport::SMTP
-
Этот транспорт связывается с удалённым SMTP-сервером по протоколу TCP. Он необязательно использует TLS или SSL и может аутентифицироваться на сервере через SASL.
Указать Email::Stuffer использовать ваш транспорт очень просто.
$message->transport($email_sender_transport_object)->send_or_die; Как использовать MIME для добавления вложений к сообщению электронной почты?
Email::MIME напрямую поддерживает составные сообщения. Объекты Email::MIME сами являются частями и могут быть прикреплены к другим объектам Email::MIME. Обратитесь к документации Email::MIME для получения дополнительной информации, включая все поддерживаемые методы и примеры их использования.
Email::Stuffer использует Email::MIME в качестве внутренней компоненты для построения сообщений и оборачивает наиболее распространённые задачи добавления вложений простыми методами attach и attach_file.
Email::Stuffer->to('friend@example.com')
->subject('The file')
->attach_file('stuff.csv')
->send_or_die; Как читать электронную почту?
Используйте модуль Email::Folder, например так:
use Email::Folder;
my $folder = Email::Folder->new('/path/to/email/folder');
while(my $message = $folder->next_message) {
# next_message returns Email::Simple objects, but we want
# Email::MIME objects as they're more robust
my $mime = Email::MIME->new($message->as_string);
} В пространстве имён Email::Folder есть разные классы для поддержки различных типов почтовых ящиков. Обратите внимание, что эти модули, как правило, довольно ограничены и поддерживают только чтение, а не запись.
Как узнать мой хост-имя, доменное имя или IP-адрес?
(предоставлено brian d foy)
Модуль Net::Domain, который входит в стандартную библиотеку начиная с Perl 5.7.3, может предоставить вам полное доменное имя (FQDN), имя хоста или доменное имя.
use Net::Domain qw(hostname hostfqdn hostdomain);
my $host = hostfqdn(); Модуль Sys::Hostname, являющийся частью стандартной библиотеки, также может предоставить хост-имя:
use Sys::Hostname;
$host = hostname(); Модуль Sys::Hostname::Long использует другой подход и пытается вернуть полное квалифицированное имя хоста:
use Sys::Hostname::Long 'hostname_long';
my $hostname = hostname_long(); Чтобы получить IP-адрес, можно использовать встроенную функцию gethostbyname, чтобы преобразовать имя в число. Чтобы преобразовать это число в формат с точками (a.b.c.d), который ожидают большинство пользователей, используйте функцию inet_ntoa из модуля Socket, который также входит в состав Perl.
use Socket;
my $address = inet_ntoa(
scalar gethostbyname( $host || 'localhost' )
); Как получить/загрузить файл (S)FTP?
Net::FTP и Net::SFTP позволяют взаимодействовать с серверами FTP и SFTP (Secure FTP).
Как реализовать RPC в Perl?
Используйте один из модулей RPC (https://metacpan.org/search?q=RPC).
АВТОР И АВТОРСКИЕ ПРАВА
Авторские права (с) 1997-2010 Tom Christiansen, Nathan Torkington и другие авторы, как указано. Все права защищены.
Данная документация бесплатна; вы можете перераспределять её и/или изменять её на тех же условиях, что и Perl.
Независимо от его распространения, все примеры кода в этом файле объявляются всеобщей собственностью. Вам разрешено и рекомендуется использовать этот код в собственных программах для развлечения или с коммерческой целью по своему усмотрению. Краткий комментарий в коде с указанием авторства будет вежливым жестом, но не является обязательным.
© 1993–2020 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.32.0/perlfaq9