summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Gass2013-03-04 17:43:04 +0000
committerNathan Gass2013-03-04 17:43:04 +0000
commit610121198886a34bcfc6cddd6649500e3c89a0cb (patch)
tree6d1f27f0cacf92038e0e998b351088212d0c37fe
parent55202ffc8bbedf0c70bdbca4f1ea2db4a0a4d404 (diff)
downloaditools-610121198886a34bcfc6cddd6649500e3c89a0cb.tar.gz
itools-610121198886a34bcfc6cddd6649500e3c89a0cb.tar.bz2
itools-610121198886a34bcfc6cddd6649500e3c89a0cb.zip
factor out request method from get method, make http method overwritable, fix Host header
-rw-r--r--it_url.class162
-rwxr-xr-xtests/it_url.t6
2 files changed, 93 insertions, 75 deletions
diff --git a/it_url.class b/it_url.class
index a48013e..3caa6cb 100644
--- a/it_url.class
+++ b/it_url.class
@@ -238,8 +238,7 @@ function get($p=null, $timeout=5)
{
if (!is_array($p))
$p = array('url' => $p, 'timeout' => $timeout);
-
- $p += array('totaltimeout' => "999999", 'timeout' => 5, 'retries' => 1);
+ $p += array('retries' => 1);
if ($this instanceof it_url)
{
@@ -250,103 +249,120 @@ function get($p=null, $timeout=5)
else # called statically
$url = new it_url($p['url']);
+ if ($url->protocol == 'http')
+ {
+ $result = $url->request($p);
+ if ($url->headers['Location'] && preg_match('#^(https?://[^/]*)?(/)?(.*)$#i', $url->headers['Location'], $parts) && ($parts[1] != $url->url)) # Handle redirects (supports relative and global)
+ {
+ unset($p['url'], $p['headers']['Host']);
+ $url->it_url($parts[1] ? $parts[1].$parts[2].$parts[3] : $url->protocol.'://'.$url->realhostname.($parts[2] ? $parts[2].$parts[3] : '/'.dirname($url->path).'/'.$parts[3]));
+ if (++$url->redir <= 4) /* Avoid infinite redirects */
+ return $url->get($p);
+ }
+ }
+ else
+ {
+ $results = self::get_multi(array('urls' => array('one' => $p['url'])) + $p);
+ $result = $results['one'];
+ }
+
+ if (!$result && $p['retries'] > 0 && $url->result < 400)
+ $result = $url->get(array('retries' => $p['retries'] - 1) + $p);
+
+ return $result;
+}
+
+function request($p=array())
+{
+ $p += array('totaltimeout' => "999999", 'timeout' => 5);
+
+ $url = $this;
+ if ($p['url'])
+ $this->it_url($p['url']);
+
$url->result = $result = false;
unset($url->data);
$url->headers = array();
$p['timeout'] = min($p['timeout'], $p['totaltimeout']); # No operation may be longer than totaltimeout
$endtime = time() + $p['totaltimeout'];
- if ($url->protocol == 'http')
+ if ($fp = @fsockopen($url->realhostname, $url->port, $dummy_errno, $dummy_errstr, $p['timeout']))
{
- if ($fp = @fsockopen($url->realhostname, $url->port, $dummy_errno, $dummy_errstr, $p['timeout']))
- {
- # urlencode data pairs if is array
- if (is_array($p['data']))
- $data = it_url::params($p['data']);
-
- $p['headers'] = (array)$p['headers'] + array(
- 'Host' => $url->realhostname,
- 'User-Agent' => "Mozilla/4.0 (compatible; MSIE 7.0; ITools)",
- 'Accept-Language' => T_lang(),
- );
+ # urlencode data pairs if is array
+ if (is_array($p['data']))
+ $data = it_url::params($p['data']);
+ else
+ $data = $p['data'];
- if (is_int($p['filemtime']))
- $p['headers']['If-Modified-Since'] = date("r", $p['filemtime']);
+ $p['headers'] = (array)$p['headers'] + array(
+ 'Host' => $url->realhostname . ($url->port != 80 ? ":" . $url->port : ''),
+ 'User-Agent' => "Mozilla/4.0 (compatible; MSIE 7.0; ITools)",
+ 'Accept-Language' => T_lang(),
+ );
- if ($datalen = strlen($data))
- {
- $method = "POST";
- $p['headers'] += array(
- 'Content-Type' => "application/x-www-form-urlencoded",
- 'Content-Length' => $datalen,
- );
- }
- else
- $method = "GET";
+ if (is_int($p['filemtime']))
+ $p['headers']['If-Modified-Since'] = date("r", $p['filemtime']);
- if ($url->user || $url->pass)
- $p['headers'] += array('Authorization' => 'Basic ' . base64_encode($url->user . ':' . $url->pass));
+ if ($datalen = strlen($data))
+ {
+ $method = $p['method'] ?: "POST";
+ $p['headers'] += array(
+ 'Content-Type' => "application/x-www-form-urlencoded",
+ 'Content-Length' => $datalen,
+ );
+ }
+ else
+ $method = $p['method'] ?: "GET";
- foreach ($p['headers'] as $header => $value)
- $headers .= "$header: $value\r\n";
+ if ($url->user || $url->pass)
+ $p['headers'] += array('Authorization' => 'Basic ' . base64_encode($url->user . ':' . $url->pass));
- stream_set_timeout($fp, intval($p['timeout']), intval(($p['timeout']*1000000)%1000000));
- @fputs($fp, "$method /$url->path HTTP/1.0\r\n$headers\r\n$data");
+ foreach ($p['headers'] as $header => $value)
+ $headers .= "$header: $value\r\n";
- while (!feof($fp) && ($line = @fgets($fp, 10240)) && ($line = trim($line)) && (time() < $endtime))
- {
- if (preg_match('#^(HTTP\S+)\s(\d+)#', $line, $parts)) # Parse result code
- $url->headers[$parts[1]] = $url->result = $parts[2];
- elseif (preg_match('#^Location: (https?://[^/]*)?(/)?(.*)$#i', $line, $parts) && ($parts[1] != $url->url)) # Handle redirects (supports relative and global)
- {
- unset($p['url'], $p['headers']['Host']);
- $url->it_url($parts[1] ? $parts[1].$parts[2].$parts[3] : $url->protocol.'://'.$url->realhostname.($parts[2] ? $parts[2].$parts[3] : '/'.dirname($url->path).'/'.$parts[3]));
- if (++$url->redir <= 4) /* Avoid infinite redirects */
- return $url->get($p);
- }
- elseif (preg_match('#^([^:]+): (.*)$#', $line, $parts))
- $url->headers[$parts[1]] = $parts[2];
- }
+ stream_set_timeout($fp, intval($p['timeout']), intval(($p['timeout']*1000000)%1000000));
+ @fputs($fp, "$method /$url->path HTTP/1.0\r\n$headers\r\n$data");
- if ($url->result)
+ while (!feof($fp) && ($line = @fgets($fp, 10240)) && ($line = trim($line)) && (time() < $endtime))
+ {
+ if (preg_match('#^(HTTP\S+)\s(\d+)#', $line, $parts)) # Parse result code
+ $url->headers[$parts[1]] = $url->result = $parts[2];
+ elseif (preg_match('#^([^:]+): (.*)$#', $line, $parts))
+ $url->headers[$parts[1]] = $parts[2];
+ }
+
+ if ($url->result)
+ {
+ if ($url->headers['Transfer-Encoding'] == "chunked") # Bogus HTTP/1.1 chunked answer from server (e.g. Wordpress/Apache2/PHP5)
{
- if ($url->headers['Transfer-Encoding'] == "chunked") # Bogus HTTP/1.1 chunked answer from server (e.g. Wordpress/Apache2/PHP5)
+ while ($len = hexdec(fgets($fp)))
{
- while ($len = hexdec(fgets($fp)))
- {
- $chunk = "";
+ $chunk = "";
- while (!feof($fp) && (strlen($chunk) < $len) && (time() < $endtime))
- $chunk .= @fread($fp, $len - strlen($chunk));
+ while (!feof($fp) && (strlen($chunk) < $len) && (time() < $endtime))
+ $chunk .= @fread($fp, $len - strlen($chunk));
- $url->data .= $chunk;
- }
+ $url->data .= $chunk;
}
- else
- {
- while (!feof($fp) && (time() < $endtime))
- $url->data .= @fread($fp, 20480);
- }
-
- if ($p['filemtime'] && ($url->result == 304))
- $result = true; # Not modified, success but no data
- else if ($url->result < 400)
- $result =& $url->data;
+ }
+ else
+ {
+ while (!feof($fp) && (time() < $endtime))
+ $url->data .= @fread($fp, 20480);
}
- @fclose($fp);
+ if ($p['filemtime'] && ($url->result == 304))
+ $result = true; # Not modified, success but no data
+ else if ($url->result < 400)
+ $result =& $url->data;
}
- } else {
- $results = self::get_multi(array('urls' => array('one' => $p['url'])) + $p);
- $result = $results['one'];
+
+ @fclose($fp);
}
if (time() >= $endtime)
$result = false;
- if (!$result && $p['retries'] > 0 && $url->result < 400)
- $result = $url->get(array('retries' => $p['retries'] - 1) + $p);
-
return $result;
}
@@ -713,7 +729,7 @@ static function absolute($url=null)
{
$dir = preg_replace('#/[^/]*$#', '/', $_SERVER['PHP_SELF']);
$url = preg_match('#^/#', $url) ? $url : "$dir$url";
- $url = "//" . $_SERVER['HTTP_HOST'] . ($_SERVER['SERVER_PORT'] == (isset($_SERVER['HTTPS']) ? 443 : 80) ? "" : ":{$_SERVER['SERVER_PORT']}") . $url;
+ $url = "//" . $_SERVER['HTTP_HOST'] . $url;
}
$url = "http" . (isset($_SERVER['HTTPS']) ? 's':'') . ":$url";
}
diff --git a/tests/it_url.t b/tests/it_url.t
index 45e882c..a1caaaa 100755
--- a/tests/it_url.t
+++ b/tests/it_url.t
@@ -66,11 +66,12 @@ is(
$_SERVER['HTTP_HOST'] = "gna.ch";
is(
it_url::absolute("/"),
- 'http://gna.ch:/',
+ 'http://gna.ch/',
'it_url::absolute basic'
);
$_SERVER['SERVER_PORT'] = 42;
+$_SERVER['HTTP_HOST'] = "gna.ch:42";
is(
it_url::absolute("/port"),
'http://gna.ch:42/port',
@@ -78,6 +79,7 @@ is(
);
$_SERVER['HTTPS'] = true;
+$_SERVER['HTTP_HOST'] = "gna.ch";
$_SERVER['SERVER_PORT'] = 443;
is(
it_url::absolute("/https"),
@@ -194,7 +196,7 @@ handle_server(
is(
it_url::get(U('http://localhost:8000/get_server_value', 'key' => 'HTTP_HOST')),
'localhost:8000',
- 'TODO it_url::get() sets correct Host header',
+ 'it_url::get() sets correct Host header',
)
);