fsock: Unable to find the socket transport "http" - php

i want to send post variables with fsock,
but when i try this:
$post_arr = array ("a" => "b");
$addr = 'http://1.2.3.4/confirmation.html';
$fp = fsockopen($addr, 80, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$req = '';
foreach ($post_arr as $key => $value) {
$value = urlencode(stripslashes($value));
$req .= "&" . $key . "=" . $value;
}
$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
fwrite($fp, $header);
while (!feof($fp)) {
echo fgets($fp, 128);
}
fclose($fp);
}
I get 'Unable to find the socket transport "http" ',
any ideas why?

fsockopen() opens a socket. Sockets do not know anything about Layer5+ protocols such as HTTP.
$fp = fsockopen('1.2.3.4', 80, $errno, $errstr, 30);
To request a certain path, send it in the request: GET /confirmation.html
To specify the domain, send it in the Host header: Host: 1.2.3.4
You might want to consider using the curl extension. There is usually no good reason to build HTTP requests manually in PHP.

Related

PHP fire and forget not working with remote server

I'm trying to send a request to a remote server using the fire-and-forget approach. This is my code:
function backgroundPost($url, $data = array()){
$parts=parse_url($url);
$fp = fsockopen($parts['host'],
isset($parts['port'])?$parts['port']:80,
$errno, $errstr, 30);
if (!$fp) {
return false;
} else {
$encoded_data = json_encode($data);
$output = "POST ".$parts['path']." HTTP/1.1\r\n";
$output .= "Host: ".$parts['host']."\r\n";
$output .= "Content-Type: application/json\r\n";
$output .= "Content-Length: " . strlen($encoded_data) . "\r\n";
$output .= "Connection: Close\r\n\r\n";
$output .= $encoded_data;
fwrite($fp, $output);
fclose($fp);
return true;
}
}
//Example of use
backgroundPost('url-here', array("foo" => "bar"));
but the data that arrives is simply empty.
When I spin up the application locally and send the request to my own machine instead, the data does arrive.
Am I misunderstanding something about this pattern?
Why is it working when sending a request to my own machine but not a remote one?
Thanks!

Persistent connections

I would like to create a locally persistent connection with my site.
I would like to create a single connection where I can exchange infinite messages.
I used the code below.
but it's really persistent? inside the "while" open (fsockopen) and close (fclose) the connection, but if I take them out of the "while" gives me problems.
$url="localhost/socket/socket.php";
$host=substr($url,0,strpos($url,"/"));
$req=substr($url,strpos($url,"/"));
$var=fopen("out.txt","a+");
while(1){
$fp = fsockopen($host, 80, $errno, $errstr, 30);
if ($fp) {
$data = "test=1";
$request = "POST ".$req." HTTP/1.1\r\n";
$request .= "Host: ".$host."\r\n";
$request .= "Content-Length: " . strlen($data) . "\r\n";
$request .= "Content-Type: application/x-www-form-urlencoded\r\n\r\n";
$request .= $data;
fwrite($fp, $request);
while (!feof($fp)) {
$json = fgets ($fp);
echo $json;
fwrite($var, $json);
}
}
sleep(10);
fclose($fp);
}
If you want a persistent connection you should use pfsockopen instead of fsockopen. Look here for more details.

Socket programming: socket_read, fgets cannot get response

I am trying to get a response from a URL using socket programming, but nothing is working correctly. I am using PHP, and I am told by the developer I am working with that I need to open a socket, send a request, and then I should get a JSON response. the $message is the string that needs to be sent in order to receive a response.
This is what I have tried so far...
$message = "api\tjson\tget\trooms\n";
$response = fsockopen("142.4.xxx.xxx", 5678);
fputs($response, $message);
fgets($response, 2048);
$data = json_decode($response, true);
And then I go on to parse the JSON response.
I have also tried,
$message = "api\tjson\tget\trooms\n";
$response = fsockopen("142.4.xxx.xxx", 5678);
fputs($response, $message);
socket_read($response, 2048, PHP_NORMAL_READ);
$data = json_decode($response, true);
But then I get an error stating that socket_read is not the correct resource. Any help would be appreciated.
You need to do some error checking, at least. Maybe this will help:
$message = "api\tjson\tget\trooms\n";
$response = fsockopen("142.4.xxx.xxx", 5678, $errno, $errstr, 30);
if (!$response) {
echo "$errstr ($errno)<br />\n";
} else {
$out = "POST /script.php HTTP/1.1\r\n";
$out .= "Host: www.webste.com\r\n";
$out .= "Content-Type: application/x-www-form-urlencoded\r\n";
$out .= 'Content-Length: ' . strlen($message) . "\r\n\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($response, $out);
fwrite($response, $message);
while (!feof($response)) {
echo fgets($response, 128);
}
fclose($response);
}

Debugging ipn.php when using paypal sandbox ipn simulator

