Я занимаюсь разработкой веб-службы на PHP, в которой я использую стандартный класс PHP SoapServer с файлом WSDL, предоставленным моим клиентом, но мне также нужно использовать буферизацию вывода, чтобы «привести в порядок» ответ SOAP, который генерирует PHP (добавив некоторые недостающие пространства имен , добавив xmlns=""
на несколько тегов и других мелких, но необходимых деталей).
Проблема в том, что когда я использую явную буферизацию вывода (ob_start()
, ob_end_flush()
…) любое исходящее сообщение с моего сервера усекается независимо от его размера (я тестирую в диапазоне от 2 до 50 КБ). Когда я не использую явную буферизацию вывода, клиент получает полный ответ SOAP, но, поскольку те детали, которые я упомянул, не были исправлены, формат не совсем правильный.
Вот код моего сервера:
if (!extension_loaded("soap")) {
dl("php_soap.dll");
}
//Disable wsdl caching
ini_set("soap.wsdl_cache_enabled", "0");
//Get SOAP message from client
$input_msg = file_get_contents("php://input");
//Create SoapServer object with url to the .wsdl file
$server = new SoapServer(WSDL_FILE_URL, array('encoding' => 'UTF-8', 'actor' => SERVER_URL));
//Set the class that will handle every possible request form the client
$server->setClass("ServerHandler",$input_msg);
//Before I let the server handle the request and return the response to the client,
//I turn on output buffering so I can fix its format
ob_start(NULL, 1<<20);
$server->handle(); //let the server handle the request and write the response to the buffer
$soapXml = ob_get_contents(); //I get the response from the output buffer
ob_end_clean(); //clear the output buffer of its content
//this function does all those small format fixes to the SOAP response that PHP produces
$soapXml=fixSoapResponseFormat($soapXml);
echo $soapXml;//put the correct SOAP response in the output buffer
ob_end_flush();//flush the output buffer and turn off buffering
flush();//this supossedly flushes lower level buffers, just in case
Как видите, я попытался использовать высокое значение для $chunk_size
параметр ob_start()
и добавление flush()
после ob_end_flush()
, так, на всякий случай. Я также пытался установить output_buffering = On
на php.ini (который якобы включает неограниченный выходной буфер) и настройки LimitRequestFieldSize
а также LimitRequestLine
до 5500000 на Apache, но безрезультатно.
Я пытался сбросить на диск содержимое $soapXml
после очистки буфера, и сообщение завершено, поэтому я думаю, что проблема должна быть в echo $soapXml;
линия или в очистке буфера сразу после него.
Я использую Apache с PHP 5.3 для запуска сервера и SoapUI 5 в качестве клиента для его тестирования. Я также использую WS-Security во всех коммуникациях между сервером и клиентом (в случае необходимости).
Кто-нибудь знает, как решить эту проблему с буферизацией SOAP-сообщений? Может быть, есть другой способ перехватить и изменить ответ SOAP, который генерирует PHP перед отправкой клиенту? Буду благодарен за любой совет.
Очевидно, проблема заключалась в том, что я позволял PHP генерировать SOAP-сообщение с его заголовком http в $server->handle();
линии, но потом я записывал его в буфер и изменение его размера без обновления Content-Length
заголовок http, поэтому сообщение было отправлено, но урезано до его первоначального размера.
Итак, вот правильно работающий код:
if (!extension_loaded("soap")) {
dl("php_soap.dll");
}
//Disable wsdl caching
ini_set("soap.wsdl_cache_enabled", "0");
//Get SOAP message from client
$input_msg = file_get_contents("php://input");
//Create SoapServer object with url to the .wsdl file
$server = new SoapServer(WSDL_FILE_URL, array('encoding' => 'UTF-8', 'actor' => SERVER_URL));
//Set the class that will handle every possible request form the client
$server->setClass("ServerHandler",$input_msg);
//Before I let the server handle the request and return the response to the client,
//I turn on output buffering so I can fix its format
ob_start(NULL, 1<<20);
$server->handle(); //let the server handle the request and write the response to the buffer
$soapXml = ob_get_contents(); //I get the response from the output buffer
ob_end_clean(); //clear the output buffer of its content
//this function does all those small format fixes to the SOAP response that PHP produces
$soapXml=fixSoapResponseFormat($soapXml);
header('Content-Length: '.strlen($soapXml));//**UPDATE THE LENGTH HEADER**
echo $soapXml;//put the correct SOAP response in the output buffer
ob_end_flush();//flush the output buffer and turn off buffering
flush();//this supossedly flushes lower level buffers, just in case
Большое спасибо Валентину Родыгину за его огромную помощь в поиске источника моих неприятностей!
Других решений пока нет …