PHP web services for PyS60
a.k.a. How to send headers like Zinedine.
A PHP web service is a good little tool for handing data between two somewhat different sources. By this I mean a little PHP code redirect calls to existing services and serve as a application adapter for your PyS60 application. GPRS data transfer is pretty slow (well in the USA anyhow), and the latency to even establish a TCP/IP connection makes an even longer wait. Here, I will briefly discuss a few little tips to speed some stuff up. I will use the KaraokeCallout game (written in PyS60) as an example.
Suppose you want to perform several operations from a smartphone:
(PyS60) <------> Jakarta Servlet
(PyS60) -------> Save to fileserver
(PyS60) <------> Talk to mySql server
Here we have a smartphone uploading a WAV file and getting back a list of XML data from a Jakarta servlet. Saving the WAV to disk and updating an SQL server. Since bandwidth and connection on a phone is somewhat 'fragile' we want to just upload the wav file off the phone and then get back a small list of results. Added transactions that save info to a file server and an sql server (while possible off the phone) add too much overhead.
We can simplify this by adding one layer of indirection.
(PyS60) <---> PHP <----> Jakarta Servlet
\--> Save to disk
\-> Add to SQL server
Now the PHP script takes the HTTP POST data from the phone and decodes and redirects it. The overall web traffic to the phone is reduced. Moreso, if we build a new client on a phone that (for example) saves audio as an AAC, we can simply build into the PHP script an AAC to WAV decoding. Offloading added conversions on the phone or the servlet.
For Karaoke Callout, we built a little PHP that takes HTTP POST data, saves the WAV to disk, and then passes the POST variables to the servlet.
After some surfing, I found a little function called sendToHost(). I made a small modification, which allows me to send the port in the parameter list. Here is my slightly modified version.
/* sendToHost
* ~~~~~~~~~~
* Params:
* $host - Just the hostname. No http:// or /path/to/file.html portions
* $port - the port number to hit, usually 80 for standard web stuff
* $method - get or post, case-insensitive
* $path - The /path/to/file.html part
* $data - The query string, without initial question mark
* $useragent - If true, 'MSIE' will be sent as the User-Agent (optional)
*
* Examples:
* sendToHost('www.google.com','get','/search','q=php_imlib');
* sendToHost('www.example.com','post','/some_script.cgi',
* 'param=First+Param&second=Second+param');
*/
function sendToHost($host,&port,$method,$path,$data,$useragent=0) {
// Supply a default method of GET if the one passed was empty
if (empty($method)) {
$method = 'GET';
}
$method = strtoupper($method);
$fp = fsockopen($host, $port);
if ($method == 'GET') {
$path .= '?' . $data;
}
fputs($fp, "$method $path HTTP/1.1\r\n");
fputs($fp, "Host: $host\r\n");
fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
fputs($fp, "Content-length: " . strlen($data) . "\r\n");
if ($useragent) {
fputs($fp, "User-Agent: MSIE\r\n");
}
fputs($fp, "Connection: close\r\n\r\n");
if ($method == 'POST') {
fputs($fp, $data);
}
while (!feof($fp)) {
$buf .= fgets($fp, 128);
}
fclose($fp);
return $buf;
}
Basically the HTTP headers are constructed and the request is sent across the socket. The result, headers and all, is returned by the function. You can take the response and send it (or part of it) out to other modules (MySQL, the file system, etc.). If you want to pass back the response (headers and all) you will need to parse out the headers from the returned data and reformat the response yourself, like this method:
function SendHtmlResponse($response_data) {
$pos = strpos($response_data, "\n\n");
if ($pos == false) {
$pos = strpos($response_data, "\r\n\r\n");
}
if ($pos == false) {
// BAD DATA
return;
}
$headers = substr($response_data, 0, $pos);
$data = substr($response_data, $pos + 1);
$tok_headers = strtok($headers, "\n");
while ($tok_headers !== false) {
header(trim($tok_headers));
$tok_headers = strtok("\n");
}
echo $data;
return trim($data);
}
This will only work if you haven't written any data back to the client yet, because the php header() function must be called before any non-header data has been sent back to the client.
© Copyright David Ayman Shamma: ayman shamma•gmail com
© Copyright David Ayman Shamma: ayman shamma•gmail com