perlfaq9
СОДЕРЖАНИЕ
- НАЗВАНИЕ
- ВЕРСИЯ
- ОПИСАНИЕ
- Использовать ли веб-фреймворк?
- Какой веб-фреймворк использовать?
- Что такое Plack и PSGI?
- Как удалить HTML из строки?
- Как извлечь URL-адреса?
- Как получить файл HTML?
- Как автоматизировать отправку HTML-формы?
- Как декодировать или создавать эти кодировки % на веб-сайте?
- Как перенаправить на другую страницу?
- Как защитить мои веб-страницы паролем?
- Как предотвратить ввод пользователем значений, вызывающих проблемы в моем CGI-скрипте?
- Как разобрать заголовок электронной почты?
- Как проверить правильность адреса электронной почты?
- Как декодировать строку MIME/BASE64?
- Как найти адрес электронной почты пользователя?
- Как отправить электронное письмо?
- Как использовать MIME для добавления вложения к сообщению электронной почты?
- Как читать электронные письма?
- Как узнать имя хоста, доменное имя или IP-адрес?
- Как получить/загрузить файл (S)FTP?
- Как выполнить удаленный вызов процедур (RPC) в Perl?
- АВТОР И АВТОРСКИЕ ПРАВА
НАЗВАНИЕ
perlfaq9 - Веб, электронная почта и сетевые операции
ВЕРСИЯ
версия 5.20190126
ОПИСАНИЕ
Этот раздел посвящен вопросам, связанным с созданием веб-сайтов, отправкой и получением электронной почты, а также общим сетевым операциям.
Использовать ли веб-фреймворк?
Да. Если вы создаёте веб-сайт с какой-либо степенью интерактивности (формы/пользователи/базы данных), вам следует использовать фреймворк для упрощения обработки запросов и ответов.
Если интерактивности нет, то вы всё равно можете рассмотреть использование чего-то вроде 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 и своего собственного кода, но для всего, что не является очень простым веб-сайтом, использование веб-фреймворка (который использует Plack) является лучшим вариантом.
Как удалить HTML из строки?
Используйте HTML::Strip или HTML::FormatText, которые не только удаляют HTML, но и пытаются немного отформатировать полученный простой текст.
Как извлечь URL-адреса?
HTML::SimpleLinkExtor извлечёт URL-адреса из HTML, обрабатывая якоря, изображения, объекты, фреймы и многие другие теги, которые могут содержать URL-адрес. Если вам нужно что-то более сложное, вы можете создать свой собственный подкласс HTML::LinkExtor или HTML::Parser. Вы даже можете использовать HTML::SimpleLinkExtor в качестве примера для чего-то, специально подходящего для ваших потребностей.
Вы можете использовать URI::Find для извлечения URL-адресов из произвольного текстового документа.
Как получить файл HTML?
(предоставлено brian d foy)
Используйте дистрибутив libwww-perl. Модуль LWP::Simple может получать веб-ресурсы и возвращать их содержимое в виде строки:
use LWP::Simple qw(get);
my $html = get( "http://www.example.com/index.html" ); Он также может сохранить ресурс непосредственно в файле:
use LWP::Simple qw(getstore);
getstore( "http://www.example.com/index.html", "foo.html" ); Если вам нужно выполнить что-то более сложное, вы можете использовать модуль LWP::UserAgent, чтобы создать свой собственный пользовательский агент (например, браузер), чтобы выполнить задачу. Если вы хотите смоделировать интерактивный веб-браузер, вы можете использовать модуль WWW::Mechanize.
Как автоматизировать отправку HTML-формы?
Если вы делаете что-то сложное, например, перемещаетесь по многим страницам и формам или по веб-сайту, вы можете использовать WWW::Mechanize. Обратитесь к документации для всех подробностей.
Если вы отправляете значения с помощью метода GET, создайте URL-адрес и закодируйте форму с помощью query_form метода:
use LWP::Simple;
use URI::URL;
my $url = url('L<http://www.perl.com/cgi-bin/cpan_mod')>;
$url->query_form(module => 'DB_File', readme => 1);
$content = get($url); Если вы используете метод POST, создайте свой собственный пользовательский агент и закодируйте содержимое соответствующим образом.
use HTTP::Request::Common qw(POST);
use LWP::UserAgent;
my $ua = LWP::UserAgent->new();
my $req = POST 'L<http://www.perl.com/cgi-bin/cpan_mod'>,
[ module => 'DB_File', readme => 1 ];
my $content = $ua->request($req)->as_string; Как декодировать или создавать эти кодировки % на веб-сайте?
В большинстве случаев вам не нужно этого делать, так как ваш веб-фреймворк или, если вы делаете запрос, модуль 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, а затем использование его метода преобразования для получения объекта 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. Декодирование base 64 станет таким же простым, как:
use MIME::Base64;
my $decoded = decode_base64($encoded); Модуль Email::MIME может декодировать закодированные в base 64 части сообщений электронной почты прозрачно, поэтому разработчик не должен об этом беспокоиться.
Как найти адрес электронной почты пользователя?
Спросите у него. Существует множество поставщиков электронной почты, поэтому маловероятно, что локальная система имеет возможность определить адрес электронной почты пользователя.
Исключением является электронная почта, специфичная для организации (например, foo@yourcompany.com), где политика может быть кодифицирована в вашей программе. В этом случае вы можете посмотреть на $ENV{USER}, $ENV{LOGNAME} и получить getpwuid($<) в скалярном контексте, как показано ниже:
my $user_name = getpwuid($<) Но вы по-прежнему не можете предполагать, что это правильно, если только ваша политика не указывает на это. Вам лучше всего спросить пользователя.
Как отправить электронное письмо?
Используйте модули Email::MIME и Email::Sender::Simple, как показано ниже:
# first, create your message
my $message = Email::MIME->create(
header_str => [
From => 'you@example.com',
To => 'friend@example.com',
Subject => 'Happy birthday!',
],
attributes => {
encoding => 'quoted-printable',
charset => 'utf-8',
},
body_str => "Happy birthday to you!\n",
);
use Email::Sender::Simple qw(sendmail);
sendmail($message); По умолчанию Email::Sender::Simple сначала попытается использовать `sendmail`, если он существует в вашем $PATH. Это обычно не так. Если у вас есть удалённый сервер электронной почты, который вы используете для отправки почты, рассмотрите возможность использования одного из классов транспорта. На момент написания доступные транспорты включают:
- Email::Sender::Transport::Sendmail
-
Это значение по умолчанию. Если вы можете использовать программу mail(1) или mailx(1) для отправки почты с машины, на которой работает ваш код, вы должны иметь возможность использовать это.
- Email::Sender::Transport::SMTP
-
Этот транспорт связывается с удалённым SMTP-сервером по TCP. Он необязательно использует TLS или SSL и может аутентифицироваться на сервере с помощью SASL.
Указать Email::Sender::Simple на использование вашего транспорта очень просто.
sendmail(
$message,
{
transport => $email_sender_transport_object,
}
); Как использовать MIME для создания вложения в сообщение электронной почты?
Email::MIME напрямую поддерживает сообщения multipart. Объекты Email::MIME сами по себе являются частями и могут быть прикреплены к другим объектам Email::MIME. Обратитесь к документации Email::MIME за дополнительной информацией, включая все поддерживаемые методы и примеры их использования.
Как читать электронную почту?
Используйте модуль 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).
АВТОР И АВТОРСКИЕ ПРАВА
Авторские права (c) 1997-2010 Том Кристиансен, Натан Торкинтон и другие авторы, как указано. Все права защищены.
Данная документация является бесплатной; вы можете перераспределять и/или изменять ее на тех же условиях, что и 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.30.3/perlfaq9