It’s strange how many different ways there are to do the same thing in PHP. For example,if you want to retrieve a URL, it can be as easy as calling file_get_contents($url), or you can use the PECL libraries, or you can go dig up an open source project such as this one.
I was messing around one night and figured it would be possible to just run an http request over a socket. As it turns out it’s not so difficult, there is tons of information out there on how to do it and it wasn’t long before I had a method figured out.
The advantage of this is that it is lightweight and gives you some control over the headers (etc) that you want to send/receive. This has only been tested on text-only requests.
function get_http_content ($url, $timeout = 3, $headers = array()) {
// initialise return variable
$stcReturn = array("headers"=>array(), "content"=>"");
// get server name, port, path from URL
$strRegex = "/^(http[s]?)\:\/\/([^\:\/]+)[\:]?([0-9]*)(.*)$/";
$strServer = preg_replace($strRegex,"$2",$url);
$strPath = preg_replace($strRegex,"$4",$url);
$numPort = preg_replace($strRegex,"$3",$url);
if ($numPort == "") {
if (preg_replace($strRegex,"$1",$url) == "https") {
$stcReturn["headers"]["Status-Code"] = "0";
$stcReturn["headers"]["Status"] = "HTTPS is not supported";
$stcReturn["content"] = "Error: HTTPS is not supported";
} else {
$numPort = 80;
}
}
// connect to server, run request
$objSocket = fsockopen($strServer, $numPort, $numError, $strError, $timeout);
if (!$objSocket) {
// connection not possible
$stcReturn["headers"]["Status-Code"] = $numError;
$stcReturn["headers"]["Status"] = $strError;
$stcReturn["content"] = "Error: {$strError} ({$numError})";
} else {
// connection made - send headers
$strOut = "GET {$strPath} HTTP/1.1\r\n";
$strOut .= "Host: {$strServer}\r\n";
$strOut .= "Connection: Close\r\n";
foreach ($headers as $strName=>$strValue) {
$strOut .= "$strName: $strValue\r\n";
}
$strOut .= "\r\n";
// get data
fwrite($objSocket, $strOut);
$strIn = "";
while (!feof($objSocket)) {
$strIn .= fgets($objSocket, 128);
}
fclose($objSocket);
// split data into lines
$aryIn = explode("\r\n", $strIn);
// data is split into headers/content by double CR
$bHeader = true;
foreach ($aryIn as $i=>$strLine) {
if ($i == 0) {
// first line is [protocol] [status code] [status]
$stcReturn["headers"]["Protocol"] = preg_replace("/^([^ ]+) ([^ ]+) (.+)$/", "$1", $strLine);
$stcReturn["headers"]["Status-Code"] = preg_replace("/^([^ ]+) ([^ ]+) (.+)$/", "$2", $strLine);
$stcReturn["headers"]["Status"] = preg_replace("/^([^ ]+) ([^ ]+) (.+)$/", "$3", $strLine);
} elseif ($bHeader && $strLine == "") {
// if line is empty headers have ended
$bHeader = false;
} elseif ($bHeader) {
// set header
$stcReturn["headers"][preg_replace("/^([^\:]+)\:[ ]*(.+)$/", "$1", $strLine)] = preg_replace("/^([^\:]+)\:[ ]*(.+)$/", "$2", $strLine);
} else {
// set content
$stcReturn["content"] .= $strLine;
if ($i < count($aryIn)-1) {
$stcReturn["content"] .= "\r\n";
}
}
}
}
return $stcReturn;
}


