Could not connect to host soap exception - php

I am using SOAP in a php script to call a web service from a Linux Centos 6 server. In this week I have been getting could not connect to host error from soapCall method. Of course this exception does not happen all the time but I see this exception most of the time, for example if I call soapCall 5 times, this error happens 3 times. My code is as below and I have not changed it at all for some months but recently it gets this error most of the time.
$wsdl="http://x.x.x.x:x/gw/services/Service?wsdl";
//Set key as HTTP Header
$aHTTP['http']['header'] = "key:" .$key ."\r\n";
$context = stream_context_create($aHTTP);
try
{
$client = new SoapClient($wsdl,array("soap_version" => SOAP_1_2,'trace' => 1,"stream_context" => $context));
}
catch(Exception $e)
{
return "something";
}
//I make $parametrs
try
{
$res = $client->__soapCall("send",array($parametrs));
}
catch(Exception $e)
{
print_r($e->getMessage()); //Most of the time it prints could not connect to host
}
I have read most answers to related questions here but my problem has not been solved. Also I added
ini_set("soap.wsdl_cache_enabled", "0");
ini_set("soap.wsdl_cache_ttl","0");
but nothing changed. I searched a lot about the reason and I found something about SSL but I have not found exact solution.
It must be mentioned that I can see the wsdl URL in browser and I have it's ping.

Related

Amazon MQ ActiveMQ heartbeat never sent to client stomp php

Summary
I am trying to set up heartbeats with my Consumer so it can detect a dropped connection - if the broker is rebooted for example so it may reconnect to the failover.
I tested the code with the Consumer/Dispatcher running locally and the queue running in AWS and everything worked fine. However, when moving the code to AWS the Consumer sets up heartbeats with the server/broker, but the heartbeat is either never sent by the server/broker or never received by the client/Consumer. As a result the HeartbeatException is thrown as soon as the requested server heartbeat interval has passed.
I based my code on the examples in the stomp-php-examples github
Repo: https://github.com/stomp-php/stomp-php-examples
Heartbeat example: https://github.com/stomp-php/stomp-php-examples/blob/support/version-4/src/heartbeats_server.php
My next best guess to as why this isn't working is something related to the queue config as I'm using the default config provided by AWS (I think). I have googled and searched all over about config settings for heartbeats but haven't got very far as this is a new topic. Any help would be appreciated!
Setup
Amazon MQ (ActiveMQ 5.15.14)
stomp-php 5.0 (latest version as of today)
I'm happy to provide any more details of my setup.
Code
Consumer (stripped down version)
abstract class AmqConsumerAbstract
{
/** #var StatefulStomp */
protected $consumer;
const HEARTBEAT = 5000;
public function listen(): void
{
$observer = new ServerAliveObserver();
$this->client->getConnection()->getObservers()->addObserver($observer);
$this->client->setHeartbeat(0, self::HEARTBEAT); // heartbeats setup here
// Note: the heartbeat above is longer than the read-timeout below
$this->client->getConnection()->setReadTimeout(2, 0);
$this->client->connect();
$this->consumer = new StatefulStomp($this->client);
$this->consumer->subscribe(
$this->getQueueName(),
null,
'client'
);
if (!$observer->isEnabled()) {
// we never get here so I assume everything is working OK
echo 'The Server is not supporting heartbeats.');
exit(1);
} else {
echo sprintf('The Server should send us signals every %d ms.', $observer->getInterval() * 1000);
}
try {
while (true) {
$frame = $this->consumer->read(); // I assumed this line would read the heartbeat?
// there is then some logic that deals with payload and does
// $this->consumer->begin();
// $this->consumer->ack($frame);
// $this->consumer->commit();
if ($observer->isDelayed()) {
$this->echoLog('ServerAliveObserver: Server has been delayed.');
}
}
} catch (HeartbeatException $e) {
echo 'AMQ (STOMP) Error, the server failed to send us heartbeats within the defined interval: ' . $e->getMessage()
$this->reconnect();
} catch (ConnectionException $e) {
echo $e->getMessage();
$this->reconnect();
} catch (Exception $e) {
echo 'AMQ (STOMP) Queue error: ' . $e->getMessage();
exit(1);
}
}
}
I have reproduced on a single-instance broker with version 5.15.14.
I have tried switching on STOMP debugging for the broker, but it appears the uri attribute under <transportConnector> is not allowed. The config will save but pulls out the uri attribute.
<transportConnector> Elements and Their Attributes Permitted in Amazon MQ Configurations
Working with Spring XML configuration files (xsd files)

SOAP webservice with PHP: could not connect to host

Please note that after much research I decided to write here since I couldn't pin-point the problem. Although it exists widely on the net. Sorry for that.
I'm trying to get a response using SOAP (see code below):
<?php
$param = array(
'USERID'=>'some_user',
'PASSWORD'=>'some_pwd',
'MARKETTYPE'=>'333',
'INSTRUMENTTYPE'=>'C'
);
$url = 'https://www.x/x/x/x.serviceagent?wsdl';
try
{
$soap_client = new SoapClient($url);
$soap_client->providedFunction($param);
} catch (SoapFault $e) {
echo $e->getMessage();
}
?>
Note that this code is on my local wamp server. (I also tried it online on a beta site)
When I refresh the php file, I get the following 'Could not connect to host'.
I appreciate any help given.
Thanks

Checking signature in WS* server implementation

I want to verify a signature for a soap request on a soap server implemented in php.
The server code:
$Server = new SoapServer();
$d = new DOMDocument();
$d->load('php://input');
$s = new WSSESoapServer($d);
try {
if($s->process()) {
// Valid signature
$Server->handle($s->saveXML());
} else {
throw new Exception('Invalid signature');
}
} catch (Exception $e) {
echo "server exception: " . $e;
}
The error:
exception 'Exception' with message 'Error loading key to handle Signature' in /<path>/wse/src/WSSESoapServer.php:146
I have implemented a Client to sign SOAP requests using this library: https://github.com/robrichards/wse-php. There are no examples of how to implement the server...
How do I load the public key to check the signature?
[Edit]
I have now been able to load the supplied key using
$key = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'public'));
$key->loadKey(CERT, true);
I am no longer getting an error message when validating the signature:
$x = new XMLSecurityDSig();
$d = $x->locateSignature($soapDoc);
$valid = $x->verify($key);
However, $valid is always false. I have no idea if it's because the key is loaded wrong or is actually invalid. I can find very little information on implementing a SOAP server with PHP and no information on implementing a SOAP server that relies on checking a signed request.
CLARIFICATION
My client talks to a remote web service and gets an acknowledgement.
Then the remote server takes some time to process my request.
A remote client (that I have no control over) then makes a request to
my service.
The last step is where I have trouble verifying the signature
Well anyways, your first approach looks fine to me, my server has the same structure. Unfortunately, WSSESoapServer does not inherit from SoapServer, thus is not really an SoapServer, but rather a SoapSignatureValidator and should be called like that. It would be easily possible to correct that behaviour, that one would not need a separate SoapServer instance (should be transparent and automatically).
<?php
require 'soap-server-wsse.php';
try {
// get soap message
$xmlSoap = DOMDocument::load('php://input');
// validate signature
$validateSignature = new WSSESoapServer($xmlSoap);
if(!$validateSignature->process())
file_put_contents("log.txt", "soapserver: SIGNATURE VALIDATION ERROR - CONTINUING WITHOUT SIGNATURE\n", FILE_APPEND);
//throw new Exception('Invalid Signature'); # this would cancel the execution and not send an answer
$sServer = new SoapServer($wsdl);
// actually process the soap message and create & send answer
//$sServer->setClass() or setObject() or set setFunction()
$sServer->handle($validateSignature->saveXML());
} catch (Exception $fault) {
file_put_contents("log.txt", "soapserver soapfault: ".print_r($fault, true), FILE_APPEND);
}
?>

Fatal error: Uncaught CurlException: 7: couldn't connect to host thrown in ....src/base_facebook.php on line 887

I'm trying to develop a sample facebook php login example following the example here
I've hosted my app here, but I'm getting the error message in the question whenever I try to access the link. Here's the code segment that throws the error
try {
$e = new FacebookApiException(array(// LINE 887
'error_code' => curl_errno($ch),
'error' => array(
'message' => curl_error($ch),
'type' => 'CurlException',
),
));
curl_close($ch);
}
// edit suggested by Kneel-before ZOD
catch(FacebookApiException $e) {
$result = $e->getResult();
echo 'Got an : ', $e->getType(),' while posting';
echo(json_encode($result));
}
catch(Exception $e){
echo 'Caught exception: ', $e->getMessage(), "\n";
}
Im quite sure Ive setup the APP ID and secret correctly in index.php.
Here's a screenshot of my app setup on facebook
Any help would be appreciated. Thanks!
You may need to give curl a certificate file for Facebook which you do like this:
Download the certificate files from https://github.com/facebookarchive/facebook-php-sdk/blob/master/src/fb_ca_chain_bundle.crt
and add this before attempting any Facebook calls
facebook::$CURL_OPTS[CURLOPT_CAINFO] = 'path/to/fb_ca_chain_bundle.crt';
You could also try
facebook::$CURL_OPTS[CURLOPT_SSL_VERIFYPEER] = false;
facebook::$CURL_OPTS[CURLOPT_SSL_VERIFYHOST] = 2;
why are you creating the exception on the try block?
my current working login function goes something like this:
public function login()
{
$this->load->library('facebook/facebook',$config);
$uid = $this->facebook->getUser();
if ($uid)
{
try
{
$user_profile = $this->facebook->api('/' . $uid);
//then redirect to whatever you need..
}
catch (FacebookApiException $e)
{ error_log($e);
$uid = null;
$this->facebook->destroySession();
}
}
else
{
$params = array(
'canvas' => 1,
'fbconnect' => 0,
'scope' => 'email',
);
echo "<script>top.location.href='" . $this->facebook->getLoginUrl($params)."'</script>";
exit();
}
}
I had the same problem like you.
I add this option before curl_exec() in base_facebook.php
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
If you are using free hosting , I think it may not going to work, mostly because they usually disabled outgoing connection. I also have faced this problem with the code that worked smoothly on paid hosting(or outgoing connection enabled).
You are creating an exception in try ... catch block. You don't need to do such things. try-catch block designed to handle code segments which can throw an exception in your applications.
You need to put inside this block code segments that can throw an exception. In your case it may be a cURL request to the Facebook API.
The link is https you may have to supply the certificate info or curl will usually throw an error if you don't have access to the certificate then adding
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
will allow access to any certificate.
Set Proxy To Connect Facebook.com
## Find Code In base_facebook.php ##
public static $CURL_OPTS = array(
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_USERAGENT => 'facebook-php-3.2',
);
And Add option
public static $CURL_OPTS = array(
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_USERAGENT => 'facebook-php-3.2',
CURLOPT_PROXY => '199.200.120.140:8089',
);
As suggested by Ashutosh Bajpay, it's likely that your web server is unable to connect based on the error message. If you're using a shared hosting provider, or have SELinux enabled, it's highly plausible that your code will not be able to initiate a new connection out.
You can write a quick and dirty script to test this theory:
$page = file_get_contents('http://google.com');
(!empty($page)) ? var_dump($page) : print_r(error_get_last());
If the script can connect, you'll get a dump of the page, otherwise you should see an error with it attempting to get to the host.
If you do have control of the box, and it happens to be running SELinux there are some useful tips here.
Check your php.ini allows curl function.
For ubantu try to this code in your terminal
sudo apt-get install php5-curl
After it restart your apache server using
sudo service apache2 restart
You are catching two exception types, neither is the exception that is "thrown". Try catching the exception that is thrown and within that exception block you'll be able to further debug your problem (such as showing the variables in play during the exception ...) then you can build a simple page to test each piece of the puzzle until you fix it.
It has nothing to do with your code. Curl simply can't connect to the facebook graph API. This could either be because your host is blocking outgoing connections to other hosts or facebook is blocking your host.
If you have ssh access you could try to reach http://graph.facebook.com and/ or check your php logs. Otherwise you should ask your host.

Dealing with Twitter's Ups and Downs - API

I make use of a great class made by Jaisen: http://github.com/jmathai/twitter-async/tree/master. Recently twitter has been up and down and I am sure it will continue to be the same in the future so I am trying to cut down on my dependency on twitter being actually working.
The following is what I have in my header.php and it is right at the top and it generates the login URL for each user. If twitter is down, my site hangs for as long as it needs to and it throws an exception. So I have to catch these expceptions which I have sort of done.
I now want to just cancel the request to the API after a few seconds and just load the page and keep trying behind the scenes. How can I best do this?
<?php include './twitter/EpiCurl.php'; include './twitter/EpiOAuth.php'; include './twitter/EpiTwitter.php';
$consumer_key = 'mykey';
$consumer_secret = 'mysecret';
$twitterObj = new EpiTwitter($consumer_key, $consumer_secret);
try{
$twiturl = $twitterObj->getAuthenticateUrl();
$url = "window.open('".$twiturl."','Login', 'left=20,top=20,width=500,height=500,toolbar=0,resizable=1'); startLoad();";
}catch(EpiOAuthBadRequestException $e){
// bad request exception do something
$statusMessage = 'Oops an error has occurred: ' . $e->getMessage();
}catch(EpiOAuthUnauthorizedException $e){
// bad authorization..probably bad tokens, do something different
$statusMessage = 'Oops an error has occurred: ' . $e->getMessage();
}catch(EpiOAuthException $e){
// uh oh, unknown oauth exception
$statusMessage = 'Oops, an unknown authorisation error has occurred! The mojo team have been notified! Please try again.';
}
if(isset($statusMessage)){
}
?>
Any improvement of the above code will also be appreciated.
Thanks all
The library supports a value to be passed into the curl timeout.
$twitterObj->setTimeout($secs_request_timeout);
I just added support for passing in a connection timeout as well. Unable to run unit tests because I'm being rate limited. Will commit this once I can verify that it works.
$twitterObj->setTimeout($secs_request_timeout, $secs_connection_timeout);
Use curl_setopt(CURLOPT_CONNECTTIMEOUT, 1 /* 1 second timeout */); to cause CURL to give up if a connection isn't established in 1 second. I use this when connecting to the facebook API, 'cause they've been pretty unreliable in the past as well.

Categories