php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #49853 Soap Client stream context header option ignored
Submitted: 2009-10-12 23:18 UTC Modified: 2012-03-21 14:38 UTC
Votes:19
Avg. Score:4.7 ± 0.6
Reproduced:18 of 18 (100.0%)
Same Version:4 (22.2%)
Same OS:6 (33.3%)
From: rumana024 at yahoo dot com Assigned: dmitry (profile)
Status: Closed Package: SOAP related
PHP Version: 5.2SVN-2009-10-12 (SVN) OS: Windows XP
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: rumana024 at yahoo dot com
New email:
PHP Version: OS:

 

 [2009-10-12 23:18 UTC] rumana024 at yahoo dot com
Description:
------------
Hi:


I am using PHP Soap PHP-SOAP/5.2.9-2 to connect to a web service. Part of the reqiurment is that , few http headers need to be as part of the request, but not part of the soap envelope. I am using the stream context option and add the http headers with that option. Unfortunately, the stream context is not being read at all. 




Reproduce code:
---------------
Here is my code 


$opts = array(
  'https'=>array(
    'method'=>"GET",
    'header'=>'X-SECURITY-USERID: seller_1253314668_biz_api1.x.com\r\n' . 
              'X-SECURITY-PASSWORD: 1253314679\r\n' .
	      'X-SECURITY-SIGNATURE: AtQaNHC.hbpghF5uGCRO99PVY6a2ASO58V7ki3.SAb3vQzBlBAxEyi0b\r\n' .
              'X-SERVICE-VERSION: 1.2.0\r\n' .
	      'X-MESSAGE-PROTOCOL: SOAP11\r\n' .
              'X-REQUEST-SOURCE: PLATFORM_JAVA_SOAP_SAMPLE_V1\r\n' .
              'X-APPLICATION-ID: APP-80W284485P519543T\r\n'));


$context = stream_context_create($opts);


$soapClient = new SoapClient(null,array('location' => "https://svcs.sandbox.x.com/AP/Method1/",
                                        'uri' => "http://svcs.x.com/types/ap", 
                                        'soap_version' => SOAP_1_1, 'trace' => 1, 'stream_context' => $context));



 

Expected result:
----------------
Security Credential are going as HTTP Headers and the Http headers are contained in the context parameter. I get the result Invalid User name and Password. So the context is not going through at all.
I know for sure the credentials are valid.

I know other option parameter like 'location', 'uri' are working.Please advice how to fix this problem.


Patches

fix-soap-stream-context-http-header-overwrite (last revision 2011-11-15 20:27 UTC by michaelclark at zagg dot com)

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-10-13 10:48 UTC] sjoerd@php.net
Thank you for your bug report.

Please try 'http' as wrapper name instead of 'https'.
 [2009-10-13 18:03 UTC] rumana024 at yahoo dot com
$headers = array('X-USERID: user_1253314668.com\r\n', 
                'Content-type: application/x-www-form-urlencoded\r\n',
                'X-PASSWORD: 1253314679\r\n',
                'X-SIGNATURE: AtQaNHC.hbpghF5uGCRO99PVYV7ki3.SAb3vQzBlBAxEyi0b\r\n',
                'X-VERSION: 1.2.0\r\n',
	        'X-PROTOCOL: SOAP11\r\n',
                'X-SOURCE: PHP_SOAP_SAMPLE_V1\r\n');	

$context = stream_context_create(array('http' => array('header' => $headers)));

$soapClient = new SoapClient(null,array('location' => "https://svcs.sandbox.com/Method1/", 
                                        'uri' => "http://x.x.com/types/test", 
                                        'soap_version' => SOAP_1_1,'trace' => 1, 'stream_context' => $context)); 



//Constructing the Payload
$param = "the payload"
$result = $soapClient->Method1($params);


I have changed the wrapper from https to http. Also made the header an array. Still the same error. I do not see the http header with other http headers when print the $soapClient->_getLastRequestHeaders(). Please advice how to resolve the issue.
 [2009-10-14 19:37 UTC] rumana024 at yahoo dot com
Is this a PHP bug? If not,can you please post some sample !working! code on creating a SOAP Client with the stream_context option and http header(in this case https). Those headers can be seen as the part of the http request headers. I have pretty much tried different suggestions that I read on diffrent threads on www and php.net to make a successful soap call.    

Regards
RI
 [2009-10-14 23:31 UTC] rumana024 at yahoo dot com
