Как я могу получить весь объект запроса с CGI.pm?

Я пытаюсь написать Perl CGI script для обработки запросов XML-RPC, в которых XML-документ отправляется как тело HTTP-запроса POST.

Модуль CGI.pm отлично справляется с извлечением именованных параметров из HTTP-запроса, но я не могу понять, как заставить его предоставить мне весь объект HTTP-запроса (т.е. XML-документ в запросе XML-RPC Я работаю).

Если не CGI.pm, есть ли еще один модуль, который мог бы разобрать эту информацию из запроса? Я бы предпочел не извлекать эту информацию "вручную" из переменных окружения. Спасибо за любую помощь.

Ответы

Ответ 1

Вы можете получить необработанные данные POST, используя специальное имя параметра POSTDATA.

my $q = CGI->new;
my $xml = $q->param( 'POSTDATA' );

Кроме того, вы можете читать STDIN напрямую, а не использовать CGI.pm, но затем вы теряете все другие полезные вещи, которые делает CGI.pm.

Трюк POSTDATA задокументирован в отличном документе CGI.pm здесь.

Ответ 2

Правильно, можно использовать POSTDATA, но это работает только в том случае, если в запросе Content-Type не было установлено "multipart/form-data".

Если он настроен на "multipart/form-data", CGI.pm не выполняет свою собственную обработку контента и POSTDATA.

Таким образом, другие параметры включают $cgi->query_string и/или $cgi->Dump.

$cgi->query_string возвращает содержимое POST в формате GET (param=value&...), и, похоже, нет способа просто получить содержимое POST STDIN, поскольку они были переданы клиентом.

Таким образом, чтобы получить фактическое содержимое стандартного ввода запроса POST, если вы измените CGI.pm, вы можете изменить строку 620, чтобы сохранить содержимое @lines где-то в переменной, например

$self->{standard_input} = join '', @lines;

И затем войдите в него через $cgi->{standard_input}.

Ответ 3

Чтобы обработать все случаи, включая случаи, когда Content-Type - multipart/form-data, прочитайте (и верните обратно) необработанные данные, до того, как CGI сделает.

use strict;
use warnings;

use IO::Handle;
use IO::Scalar;

STDIN->blocking(1); # ensure to read everything
my $cgi_raw = '';

{ 
  local $/; 
  $cgi_raw = <STDIN>;
  my $s;
  tie  *STDIN, 'IO::Scalar', \$s;
  print STDIN $cgi_raw;
  tied(*STDIN)->setpos(0);
}

use CGI qw /:standard/;
...