How do I debug the ipn.php file when using the paypal sandbox ipn simulator tool?
The code looks like this:
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
foreach($_POST as $key = > $value) {
$value = urlencode(stripslashes($value));
$req. = "&$key=$value";
}
// post back to PayPal system to validate
$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header. = "Content-Type: application/x-www-form-urlencoded\r\n";
$header. = "Content-Length: ".strlen($req)."\r\n\r\n";
$fp = fsockopen('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
if (!$fp) {
// HTTP ERROR
} else {
fputs($fp, $header.$req);
while (!feof($fp)) {
$res = fgets($fp, 1024);
if (strcmp($res, "VERIFIED") == 0) {
$DBH = new PDO("mysql:host=localhost;dbname=db", "user", "pass");
$DBH - > setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$STH = $DBH - > prepare("update table2 set status = :status where tracking_id = :tracking_id");
$status = 1;
parse_str($req, $data);
$STH - > bindParam(':status', $status, PDO::PARAM_INT, 1);
$STH - > bindParam(':tracking_id', 'id_goes_here', PDO::PARAM_STR, 50);
$STH - > execute();
$DBH = null;
} else if (strcmp($res, "INVALID") == 0) {
// do something else
}
}
fclose($fp);
}
I normally use netbeans debug facility to debug, but how do I debug using the sandbox simulator? When I click send ipn from the sandbox ipn simulator, I get a message in the sandbox saying IPN successfully sent., but when I then go into my database to check the status, it's still 0.
Maybe problem is in parameter binding
$STH - > bindParam(':tracking_id', 'id_goes_here', PDO::PARAM_STR, 50);
if table 'table2' do not contain row with tracking_id = 'id_goes_here' update action will fail.
Try this
<?php
$testMode = false;
$url = 'https://www.paypal.com/cgi-bin/webscr';
if ($testMode === true)
$url = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
$ipnResponse = ''; // holds the IPN response from paypal
$ipnData = array(); // array will contain the POST values for IPN
$urlParsed = parse_url($url);
$req = 'cmd=_notify-validate'; // Add 'cmd' to req (ipn command)
// Read the post from PayPal system and add them to req
foreach ($_POST as $key => $value) {
$ipnData["$key"] = $value;
$value = urlencode(stripslashes($value));
$req .= "&" . $key . "=" . $value;
}
// Open the connection to paypal
$fp = fsockopen($urlParsed['host'], "80", $errno, $errstr, 30);
// If could open the connection and check response
if ($fp) {
fputs($fp, "POST " . $urlParsed['path'] . " HTTP/1.1\r\n");
fputs($fp, "Host: " . $urlParsed['host'] . "\r\n");
fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
fputs($fp, "Content-length: " . strlen($req) . "\r\n");
fputs($fp, "Connection: close\r\n\r\n");
fputs($fp, $req . "\r\n\r\n");
// Loop through the response from the server and append to variable
while (!feof($fp)) {
$ipnResponse .= fgets($fp, 1024);
}
fclose($fp);
// Valid IPN transaction.
if (preg_match('/^VERIFIED/', $ipnResponse)) {
// Some action on IPN validation - update payment status etc
die("OK. IPN Validation: Success");
}
// Invalid IPN transaction
else {
// Some action on IPN validation - update payment status etc
die("ERROR. IPN Validation: Failed");
}
}
// Else no connection, so maybe wrong url or other reasons, you can do another call later
else {
die("ERROR. IPN Connection: fsockopen error");
}
?>
In general when I want to debug a script that doesn't provide direct output in the browser, I call a simple logging function throughout the script to output variable values or help determine where errors are occurring.
When I have no idea where the script is dying, I write a line to a log file after each significant line of code. After running the script and then checking the log file I can see exactly which line caused the script to die, a very simplified example is below. Of course after everything is running smoothly all of the logging should be removed.
public function logToFile($msg){
$file = 'log.txt';
$current = file_get_contents($file);
$current .= $msg . "\n";
file_put_contents($file, $current);
}
public function doOtherStuff(){
foreach ($_POST as $key => $value) {
$ipnData["$key"] = $value;
$value = urlencode(stripslashes($value));
$req .= "&" . $key . "=" . $value;
}
logToFile("1");
$fp = fsockopen($urlParsed['host'], "80", $errno, $errstr, 30);
logToFile("2");
if ($fp) {
logToFile("3");
fputs($fp, "POST " . $urlParsed['path'] . " HTTP/1.1\r\n");
logToFile("4");
fputs($fp, "Host: " . $urlParsed['host'] . "\r\n");
logToFile("5");
fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
logToFile("6");
fputs($fp, "Content-length: " . strlen($req) . "\r\n");
logToFile("7");
fputs($fp, "Connection: close\r\n\r\n");
logToFile("8");
fputs($fp, $req . "\r\n\r\n");
logToFile("9");
while (!feof($fp)) {
logToFile("10");
$ipnResponse .= fgets($fp, 1024);
}
logToFile("11");
fclose($fp);
}
}

fsockopen soap request

I am trying to send a SOAP message to a service using php.
I want to do it with fsockopen, here's is the code :
<?php
$fp = #fsockopen("ssl://xmlpropp.worldspan.com", 443, $errno, $errstr);
if (!is_resource($fp)) {
die('fsockopen call failed with error number ' . $errno . '.' . $errstr);
}
$soap_out = "POST /xmlts HTTP/1.1\r\n";
$soap_out .= "Host: 212.127.18.11:8800\r\n";
//$soap_out .= "User-Agent: MySOAPisOKGuys \r\n";
$soap_out .= "Content-Type: text/xml; charset='utf-8'\r\n";
$soap_out .= "Content-Length: 999\r\n\r\n";
$soap_put .= "Connection: close\r\n";
$soap_out .= "SOAPAction:\r\n";
$soap_out .= '
Worldspan
This is a test
';
if(!fputs($fp, $soap_out, strlen($soap_out)))
echo "could not write";
echo "<xmp>".$soap_out."</xmp>";
echo "--------------------<br>";
while (!feof($fp))
{
$soap_in .= fgets($fp, 100);
}
echo "<xmp>$soap_in</xmp>";
fclose($fp);
echo "ok";
the above code just hangs . if i remove the while it types ok, so i suppose the problem is at $soap_in .= fgets($fp, 100)
Any ideas of what is happening
Its not just a matter of opening a socket then writing 'POST....' to it - you need a full HTTP stack to parse the possible responses (e.g. what different encodings? Partial Content?). Use cURL.
The reason its currently failing is probably because the remote system is configured to use keepalives - which would again be solved by using a proper HTTP stack.
C.
I recommend, use curl for soap actions. http://www.zimbra.com/forums/developers/9890-solved-simple-soap-admin-example-php.html#post52586

Categories