I see a conversation at http://aspn.activestate.com/ASPN/Mail/Message/php-dev/3710449 about Transfer-Encoding: chunked and its affect on stream_context parameters. Is this the problem?
 [2009-10-15 18:48 UTC] rumana024 at yahoo dot com
I have solved my issue... Yahoooooooooo...
I switched to php5.3. And I now the http headers are passing through.
 [2011-05-09 17:09 UTC] vidalis dot aris at gmail dot com
Using php5.3.6 i couldn't pass extra HTTP headers to the SOAP request.
stream_context_create appears to get ignored

[VERSION]
PHP 5.3.6 with Suhosin-Patch (cli) (built: Apr 18 2011 11:14:25)
Copyright (c) 1997-2011 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2011 Zend Technologies

[CODE]
$context = stream_context_create(array('http' => array('header' => "token: 
85E91AAC-7A4A-11E0-B46B-78E7D1E19752\r\n")));

        $soapparams = array(                    
                                                'stream_context' => $context,
                                                'trace' => 1,
                                                'exceptions' => 1,
                                                'soap_version' => SOAP_1_2,
                                                'encoding' => 'UTF-8',
                                                'features' => 
SOAP_SINGLE_ELEMENT_ARRAYS
                                );
$client = new SoapClient($wsdl,$soapparams);

[REQUEST HEADERS]
POST /SocialMetadataService HTTP/1.1
Host: test.host.com:9080
Connection: Keep-Alive
User-Agent: PHP-SOAP/5.3.6
Content-Type: application/soap+xml; charset=utf-8; action="urn:getObjectID"
Content-Length: 331
 [2011-09-22 10:14 UTC] dave dot wilcock at gmail dot com
[VERSION]
PHP 5.3.2 (cli) (built: Apr 27 2010 20:28:18)
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
    with eAccelerator v0.9.6.1, Copyright (c) 2004-2010 eAccelerator, by 
eAccelerator

[CODE]
$str_auth_header = "Authorization: Bearer ". $str_token;
      
$arr_context = array('http' =>array('header' => $str_auth_header));

$obj_context = stream_context_create($arr_context);

$arr_options = array (
   'soap_version' => 'SOAP_1_2',
   'encoding' => 'UTF-8',
   'exceptions' => true,
   'trace' => true,
   'cache_wsdl' => 'WSDL_CACHE_NONE',
   'stream_context' => $obj_context
);

$this->obj_connection = new SoapClient(self::STR_BASE_URL, $arr_options);

[EXPECTED]
Authorization header in HTTP request

[GOT]
No Authorization header in HTTP request

[WORKAROUND/CODE]
ini_set('user_agent', 'PHP-SOAP/' . PHP_VERSION . "\r\n" . $str_auth_header);

[COMMENT]
No idea why appending the user agent string with the headers would work, but it 
seemingly does. Bizarre.
 [2011-10-27 08:49 UTC] richard dot deguilhem at laposte dot net
I have the same problem with php 5.2.6 To 5.3.8.

[VERSION]

[CODE
class CMyClass extends SoapClient
{
 
    public function CMyClass($sWsdlUri = '',$aOptions = array())
    {
        $aOptions['stream_context'] = stream_context_create(array( 'http' => array('header'=>"foo: bar\r\n")));
 
        parent::__construct($sWsdlUri, $aOptions);
    }
 
    public function callSoapActionX()
    {
        $aParams = array(...);
        return $this->__soapCall('GetTokenSession', $aParams);
    }
}

[REQUEST HEADERS]
POST  HTTP/1.0
Host: 127.0.0.1:8052
Connection: Keep-Alive
User-Agent: PHP-SOAP/5.3.8
Content-Type: application/soap+xml; charset=utf-8; action="GetTokenSession"
Content-Length: 532
 [2011-11-04 19:00 UTC] michaelclark at zagg dot com
I suspect that my problem is the same as the submitter, so I'm adding this as a comment instead of as a new issue. Again, this has to do with SoapClient, stream_context_create, and custom http headers.

Simple TESTCASE:
#!/usr/bin/php
<?php
$wsdl = 'http://www.w3schools.com/webservices/tempconvert.asmx?WSDL';
$apikey = 'this-must-still-be-here';
$c = stream_context_create(array(
        'http' => array(
                'header' => "apikey: this-must-still-be-here",
        )
));
var_dump(stream_context_get_options($c));
$soap = new SoapClient($wsdl, array('stream_context' => $c));
var_dump(stream_context_get_options($soap->_stream_context));
unlink('/tmp/wsdl-'.get_current_user().'-d4e1ad3ff31424862843f4814eade4a8');
?>

As you can see from running the code, if the SoapClient needs to download a new WSDL (function get_sdl() called on line 2679 of ext/soap/soap.c - PHP source code is version 5.3.8, function defined at line 3154 of ext/soap/php_sdl.c), AND also the 'protocol_version' option isn't explicitly set in the stream_context (line 3267, file ext/soap/php_sdl.c), it sets the 'protocol_version' option (3271), and sets up a new header - "Connection: close" (3273). The following if statement (3276) sets the http "header" option to the value of that string (3286) - effectively overwriting any custom headers that were supplied.

The following if statement (3291) might be making an effort to prevent this (3294,3307), but is ineffective (operating on a pointer to the original I suspect; any copy should be made at the point of initialization, and this might not be copying the context structure itself at all).

So - userland mitigation:
Set the http 'protocol_version' explicitly to 1.1 in your code, and append the "\r\nConnection: close" header to your custom headers.
example:
$context = stream_context_create(array(
    'http'=>array(
        'protocol_version' => 1.1,
        'header' => "token: 85E91AAC-7A4A-11E0-B46B-78E7D1E19752\r\n" .
                    "Connection: close"
    )
));

Thoughts about fixing it:
It appears to be safe to pass the Connection: close header implicitly - so the simple solution of appending instead of replacing the custom headers could be good enough, without having to copy, backup, and restore the original context itself. Should that be the easier solution it should be preferred. If the simple solution is used, it would also be nice to have it in the docs.
 [2011-11-04 21:15 UTC] michaelclark at zagg dot com
In the TESTCASE, please replace the last line with

unlink(ini_get('soap.wsdl_cache_dir').DIRECTORY_SEPARATOR.'wsdl-'.get_current_user().'-'.md5($wsdl));

if you need something a little bit more portable, or to change the WSDL location.
 [2011-11-11 23:30 UTC] michaelclark at zagg dot com
So, here's an SVN diff against trunk, seems to be working for the test case I posted. This patch should apply cleanly against anything dating back to the current release, PHP 5.3.8. This patch follows the simple mitigation strategy proposed above. There was an error in the trunk for one of the soap test cases, but it was there even after reverting the patch.

Index: ext/soap/php_sdl.c
===================================================================
--- ext/soap/php_sdl.c  (revision 319075)
+++ ext/soap/php_sdl.c  (working copy)
@@ -3270,7 +3270,7 @@
                ZVAL_DOUBLE(http_version, 1.1);
                php_stream_context_set_option(context, "http", "protocol_version", http_version);
                zval_ptr_dtor(&http_version);
-               smart_str_appendl(&headers, "Connection: close", sizeof("Connection: close")-1);
+               smart_str_appendl(&headers, "Connection: close\r\n", sizeof("Connection: close\r\n")-1);
        }
 
        if (headers.len > 0) {
@@ -3278,6 +3278,8 @@
 
                if (!context) {
                        context = php_stream_context_alloc(TSRMLS_C);
+               } else if (php_stream_context_get_option(context, "http", "header", &tmp) != FAILURE) {
+                       smart_str_appendl(&headers, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
                }
 
                smart_str_0(&headers);
 [2011-11-16 17:52 UTC] felipe@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: dmitry
 [2012-03-21 14:38 UTC] dmitry@php.net
-Status: Assigned +Status: Closed
 [2012-03-21 14:38 UTC] dmitry@php.net
This bug has been fixed in SVN.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.


 [2014-10-07 23:28 UTC] stas@php.net
Automatic comment on behalf of dmitry@zend.com
Revision: http://git.php.net/?p=php-src-security.git;a=commit;h=657547f8c4758efcf85c73fec6d7fd8b3983d7cb
Log: Fixed bug #49853 (Soap Client stream context header option ignored)
 [2014-10-07 23:39 UTC] stas@php.net
Automatic comment on behalf of dmitry@zend.com
Revision: http://git.php.net/?p=php-src-security.git;a=commit;h=657547f8c4758efcf85c73fec6d7fd8b3983d7cb
Log: Fixed bug #49853 (Soap Client stream context header option ignored)
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Dec 03 17:01:29 2024 UTC