📄 request.php
字号:
} elseif (empty($sockets[$sockKey]) || empty($sockets[$sockKey]->fp)) {
$sockets[$sockKey] =& $this->_sock;
}
// Check for redirection
if ( $this->_allowRedirects
AND $this->_redirects <= $this->_maxRedirects
AND $this->getResponseCode() > 300
AND $this->getResponseCode() < 399
AND !empty($this->_response->_headers['location'])) {
$redirect = $this->_response->_headers['location'];
// Absolute URL
if (preg_match('/^https?:\/\//i', $redirect)) {
$this->_url = &new Net_URL($redirect);
$this->addHeader('Host', $this->_generateHostHeader());
// Absolute path
} elseif ($redirect{0} == '/') {
$this->_url->path = $redirect;
// Relative path
} elseif (substr($redirect, 0, 3) == '../' OR substr($redirect, 0, 2) == './') {
if (substr($this->_url->path, -1) == '/') {
$redirect = $this->_url->path . $redirect;
} else {
$redirect = dirname($this->_url->path) . '/' . $redirect;
}
$redirect = Net_URL::resolvePath($redirect);
$this->_url->path = $redirect;
// Filename, no path
} else {
if (substr($this->_url->path, -1) == '/') {
$redirect = $this->_url->path . $redirect;
} else {
$redirect = dirname($this->_url->path) . '/' . $redirect;
}
$this->_url->path = $redirect;
}
$this->_redirects++;
return $this->sendRequest($saveBody);
// Too many redirects
} elseif ($this->_allowRedirects AND $this->_redirects > $this->_maxRedirects) {
return PEAR::raiseError('Too many redirects');
}
return true;
}
/**
* Disconnect the socket, if connected. Only useful if using Keep-Alive.
*
* @access public
*/
function disconnect()
{
if (!empty($this->_sock) && !empty($this->_sock->fp)) {
$this->_notify('disconnect');
$this->_sock->disconnect();
}
}
/**
* Returns the response code
*
* @access public
* @return mixed Response code, false if not set
*/
function getResponseCode()
{
return isset($this->_response->_code) ? $this->_response->_code : false;
}
/**
* Returns either the named header or all if no name given
*
* @access public
* @param string The header name to return, do not set to get all headers
* @return mixed either the value of $headername (false if header is not present)
* or an array of all headers
*/
function getResponseHeader($headername = null)
{
if (!isset($headername)) {
return isset($this->_response->_headers)? $this->_response->_headers: array();
} else {
$headername = strtolower($headername);
return isset($this->_response->_headers[$headername]) ? $this->_response->_headers[$headername] : false;
}
}
/**
* Returns the body of the response
*
* @access public
* @return mixed response body, false if not set
*/
function getResponseBody()
{
return isset($this->_response->_body) ? $this->_response->_body : false;
}
/**
* Returns cookies set in response
*
* @access public
* @return mixed array of response cookies, false if none are present
*/
function getResponseCookies()
{
return isset($this->_response->_cookies) ? $this->_response->_cookies : false;
}
/**
* Builds the request string
*
* @access private
* @return string The request string
*/
function _buildRequest()
{
$separator = ini_get('arg_separator.output');
ini_set('arg_separator.output', '&');
$querystring = ($querystring = $this->_url->getQueryString()) ? '?' . $querystring : '';
ini_set('arg_separator.output', $separator);
$host = isset($this->_proxy_host) ? $this->_url->protocol . '://' . $this->_url->host : '';
$port = (isset($this->_proxy_host) AND $this->_url->port != 80) ? ':' . $this->_url->port : '';
$path = $this->_url->path . $querystring;
$url = $host . $port . $path;
$request = $this->_method . ' ' . $url . ' HTTP/' . $this->_http . "\r\n";
if (in_array($this->_method, $this->_bodyDisallowed) ||
(empty($this->_body) && (HTTP_REQUEST_METHOD_POST != $this->_method ||
(empty($this->_postData) && empty($this->_postFiles)))))
{
$this->removeHeader('Content-Type');
} else {
if (empty($this->_requestHeaders['content-type'])) {
// Add default content-type
$this->addHeader('Content-Type', 'application/x-www-form-urlencoded');
} elseif ('multipart/form-data' == $this->_requestHeaders['content-type']) {
$boundary = 'HTTP_Request_' . md5(uniqid('request') . microtime());
$this->addHeader('Content-Type', 'multipart/form-data; boundary=' . $boundary);
}
}
// Request Headers
if (!empty($this->_requestHeaders)) {
foreach ($this->_requestHeaders as $name => $value) {
$canonicalName = implode('-', array_map('ucfirst', explode('-', $name)));
$request .= $canonicalName . ': ' . $value . "\r\n";
}
}
// No post data or wrong method, so simply add a final CRLF
if (in_array($this->_method, $this->_bodyDisallowed) ||
(HTTP_REQUEST_METHOD_POST != $this->_method && empty($this->_body))) {
$request .= "\r\n";
// Post data if it's an array
} elseif (HTTP_REQUEST_METHOD_POST == $this->_method &&
(!empty($this->_postData) || !empty($this->_postFiles))) {
// "normal" POST request
if (!isset($boundary)) {
$postdata = implode('&', array_map(
create_function('$a', 'return $a[0] . \'=\' . $a[1];'),
$this->_flattenArray('', $this->_postData)
));
// multipart request, probably with file uploads
} else {
$postdata = '';
if (!empty($this->_postData)) {
$flatData = $this->_flattenArray('', $this->_postData);
foreach ($flatData as $item) {
$postdata .= '--' . $boundary . "\r\n";
$postdata .= 'Content-Disposition: form-data; name="' . $item[0] . '"';
$postdata .= "\r\n\r\n" . urldecode($item[1]) . "\r\n";
}
}
foreach ($this->_postFiles as $name => $value) {
if (is_array($value['name'])) {
$varname = $name . ($this->_useBrackets? '[]': '');
} else {
$varname = $name;
$value['name'] = array($value['name']);
}
foreach ($value['name'] as $key => $filename) {
$fp = fopen($filename, 'r');
$data = fread($fp, filesize($filename));
fclose($fp);
$basename = basename($filename);
$type = is_array($value['type'])? @$value['type'][$key]: $value['type'];
$postdata .= '--' . $boundary . "\r\n";
$postdata .= 'Content-Disposition: form-data; name="' . $varname . '"; filename="' . $basename . '"';
$postdata .= "\r\nContent-Type: " . $type;
$postdata .= "\r\n\r\n" . $data . "\r\n";
}
}
$postdata .= '--' . $boundary . "--\r\n";
}
$request .= 'Content-Length: ' . strlen($postdata) . "\r\n\r\n";
$request .= $postdata;
// Explicitly set request body
} elseif (!empty($this->_body)) {
$request .= 'Content-Length: ' . strlen($this->_body) . "\r\n\r\n";
$request .= $this->_body;
}
return $request;
}
/**
* Helper function to change the (probably multidimensional) associative array
* into the simple one.
*
* @param string name for item
* @param mixed item's values
* @return array array with the following items: array('item name', 'item value');
*/
function _flattenArray($name, $values)
{
if (!is_array($values)) {
return array(array($name, $values));
} else {
$ret = array();
foreach ($values as $k => $v) {
if (empty($name)) {
$newName = $k;
} elseif ($this->_useBrackets) {
$newName = $name . '[' . $k . ']';
} else {
$newName = $name;
}
$ret = array_merge($ret, $this->_flattenArray($newName, $v));
}
return $ret;
}
}
/**
* Adds a Listener to the list of listeners that are notified of
* the object's events
*
* @param object HTTP_Request_Listener instance to attach
* @return boolean whether the listener was successfully attached
* @access public
*/
function attach(&$listener)
{
if (!is_a($listener, 'HTTP_Request_Listener')) {
return false;
}
$this->_listeners[$listener->getId()] =& $listener;
return true;
}
/**
* Removes a Listener from the list of listeners
*
* @param object HTTP_Request_Listener instance to detach
* @return boolean whether the listener was successfully detached
* @access public
*/
function detach(&$listener)
{
if (!is_a($listener, 'HTTP_Request_Listener') ||
!isset($this->_listeners[$listener->getId()])) {
return false;
}
unset($this->_listeners[$listener->getId()]);
return true;
}
/**
* Notifies all registered listeners of an event.
*
* Events sent by HTTP_Request object
* - 'connect': on connection to server
* - 'sentRequest': after the request was sent
* - 'disconnect': on disconnection from server
*
* Events sent by HTTP_Response object
* - 'gotHeaders': after receiving response headers (headers are passed in $data)
* - 'tick': on receiving a part of response body (the part is passed in $data)
* - 'gzTick': on receiving a gzip-encoded part of response body (ditto)
* - 'gotBody': after receiving the response body (passes the decoded body in $data if it was gzipped)
*
* @param string Event name
* @param mixed Additional data
* @access private
*/
function _notify($event, $data = null)
{
foreach (array_keys($this->_listeners) as $id) {
$this->_listeners[$id]->update($this, $event, $data);
}
}
}
/**
* Response class to complement the Request class
*/
class HTTP_Response
{
/**
* Socket object
* @var object
*/
var $_sock;
/**
* Protocol
* @var string
*/
var $_protocol;
/**
* Return code
* @var string
*/
var $_code;
/**
* Response headers
* @var array
*/
var $_headers;
/**
* Cookies set in response
* @var array
*/
var $_cookies;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -