So here’s a piece of code which I think you guys will like. It’s a URL call with timeout function in PHP.
/* This works only for simple URIs
Returns:
array(headers, body): if everything's fine.
TIMED OUT if it times out.
UNABLE TO OPEN if we can't connect to host.
*/
private function file_get_contents_with_timeout($url, $read_timeout = 5, $connection_timeout = 5) {
$url_parts = parse_url($url);
$host = $url_parts['host'];
$get = $url_parts['path'] . '?' . $url_parts['query'];
$fp = fsockopen($host, 80, $errno, $errstr, $connection_timeout);
if (!$fp) {
return "UNABLE TO OPEN";
} else {
$out = "GET $get HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
stream_set_timeout($fp, $read_timeout);
$result = stream_get_contents($fp);
$divider = strpos($result, "\r\n\r\n");
$headers = substr($result, 0, $divider);
$body = substr($result, $divider, strlen($result));
$info = stream_get_meta_data($fp);
fclose($fp);
if ($info['timed_out']) {
return 'TIMED OUT';
} else {
return array('headers' => $headers, 'body' => $body);
}
}
}
Yup, a bit crude, but hey it works for me! (Oh, and it probably needs PHP5). Feel free to take the core logic out and wrap it up in exceptions and what have you.
Why did I have to write this contraption? Ah, the joys of the Indian SMS scene. Let me take you through a tour: Fastalerts is a bulk SMS solution for end users and resellers. The web frontend is written in PHP using Symfony (an older version, 0.6). The API is written in plain PHP and it connects to a SOAP-based (using nuSOAP) SMS sending solution.
This is a comment I have on top of the new backend code which sums up all the complexity:
/*
A note on message sending.
These actions have to happen as transactions:
* Calling the GATEWAY.
* Entering data into LOGS.
* Reducing CREDITS.
ONLY if:
* User has "enough" credits.
* Input is valid (numbers and mesage)
* User has valid credentials
AND we have to handle:
* Gateway timeouts
* Gateway errors
* CDMA senderid correction.
ALSO:
If the user doesn't have enough credits to send the entirety of numbers,
messages are sent until his credits are exhausted.
AND:
A separate status message is returned for each of these conditions.
BUT WE ENSURE:
That everything is logged appropriately:
* All successfully sent messages are logged and credits reduced.
* In every other case, credits are NOT reduced (we are customer friendly).
* When gateway times out or errors out, the messages are logged.
*/
Interested people should note that there is a lot more you can add on to this: dynamic gateway switches (automatic failover), regular gateway tests, more backend support etc. but this is the bare minimum that’s needed for the backend to work. If you spend some time thinking about the problem, you’ll come to the realization that this bit:
AND we have to handle:
* Gateway timeouts
* Gateway errors
means that we have to handle gateways that time out and never return a response. Most of the SMPP providers in India use something called NowSMS to manage their backend connectivity to the operator. In short: we connect to a vendor via his common gateway, he routes it (depending on destination) to multiple operators. NowSMS exposes a simple HTTP service (a URL call in other words) to add SMS to the vendor queue and it’s this service that’s preferred by a majority of the good vendors. However, HTTP traffic being what it is, a monolithic backend in PHP will stall if the request doesn’t return a response. Hence that file_get_contents_with_timeout
.
Note: this is hardly an ideal solution (that would be a separate daemon). But without adding moving parts, this simple function should increase the reliability of our backend.
Leave a Reply