Можно ли отправить параметры POST в сценарий CGI без другого HTTP-запроса? - PullRequest
0 голосов
/ 05 декабря 2009

Я пытаюсь запустить скрипт CGI в текущей среде из другого модуля Perl. Все работает хорошо, используя стандартные системные вызовы для запросов GET. С POST тоже все в порядке, пока список параметров не станет слишком длинным, затем они будут обрезаны.

Кто-нибудь сталкивался с этой проблемой, или есть какие-либо предложения для других способов решить эту проблему?

Следующее несколько упрощено для ясности. Есть еще проверка ошибок и т. Д.

Для GET-запросов и POST-запросов без параметров , я делаю следующее:

# $query is a CGI object.
my $perl = $^X;
my $cgi  = $cgi_script_location; # /path/file.cgi
system {$perl} $cgi;
  • Параметры передаются через Переменная среды QUERY_STRING.
  • STDOUT захватывается вызывающим Сценарий так что бы сценарий CGI Отпечатки ведут себя как обычно.
  • Эта часть работает.

Для POST-запросов с параметрами работает следующее, но, похоже, ограничивает мою доступную длину запроса:

# $query is a CGI object.
my $perl = $^X;
my $cgi  = $cgi_script_location; # /path/file.cgi

# Gather parameters into a URL-escaped string suitable 
# to pass to a CGI script ran from the command line.
# Null characters are handled properly.
# e.g., param1=This%20is%20a%20string&param2=42&... etc.
# This works.
my $param_string = $self->get_current_param_string();

# Various ways to do this, but system() doesn't pass any 
# parameters (different question).
# Using qx// and printing the return value works as well.
open(my $cgi_pipe, "|$perl $cgi");
print {$cgi_pipe} $param_string;
close($cgi_pipe);
  • Этот метод работает для коротких списков параметров, но если вся команда становится близкой к 1000 символов, список параметров сокращается. Вот почему я попытался сохранить параметры в файл; чтобы избежать ограничений оболочки.
  • Если я выгружаю список параметров из выполненного скрипта CGI, я получаю что-то вроде следующего:

param1=blah<br> ... a bunch of other parameters ...<br> paramN=whatever<br> p <-- cut off after 'p'. There are more parameters.<br>

Другие вещи, которые я сделал, которые не помогли или не помогли

$> perl index.cgi < temp-param-file

  • Сохраняет $ param_string в файл, передавая этот файл в CGI-скрипт, как описано выше. Те же ограничения, что и при передаче команд через командную строку; все еще отрезан.
  • Удостоверился, что $CGI::POST_MAX приемлемо высокий (это -1).
  • Убедитесь, что обработка командной строки CGI работает. (: no_debug не установлен)
  • Запустите CGI из командной строки с теми же параметрами. Это работает.

Ведет

  • Очевидно, это похоже на ограничение количества символов в оболочке, которое Perl использует для выполнения команды, но оно не было разрешено путем передачи параметров через файл.

Ответы [ 3 ]

1 голос
/ 06 декабря 2009

Передача параметров в систему в виде одной строки из HTTP-ввода чрезвычайно опасна.

Из системы perldoc -f ,

Если есть только один скалярный аргумент, этот аргумент проверяется на наличие метасимволов оболочки, и если они есть, весь аргумент передается в системную командную оболочку для анализа (это / bin / sh -c на платформах Unix но меняется на других платформах). Если в аргументе нет метасимволов оболочки, ..

Другими словами, если я передам аргументы -e printf("working..."); rm -rf /;, я могу удалить информацию с вашего диска (все, если ваш веб-сервер работает от имени пользователя root). Если вы решите сделать это, обязательно наберите system("perl", @cgi).

Проблема длины аргумента, с которой вы сталкиваетесь, может быть ограничением операционной системы (описано в http://www.in -ulm.de / ~ mascheck / различным / argmax / ):

Существуют разные способы узнать верхний предел:

  • команда: getconf ARG_MAX
  • системный заголовок: ARG_MAX, например, <[sys /] limit.h>

Сохранение во временном файле сопряжено с риском: несколько вызовов CGI могут быть сохранены в одном и том же файле, создавая состояние гонки, при котором параметры одного пользователя могут использоваться процессом другого пользователя.

Вместо этого вы можете попробовать открыть дескриптор файла для процесса и передать аргументы в качестве стандартного ввода. open my $perl, '|', 'perl' or die; fprintf(PERL, @cgi);

0 голосов
/ 08 декабря 2009

Оказывается, что проблема на самом деле связана с разницей в Content-Length между исходными параметрами и строкой параметров, которую я сложил вместе. Я не осознавал, что модуль CGI использовал это значение из исходных заголовков в качестве предела того, сколько входных данных нужно прочитать (имеет смысл!). По-видимому, дополнительным побегом, которое я делал, было добавление некоторых символов.

Мое решение состоит в том, чтобы просто собрать воедино строку параметров, которую я передам, и изменить переменную среды, которую модуль CGI проверит, чтобы определить длину содержимого, равную.

Вот окончательный рабочий код:

use CGI::Util qw(escape);

my $params;

foreach my $param (sort $query->param) {
 my $escaped_param  = escape($param);

 foreach my $value ($query->param($param)) {
  $params .= "$escaped_param=" . escape("$value") . "&";
 }
}

foreach (keys %{$query->{'.fieldnames'}}) {
 $params .= ".cgifields=" . escape("$_") . "&";
}

# This is the trick.
$ENV{'CONTENT_LENGTH'} = length($params);

open(my $cgi_pipe, "| $perl $cgi_script") || die("Cannot fork CGI: $!");
local $SIG{PIPE} = sub { warn "spooler pipe broke" };

print {$cgi_pipe} $params;

warn("param chars: " . length($params));

close($cgi_pipe) || warn "Error: CGI exited with value $?";

Спасибо за помощь!

0 голосов
/ 07 декабря 2009

Я не хотел этого делать, но я использовал самый прямой подход, и он работает. Я обманываю среду, полагая, что метод запроса GET, чтобы вызываемый сценарий CGI считывал свои входные данные из ожидаемой переменной среды QUERY_STRING. Вот так:

$ENV{'QUERY_STRING'} = $long_parameter_string . '&' . $ENV{'QUERY_STRING'};
$ENV{'REQUEST_METHOD'} = 'GET';

system {$perl_exec} $cgi_script;

Я беспокоюсь о потенциальных проблемах, которые это может вызвать, но я не могу думать о том, что это повредит, и до сих пор это работает хорошо. Но, поскольку я волнуюсь, я решил спросить у орды, видели ли они какие-либо потенциальные проблемы:

Есть ли проблемы при обработке запроса POST как запроса GET на сервере

Я сохраню пометку как официальный ответ, пока люди не подтвердят или, по крайней мере, не обсудят это в вышеуказанном посте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...