Merge pull request #5878 from nupplaphil/curl_response_refactoring

Curl response refactoring
This commit is contained in:
Hypolite Petovan 2018-10-10 18:31:49 -04:00 committed by GitHub
commit a066befba5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 563 additions and 484 deletions

View file

@ -179,17 +179,17 @@ class ExAuth
$url = ($ssl ? 'https' : 'http') . '://' . $host . '/noscrape/' . $user;
$data = Network::curl($url);
$curlResult = Network::curl($url);
if (!is_array($data)) {
if (!$curlResult->isSuccess()) {
return false;
}
if ($data['return_code'] != '200') {
if ($curlResult->getReturnCode() != 200) {
return false;
}
$json = @json_decode($data['body']);
$json = @json_decode($curlResult->getBody());
if (!is_object($json)) {
return false;
}

View file

@ -302,10 +302,9 @@ class HTTPSignature
$headers[] = 'Content-Type: application/activity+json';
Network::post($target, $content, $headers);
$return_code = Network::getCurl()->getCode();
$postResult = Network::post($target, $content, $headers);
logger('Transmit to ' . $target . ' returned ' . $return_code);
logger('Transmit to ' . $target . ' returned ' . $postResult->getReturnCode());
}
/**

View file

@ -7,31 +7,12 @@ namespace Friendica\Util;
use Friendica\Core\Addon;
use Friendica\Core\System;
use Friendica\Core\Config;
use Friendica\Network\Curl;
use Friendica\Network\CurlResult;
use DOMDocument;
use DomXPath;
class Network
{
/**
* @var Curl The latest Curl output
*/
private static $curl;
/**
* Returns the latest Curl output
*
* @return Curl The latest Curl output
*/
public static function getCurl()
{
if (empty(self::$curl)) {
self::$curl = new Curl();
}
return self::$curl;
}
/**
* Curl wrapper
*
@ -54,7 +35,7 @@ class Network
{
$ret = self::fetchUrlFull($url, $binary, $redirects, $timeout, $accept_content, $cookiejar);
return $ret['body'];
return $ret->getBody();
}
/**
@ -72,7 +53,7 @@ class Network
* @param string $accept_content supply Accept: header with 'accept_content' as the value
* @param string $cookiejar Path to cookie jar file
*
* @return array With all relevant information, 'body' contains the actual fetched content.
* @return CurlResult With all relevant information, 'body' contains the actual fetched content.
*/
public static function fetchUrlFull($url, $binary = false, &$redirects = 0, $timeout = 0, $accept_content = null, $cookiejar = '')
{
@ -102,12 +83,7 @@ class Network
* 'nobody' => only return the header
* 'cookiejar' => path to cookie jar file
*
* @return array an assoziative array with:
* int 'return_code' => HTTP return code or 0 if timeout or failure
* boolean 'success' => boolean true (if HTTP 2xx result) or false
* string 'redirect_url' => in case of redirect, content was finally retrieved from this URL
* string 'header' => HTTP headers
* string 'body' => fetched content
* @return CurlResult
*/
public static function curl($url, $binary = false, &$redirects = 0, $opts = [])
{
@ -120,24 +96,24 @@ class Network
$parts = parse_url($url);
$path_parts = explode('/', defaults($parts, 'path', ''));
foreach ($path_parts as $part) {
if (strlen($part) <> mb_strlen($part)) {
if (strlen($part) <> mb_strlen($part)) {
$parts2[] = rawurlencode($part);
} else {
$parts2[] = $part;
}
} else {
$parts2[] = $part;
}
}
$parts['path'] = implode('/', $parts2);
$parts['path'] = implode('/', $parts2);
$url = self::unparseURL($parts);
if (self::isUrlBlocked($url)) {
logger('domain of ' . $url . ' is blocked', LOGGER_DATA);
return $ret;
return CurlResult::createErrorCurl($url);
}
$ch = @curl_init($url);
if (($redirects > 8) || (!$ch)) {
return $ret;
return CurlResult::createErrorCurl($url);
}
@curl_setopt($ch, CURLOPT_HEADER, true);
@ -232,91 +208,20 @@ class Network
$curl_info = @curl_getinfo($ch);
}
if (curl_errno($ch) !== CURLE_OK) {
logger('error fetching ' . $url . ': ' . curl_error($ch), LOGGER_INFO);
}
$curlResponse = new CurlResult($url, $s, $curl_info, curl_errno($ch), curl_error($ch));
$ret['errno'] = curl_errno($ch);
$base = $s;
$ret['info'] = $curl_info;
$http_code = $curl_info['http_code'];
logger($url . ': ' . $http_code . " " . $s, LOGGER_DATA);
$header = '';
// Pull out multiple headers, e.g. proxy and continuation headers
// allow for HTTP/2.x without fixing code
while (preg_match('/^HTTP\/[1-2].+? [1-5][0-9][0-9]/', $base)) {
$chunk = substr($base, 0, strpos($base, "\r\n\r\n") + 4);
$header .= $chunk;
$base = substr($base, strlen($chunk));
}
self::$curl = new Curl($http_code, (isset($curl_info['content_type']) ? $curl_info['content_type'] : ''), $header);
if ($http_code == 301 || $http_code == 302 || $http_code == 303 || $http_code == 307) {
$new_location_info = @parse_url($curl_info['redirect_url']);
$old_location_info = @parse_url($curl_info['url']);
$newurl = $curl_info['redirect_url'];
if (empty($new_location_info['path']) && !empty($new_location_info['host'])) {
$newurl = $new_location_info['scheme'] . '://' . $new_location_info['host'] . $old_location_info['path'];
}
$matches = [];
if (preg_match('/(Location:|URI:)(.*?)\n/i', $header, $matches)) {
$newurl = trim(array_pop($matches));
}
if (strpos($newurl, '/') === 0) {
$newurl = $old_location_info["scheme"]."://".$old_location_info["host"].$newurl;
}
$old_location_query = @parse_url($url, PHP_URL_QUERY);
if ($old_location_query != '') {
$newurl .= '?' . $old_location_query;
}
if (filter_var($newurl, FILTER_VALIDATE_URL)) {
$redirects++;
@curl_close($ch);
return self::curl($newurl, $binary, $redirects, $opts);
}
}
self::$curl->setCode($http_code);
if (isset($curl_info['content_type'])) {
self::$curl->setContentType($curl_info['content_type']);
}
$rc = intval($http_code);
$ret['return_code'] = $rc;
$ret['success'] = (($rc >= 200 && $rc <= 299) ? true : false);
$ret['redirect_url'] = $url;
if (!$ret['success']) {
$ret['error'] = curl_error($ch);
$ret['debug'] = $curl_info;
logger('error: '.$url.': '.$ret['return_code'].' - '.$ret['error'], LOGGER_DEBUG);
logger('debug: '.print_r($curl_info, true), LOGGER_DATA);
}
$ret['body'] = substr($s, strlen($header));
$ret['header'] = $header;
if (x($opts, 'debug')) {
$ret['debug'] = $curl_info;
if ($curlResponse->isRedirectUrl()) {
$redirects++;
logger('curl: redirect ' . $url . ' to ' . $curlResponse->getRedirectUrl());
@curl_close($ch);
return self::curl($curlResponse->getRedirectUrl(), $binary, $redirects, $opts);
}
@curl_close($ch);
$a->saveTimestamp($stamp1, 'network');
return($ret);
return $curlResponse;
}
/**
@ -328,7 +233,7 @@ class Network
* @param integer $redirects Recursion counter for internal use - default = 0
* @param integer $timeout The timeout in seconds, default system config value or 60 seconds
*
* @return string The content
* @return CurlResult The content
*/
public static function post($url, $params, $headers = null, &$redirects = 0, $timeout = 0)
{
@ -336,14 +241,14 @@ class Network
if (self::isUrlBlocked($url)) {
logger('post_url: domain of ' . $url . ' is blocked', LOGGER_DATA);
return false;
return CurlResult::createErrorCurl($url);
}
$a = get_app();
$ch = curl_init($url);
if (($redirects > 8) || (!$ch)) {
return false;
return CurlResult::createErrorCurl($url);
}
logger('post_url: start ' . $url, LOGGER_DATA);
@ -397,8 +302,6 @@ class Network
}
}
self::getCurl()->setCode(0);
// don't let curl abort the entire application
// if it throws any errors.
@ -406,53 +309,23 @@ class Network
$base = $s;
$curl_info = curl_getinfo($ch);
$http_code = $curl_info['http_code'];
logger('post_url: result ' . $http_code . ' - ' . $url, LOGGER_DATA);
$curlResponse = new CurlResult($url, $s, $curl_info, curl_errno($ch), curl_error($ch));
$header = '';
// Pull out multiple headers, e.g. proxy and continuation headers
// allow for HTTP/2.x without fixing code
while (preg_match('/^HTTP\/[1-2].+? [1-5][0-9][0-9]/', $base)) {
$chunk = substr($base, 0, strpos($base, "\r\n\r\n") + 4);
$header .= $chunk;
$base = substr($base, strlen($chunk));
if ($curlResponse->isRedirectUrl()) {
$redirects++;
logger('post_url: redirect ' . $url . ' to ' . $curlResponse->getRedirectUrl());
curl_close($ch);
return self::post($curlResponse->getRedirectUrl(), $params, $headers, $redirects, $timeout);
}
if ($http_code == 301 || $http_code == 302 || $http_code == 303 || $http_code == 307) {
$matches = [];
$new_location_info = @parse_url($curl_info['redirect_url']);
$old_location_info = @parse_url($curl_info['url']);
preg_match('/(Location:|URI:)(.*?)\n/', $header, $matches);
$newurl = trim(array_pop($matches));
if (strpos($newurl, '/') === 0) {
$newurl = $old_location_info["scheme"] . "://" . $old_location_info["host"] . $newurl;
}
if (filter_var($newurl, FILTER_VALIDATE_URL)) {
$redirects++;
logger('post_url: redirect ' . $url . ' to ' . $newurl);
return self::post($newurl, $params, $headers, $redirects, $timeout);
}
}
self::getCurl()->setCode($http_code);
$body = substr($s, strlen($header));
self::getCurl()->setHeaders($header);
curl_close($ch);
$a->saveTimestamp($stamp1, 'network');
logger('post_url: end ' . $url, LOGGER_DATA);
return $body;
return $curlResponse;
}
/**

View file

@ -135,23 +135,23 @@ class ParseUrl
$siteinfo['url'] = $url;
$siteinfo['type'] = 'link';
$data = Network::curl($url);
if (!$data['success']) {
$curlResult = Network::curl($url);
if (!$curlResult->isSuccess()) {
return $siteinfo;
}
// If the file is too large then exit
if ($data['info']['download_content_length'] > 1000000) {
if ($curlResult->getInfo()['download_content_length'] > 1000000) {
return $siteinfo;
}
// If it isn't a HTML file then exit
if (($data['info']['content_type'] != '') && !strstr(strtolower($data['info']['content_type']), 'html')) {
if (($curlResult->getContentType() != '') && !strstr(strtolower($curlResult->getContentType()), 'html')) {
return $siteinfo;
}
$header = $data['header'];
$body = $data['body'];
$header = $curlResult->getHeader();
$body = $curlResult->getBody();
if ($do_oembed) {
$oembed_data = OEmbed::fetchURL($url);