2014-10-29 1 views
0

Я разрабатываю веб-службу на PHP, где я использую стандартный класс PHP SoapServer с WSDL-файлом, предоставленным моим клиентом, но мне также нужно использовать буферизацию вывода для «убирать», ответ SOAP, который генерирует PHP (добавление некоторых отсутствующих пространств имен, добавление xmlns="" к нескольким тегам и другим небольшим, но необходимым деталям).
Проблема заключается в том, что когда я использую явную буферизацию вывода (ob_start(), ob_end_flush() ...), любое исходящее сообщение с моего сервера обрезается, независимо от его размера (я тестирую в диапазоне около 2 КБ-50 КБ). Когда я не использую явную буферизацию вывода, клиент получает полный ответ SOAP, но поскольку те данные, о которых я упоминал, не были исправлены, формат не совсем прав.
Вот код моего сервера:Сообщения веб-службы PHP, усеченные буферизацией вывода

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 

Как вы можете видеть, я попытался использовать высокое значение для параметра ob_start()$chunk_size и добавление 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, прежде чем он будет отправлен клиенту? Я был бы благодарен за любой совет.

+0

Где вы выписываете $ soapXml? Право на браузер? Или это приложение CLI? –

+0

Я выводил «прямо в браузер», так сказать, но это действительно клиентская программа (SoapUI). Моя серверная программа получает запрос SOAP от клиента через http и возвращает ответ через http. Этот ответ - результат, с которым у меня возникают проблемы. –

+0

Возможно, браузер неправильно отображает xml-теги, и вы не избегаете их. Вы сказали, что успешно свалили документ на диск. Вы пытались открыть исходный код страницы? –

ответ

2

Видимо, проблема заключалась в том, что я отпускал 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 

Огромное спасибо Валентину Родыгиным за большую помощь в поиске источника моих проблем!

Смежные вопросы