perlfaq9
СОДЕРЖАНИЕ
- НАЗВАНИЕ
- ВЕРСИЯ
- ОПИСАНИЕ
- Стоит ли использовать фреймворк для веб-приложений?
- Какой веб-фреймворк следует использовать?
- Что такое Plack и PSGI?
- Как удалить HTML из строки?
- Как извлечь URL-адреса?
- Как получить файл HTML?
- Как автоматизировать отправку HTML-формы?
- Как декодировать или создавать %-кодировки в веб-приложениях?
- Как перенаправить на другую страницу?
- Как добавить защиту паролем для моих веб-страниц?
- Как убедиться, что пользователи не могут вводить значения в форму, которые могут привести к нежелательному поведению скрипта CGI?
- Как разобрать заголовок письма?
- Как проверить корректность адреса электронной почты?
- Как декодировать строку MIME/BASE64?
- Как найти адрес электронной почты пользователя?
- Как отправить электронное письмо?
- Как использовать MIME для добавления вложения к сообщению электронной почты?
- Как прочитать электронное письмо?
- Как узнать имя хоста, доменное имя или IP-адрес?
- Как получить/отправить файл (S)FTP?
- Как реализовать RPC на Perl?
- АВТОР И АВТОРСКИЕ ПРАВА
НАЗВАНИЕ
perlfaq9 - Веб, электронная почта и сети
ВЕРСИЯ
версия 5.20210520
ОПИСАНИЕ
Этот раздел посвящен вопросам, связанным с запуском веб-сайтов, отправкой и получением электронной почты, а также общим вопросам сетевого взаимодействия.
Стоит ли использовать фреймворк для веб-приложений?
Да. Если вы разрабатываете веб-сайт с каким-либо уровнем интерактивности (формы/пользователи/базы данных), вам следует использовать фреймворк, чтобы упростить обработку запросов и ответов.
Если интерактивности нет, то вы все равно можете рассмотреть использование чего-то вроде 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, а затем использования метода преобразования для получения объекта Email::MIME:
my $abstract = Email::Abstract->new($mail_message_object);
my $email_mime_object = $abstract->cast('Email::MIME'); Как проверить корректность адреса электронной почты?
(частично предоставлено Аароном Шерманом)
Это не такой простой вопрос, как кажется. Есть две части:
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 и %%%CODE_BLOCK_36%%.
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).
АВТОР И АВТОРСКИЕ ПРАВА
Авторские права (c) 1997-2010 Tom Christiansen, Nathan Torkington и другие авторы, как указано. Все права защищены.
Эта документация бесплатна; вы можете перераспределять и/или изменять её на тех же условиях, что и Perl сам по себе.
Независимо от его распространения, все примеры кода в этом файле объявляются общественным достоянием. Вам разрешено и поощряется использование этого кода в ваших собственных программах для развлечения или с целью получения прибыли, как вы посчитаете нужным. Простая заметка в коде, дающая кредит, была бы вежливой, но не обязательной.
© 1993–2023 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.38.0/perlfaq9