Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

no SOAPAction header! #308

Open
fcojavierdomenech opened this issue May 22, 2020 · 3 comments
Open

no SOAPAction header! #308

fcojavierdomenech opened this issue May 22, 2020 · 3 comments

Comments

@fcojavierdomenech
Copy link

fcojavierdomenech commented May 22, 2020

I'm getting SoapFault: WSWS3147E: Error: no SOAPAction header! when using the vcr.

I'm doing the call this way, trying to pass the SOAPAction someway so the vcr receives it as a parameter:

$response = $this->soapClient->__soapCall("trataPeticion", array($params), ['soapaction' => 'trataPeticion'], new SoapHeader('somthing', 'something', 'something'));

Still no luck, if I edit the vendor/php-vcr/php-vcr/src/VCR/LibraryHooks/SoapHook.php file and add on line 77:

if ($action == "") {
            $action = "something";
}

Then it works, am I doing anything wrong?

@andriuspetrauskis
Copy link

Hi @vivoconunxino, what is the version of your soap server?

@fcojavierdomenech
Copy link
Author

fcojavierdomenech commented May 27, 2020

Hi @andriuspetrauskis. It uses <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> so I think it's 1_1. This is the WSDL

@ghost
Copy link

ghost commented Apr 4, 2021

I think that I have found the problem. In normal curl requests an empty SOAPAction header is formatted like so:
SOAPAction;

this package uses the CurlHelper::setCurlOptionOnRequest function in src/VCR/Util/CurlHelper.php to set the curl options when the curl_setopt function is overridden in src/VCR/LibraryHooks/CurlHook.php:363

the setCurlOptionOnRequest function is as follows:

/**
     * Sets a cURL option on a Request.
     *
     * @param Request  $request    request to set cURL option to
     * @param int      $option     cURL option to set
     * @param mixed    $value      value of the cURL option
     * @param resource $curlHandle cURL handle where this option is set on (optional)
     */
    public static function setCurlOptionOnRequest(Request $request, int $option, $value, $curlHandle = null): void
    {
        switch ($option) {
            case \CURLOPT_URL:
                $request->setUrl($value);
                break;
            case \CURLOPT_CUSTOMREQUEST:
                $request->setCurlOption(\CURLOPT_CUSTOMREQUEST, $value);
                break;
            case \CURLOPT_POST:
                if (true == $value) {
                    $request->setMethod('POST');
                }
                break;
            case \CURLOPT_POSTFIELDS:
                // todo: check for file @
                if (\is_array($value)) {
                    foreach ($value as $name => $fieldValue) {
                        $request->setPostField($name, $fieldValue);
                    }

                    if (0 == \count($value)) {
                        $request->removeHeader('Content-Type');
                    }
                } elseif (!empty($value)) {
                    // Empty values are ignored to be consistent with how requests are read out of
                    // storage using \VCR\Request::fromArray(array $request).
                    $request->setBody($value);
                }
                $request->setMethod('POST');
                break;
            case \CURLOPT_HTTPHEADER:
                foreach ($value as $header) {
                    $headerParts = explode(': ', $header, 2);
                    if (!isset($headerParts[1])) {
                        $headerParts[0] = rtrim($headerParts[0], ':');
                        $headerParts[1] = '';
                    }
                    $request->setHeader($headerParts[0], $headerParts[1]);
                }
                break;
            case \CURLOPT_FILE:
            case \CURLOPT_HEADER:
            case \CURLOPT_WRITEFUNCTION:
            case \CURLOPT_HEADERFUNCTION:
            case \CURLOPT_UPLOAD:
                // Ignore header, file and writer functions.
                // These options are stored and will be handled later in handleOutput().
                break;
            default:
                $request->setCurlOption($option, $value);
                break;
        }
    }

case \CURLOPT_HTTPHEADER trims the ':' from the end of $headerParts[0] but does nothing if that value contains a ';'. So if the value of $header in that instance is "SOAPAction;" then you end up with a header like this: SOAPAction;: '' as you can see in my cassette file:


-
    request:
        method: POST
        url: 'http://10.0.0.4/flexnet/services/v3/EntitlementOrderService'
        headers:
            Host: 10.0.0.4
            Expect: ''
            Accept-Encoding: ''
            User-Agent: GuzzleHttp/7
            SOAPAction;: ''
            Content-Type: 'text/xml; charset="utf-8"'
            Authorization: 'Basic QURNTmFkbWluOjNPTWt1YWd1aDg='
            Accept: ''
        body: ""
    response:

My proposal is to update that function in CurlHelper.php as follows:

    /**
     * Sets a cURL option on a Request.
     *
     * @param Request  $request    request to set cURL option to
     * @param int      $option     cURL option to set
     * @param mixed    $value      value of the cURL option
     * @param resource $curlHandle cURL handle where this option is set on (optional)
     */
    public static function setCurlOptionOnRequest(Request $request, int $option, $value, $curlHandle = null): void
    {
        switch ($option) {
            case \CURLOPT_URL:
                $request->setUrl($value);
                break;
            case \CURLOPT_CUSTOMREQUEST:
                $request->setCurlOption(\CURLOPT_CUSTOMREQUEST, $value);
                break;
            case \CURLOPT_POST:
                if (true == $value) {
                    $request->setMethod('POST');
                }
                break;
            case \CURLOPT_POSTFIELDS:
                // todo: check for file @
                if (\is_array($value)) {
                    foreach ($value as $name => $fieldValue) {
                        $request->setPostField($name, $fieldValue);
                    }

                    if (0 == \count($value)) {
                        $request->removeHeader('Content-Type');
                    }
                } elseif (!empty($value)) {
                    // Empty values are ignored to be consistent with how requests are read out of
                    // storage using \VCR\Request::fromArray(array $request).
                    $request->setBody($value);
                }
                $request->setMethod('POST');
                break;
            case \CURLOPT_HTTPHEADER:
                foreach ($value as $header) {
                    $headerParts = explode(': ', $header, 2);
                    if (!isset($headerParts[1])) {
                        $headerParts[0] = rtrim($headerParts[0], ':');
                        $headerParts[1] = '';
                        if (strpos($headerParts[0], ';') !== false) {       // new lines here
                            $headerParts[0] = rtrim($headerParts[0], ';');
                            $headerParts[1] = ';';
                        }                                                   // to here
                    }
                    $request->setHeader($headerParts[0], $headerParts[1]);
                }
                break;
            case \CURLOPT_FILE:
            case \CURLOPT_HEADER:
            case \CURLOPT_WRITEFUNCTION:
            case \CURLOPT_HEADERFUNCTION:
            case \CURLOPT_UPLOAD:
                // Ignore header, file and writer functions.
                // These options are stored and will be handled later in handleOutput().
                break;
            default:
                $request->setCurlOption($option, $value);
                break;
        }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants