Soap Response Error (Yii web service) - php

Can anyone help me with my problem?
I'm trying to get data from my web service and sometimes server responses with invalid XML.
I've noticed that it depends on data size. When response reach a certain size it ends with </SOAP-ENV:Envelop instead of </SOAP-ENV:Envelope>.
Here is my example code: client and server in one controller.
Method "success" works fine, but similiar method "fail" does not.
Even more: for nginx and php-fpm "success" method fails too (for apache with php_mod "success" method works).
<?php
class SoapController extends CController
{
public function actions()
{
return array('wsdl' => array('class' => 'CWebServiceAction'));
}
private function getData($size)
{
return array_fill(0, $size, '18ad96e6-5526-11e0-9c19-00248c654095');
}
/**
* #return array
* #soap
*/
public function success()
{
return $this->getData(104);
}
/**
* #return array
* #soap
*/
public function fail()
{
return $this->getData(105);
}
public function actionTest()
{
$client = new SoapClient($this->createAbsoluteUrl('wsdl'), array('trace' => true));
$methods = array('success', 'fail');
foreach ($methods as $method) {
try {
$result = call_user_func(array($client, $method));
$result = count($result);
} catch (SoapFault $ex) {
$result = $ex->getMessage();
}
echo $method . ' result: ' . $result . '<br>';
echo $method . ' response: <br>' . htmlspecialchars($client->__getLastResponse()) . '<br><br>';
}
}
}
Software versions:
Ubuntu Server 12.10
Yii 1.1.13
PHP 5.4.6
Apache 2.2.22
Nginx 1.2.1

Problem was in controller file.
It has UTF-8 charset with BOM. After removing BOM it works fine.

Related

Fatal Error on using $exception variable in render() Method in App\Exceptions\Handler.php

I am new to Laravel and have an Issue regarding the Handler.php File.
I am trying to create a class that takes an exceptions and transforms it into a JSON Response.
Sadly though, upon calling the constructor a series of Errors are thrown:
(ErrorErrorErrorErrorErrorErrorErrorErrorErrorErrorErrorSymfony\Component\ErrorHandler\Error\FatalError)
My code:
render() in Handler.php:
public function render($request, Throwable $exception)
{
$errorResource = new ErrorResource($exception);
return $errorResource->getJsonResponse();
}
class ErrorResource in ErrorResource.php:
<?php
namespace Transformers;
use Throwable;
class ErrorResource
{
private $exception;
private $defaultCodes = [TypeError::class => 400];
private $defaultMessages = [TypeError::class => 'Untgültige URL Parameter'];
function __construct(Throwable $exception)
{
$this->exception = $exception;
}
public function getJsonResponse($exception)
{
$codeToThrow = 500;
$messageToThrow = "Internal Server Error";
$type = get_class($this->exception);
if (empty($exception->getCode())) {
$codeToThrow = $this->defaultCodes[$type];
} else {
$codeToThrow = $exception->getCode();
}
if (empty($exception->getMessage())) {
$messageToThrow = $this->defaultMessages[$type];
} else {
$messageToThrow = $exception->getMessage();
}
return response()->json(array(
'Type' => $type,
'Message' => $messageToThrow
), $codeToThrow);
}
}
I have also tried to move the method getJsonResponse() to the Handler.php file and call it from there, but without any luck.
I am really confused as to why I am not allowed to do certain things with the $exception variable (I have also tried to create a clone of this object - but the same error occures)
I hope you can help me resolving this issue,
Greetins,
Franz
The issue is, that PHP is call by value. That is why it is implicitely trying to clone an unclonable object -> Error. To resolve this issue one can use wrapper objects, but I decided to simply use call by reference (https://www.javatpoint.com/php-call-by-reference)

How to unit test this try catch

I'm trying to 100% code coverage my service. Here is a method:
<?php
* Search to public accounts.
*
* #param string $query
*
* #return TwitterResponse
*/
public function search(string $query): TwitterResponse
{
try {
$response = $this->client->getClient()->get(UserEnum::URI_SEARCH, [
'query' => ['q' => $query,]
]);
} catch (ClientException $e) {
$response = $e->getResponse();
}
return new TwitterResponse($response);
}
It simply GET a user with Twitter API.
In my opinion, I should develop two tests : one for the try and one for the catch. Bellow is my test for the try.
<?php
/**
* #return void
*/
public function setUp(): void
{
$this->prophet = new Prophet();
$this->client = $this->prophet->prophesize(Client::class);
$this->client->get(Argument::any(), Argument::any())->willReturn(new TwitterResponse(new Response()));
$this->client->post(Argument::any(), Argument::any())->willReturn(new TwitterResponse(new Response()));
$this->twitterClient = $this->prophet->prophesize(TwitterClient::class);
$this->twitterClient->getClient()->willReturn($this->client);
$this->userService = new UserService($this->twitterClient->reveal());
}
/**
* Tests if a TwitterResponse is returned with status HTTP_OK.
*
* #return void
*/
public function testGetOk(): void
{
$actual = $this->userService->get('');
$this->assertEquals(get_class($actual), TwitterResponse::class);
$this->assertEquals(HttpResponse::HTTP_OK, $actual->getStatusCode());
}
Bellow the code coverage of get().
As you can see, I don't test the catch case. How can I do it ? I already tried to mock a 404 HTTP response catch something but it did not work. Do you have an idea of how I can do it ?
Thanks.
EDIT : I tried this for the catch case ->
public function testGetKo(): void
{
$response = new TwitterResponse(new Response(HttpResponse::HTTP_NOT_FOUND));
$response->setStatusCode(HttpResponse::HTTP_NOT_FOUND);
$this->client = $this->prophet->prophesize(Client::class);
$this->client->get(Argument::any(), Argument::any())->willReturn($response);
$this->twitterClient = $this->prophet->prophesize(TwitterClient::class);
$actual = $this->userService->get('');
$this->assertEquals(get_class($actual), TwitterResponse::class);
$this->assertEquals(HttpResponse::HTTP_NOT_FOUND, $actual->getStatusCode());
}
Phpunit returns : Failed asserting that 200 matches expected 404. It seems that my mock client doesn't work well.
I know, it's an old post, but..
Maybe try to mock client, and when it's triggered throw exception?
So when you throw ClientException, you should check for TwitterResponse result. And when you throw DummyException, you should expect DummyException.
This is untested, as I don't usually use prophecy, but I do simialry with other mocking frameworks:
public function testGetKo(): void
{
// ... other setup
$exception = new ClientException();
$this->client = $this->prophet->prophesize(Client::class);
$this->client->get(Argument::any(), Argument::any())->willThrow($exception);
And you will likely add $this->expectException(ClientException::class); before you run the function being tested.

how to call a soap webservice with struct input parameters?

I want to interact with SOAP (as a client) and am not able to get the right syntax for input parameters. I have a WSDL URL that I have tested it with SoapUI and it returns result properly. There are two functions defined in the WSDL, but I only need one ("FirstFunction" below). Here is the script I run to get information on the available functions and types:
$client = new SoapClient("http://example.com/webservices?wsdl");
var_dump($client->__getFunctions());
var_dump($client->__getTypes());
And here is the output it generates:
array(
[0] => "FirstFunction Function1(FirstFunction $parameters)",
[1] => "SecondFunction Function2(SecondFunction $parameters)",
);
struct Amount {
anyURI Identifier;
Information charge;
string referenceCode;
}
struct Information {
string description;
decimal amount;
string code;
}
According to above result I developed my client with nusoap and php as below:
class Information
{
public $description;
public $amount;
public $code;
}
class Amount {
public $Identifier;
public $charge;
public $referenceCode;
}
$charge = new Information();
$charge->description = "ROUTE=XXX|abc=".$code;
$charge->amount = "NULL";
$charge->code = $chargecode;
$params = new Amount();
$params->Identifier =$num;
$params->charge = $charge;
$params->referenceCode = $refcode;
$header = new SoapHeader('key', $key);
$client->__setSoapHeaders($header);
try
{
$res = $client->__call('charge',array('parametrs'=>$params));
print_r($res->return);
}
catch(PDOException $e)
{
print_r($e->getMessage());
}
I get the following error as result:
Uncaught SoapFault exception: [soapenv:Server] unknown
In my opinion the best way to achieve it is to use a WSDL to php generator such as the PackageGenerator project. It abstracts the whole process so you only deal with objects without really worrying about SOAP.

How to pass single tag header in php soap client for wcf?

I am trying to consume WCF service from PHP . I need to pass a header field in soap client of PHP in order to consume it. Soap header will be something like this:
<header>
<LisenseKey>Lisense key goes here</LisenseKey>
</header>
The namespace for LisenseKey element is "http://mylinsensekeynamespace".
The method I want to consume in WCF is as follows:
public string function GetMessage(string name)
{
return "Hello , "+name;
}
Before the service is configured to validate header, I was consuming the service from PHP as follows and it is working perfectly:
try{
$client = new SoapClient("http://localhost:8181/?wsdl");
$param = new stdClass();
$param->name = "My Name";
$webService = $client->GetMessage($param);
print_r($webService);
}
catch(Exception $e)
{
echo $e->getMessage();
}
When after the service is configured to validate license key in header, I am trying to consume it like this and it is not working yet:
try{
$client = new SoapClient("http://localhost:8181/?wsdl");
$actionHeader = new SoapHeader("http://mycustomheader",'LisenseKey',"lisense key",true);
$client->__setSoapHeaders($actionHeader);
$param = new stdClass();
$param->name = "My Name";
$webService = $client->GetMessage($param);
print_r($webService);
}
catch(Exception $e)
{
echo $e->getMessage();
}
I already tried in so many different ways from online articles. How can I consume it? WCF service is using BasicHttpBinding and SOAP version should be 1.1. How to pass the header information to consume the service?
Following is the .NET WCF service code that validate for LicenseKey soap header for every request.
public class MyServiceMessageInspector : System.ServiceModel.Dispatcher.IDispatchMessageInspector
{
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel,
System.ServiceModel.InstanceContext instanceContext)
{
if (request.Headers.FindHeader("LisenseKey", "") == -1)
{
throw new FaultException("Lisense Key Was Not Provided");
}
var lisenseKey = request.Headers.GetHeader<string>("LisenseKey", "http://mycustomheader.com");
if (string.IsNullOrEmpty(lisenseKey))
{
throw new FaultException("Lisnse key should not be empty");
}
if (lisenseKey != "12345x")
{
throw new FaultException("Lisense key is not valid");
}
return instanceContext;
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
}
}
public class MyServiceMessageInspectorBehaviour : Attribute, System.ServiceModel.Description.IServiceBehavior
{
public void AddBindingParameters(System.ServiceModel.Description.ServiceDescription serviceDescription,
System.ServiceModel.ServiceHostBase serviceHostBase,
System.Collections.ObjectModel.Collection<System.ServiceModel.Description.ServiceEndpoint> endpoints,
System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(System.ServiceModel.Description.ServiceDescription serviceDescription,
System.ServiceModel.ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
{
foreach (var endpointDispatcher in channelDispatcher.Endpoints)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new MyServiceMessageInspector());
}
}
}
public void Validate(System.ServiceModel.Description.ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
}
}
Try calling the WCF service like this : $client->__soapCall("GetMessage", $param, NULL, $header);

Should I check if array/collection value exists before trying to get it?

Should I check if a key exists and then get it or just get it (when I need to get it, not check if its set)?
What is more reliable? safer? faster?
Examples:
1) PHP redis (https://github.com/nicolasff/phpredis)
if ($redis->exists('key'))
echo $redis->get('key');
// VS
if ($value = $redis->get('key'))
echo $value;
2) PHP phalcon cookies(http://docs.phalconphp.com/pt/latest/reference/cookies.html)
if ($this->cookies->has('remember-me'))
echo $this->cookies->get('remember-me')->getValue()
// VS
if ($value = $this->cookies->get('remember-me')->getValue())
echo $value;
Thank you!
My interpretation of this problem is:
I don't like writing things like
if ($value = $redis->get('key'))
echo $value;
it makes code unclear.
Also, why is checking if variable exists so important? Because it simplifies control flow.
Let's consider that you're grabbing some data from service to render it on page. You can write low quality code with multiple ifs, but you can also try something like this:
offerServiceImpl.php
class offerServiceImpl implements offerService {
//... (some methods)
/**
* #param int $offerId
* #return Offer
* #throws InvalidArgumentException
* #throws RuntimeException
*/
public function getOffer($offerId)
{
if (!$offerId || !is_numeric($offerId)) {
throw new InvalidArgumentException("Invalid offer id: " . $offerId);
}
$offer = $this->offerDao->get($offerId);
if (!$offer) {
//could be your own exception class
throw new RuntimeException("Could not found offer " . $offerId);
} else {
return $offer;
}
}
}
offersControler.php
class offersController extends AbstractController{
public function index($id){
//... some code
try{
$offer = $this->offerService->getOffer($id);
} catch (InvalidArgumentException $ex) {
//log error, perform redirect to error 500
} catch (RuntimeException $ex){
//log another error, perform redirect to error 404
} catch (Exception $ex){
//log error, perform redirect to error 500
}
}
}

Categories