Commit 6186ec96 authored by tufengqi's avatar tufengqi

fix swoole http

parent 83a90d9b
......@@ -3,7 +3,7 @@
namespace fpf\http;
use fpf\http\CurlHttpClient;
use fpf\http\SwoftHttpClient;
use fpf\http\SwooleHttpClient;
class FpfHttpClient
{
......@@ -15,7 +15,7 @@ class FpfHttpClient
public function __construct()
{
if (defined('IS_SWOOLE_SERVICE') && IS_SWOOLE_SERVICE === true) {
$this->http_client = new SwoftHttpClient();
$this->http_client = new SwooleHttpClient();
} else {
$this->http_client = new CurlHttpClient();
}
......
<?php
namespace fpf\http;
use fpf\http\exception\SwoftHttpException;
use Swoole\Coroutine\Http\Client;
class SwooleHttpClient
{
/**
* The URI to request
*
* @var string
*/
protected $full_url;
/**
* The scheme to use for the request, i.e. http, https
*
* @var string
*/
protected $scheme;
/**
* Buffer for the HTTP request data
*
* @var string
*/
protected $post_fields;
/**
* http headers
*
* @var array
*/
protected $headers = [];
protected $uri_no_func;
protected $connect_timeout_ms;
protected $timeout_ms;
protected $method;
protected $curl_handle;
protected $response;
protected $cookies = [];
const METHOD_POST = 'POST';
const METHOD_GET = 'GET';
public function __construct()
{
$config = \Yii::$app->fpf->loadConfig('http_options');
$this->connect_timeout_ms = $config['connect_timeout'] ?? 10;
$this->timeout_ms = $config['timeout_ms'] ?? 100;
}
/**
* Set read timeout
*
* @param float $timeout
*/
public function setTimeoutSecs($timeout)
{
$this->timeout = $timeout;
}
/**
* Close the transport.
*/
public function close()
{
$this->request = '';
$this->response = null;
}
public function get($url, $get_arr, $options = [])
{
$arr = explode(':', $url);
$scheme = 'https' === $arr[0] ? 'https' : 'http';
$this->scheme = $scheme;
$this->full_url = $url . '?' . http_build_query($get_arr);
if (!empty($options['time']['connect_timeout_ms'])) {
$this->connect_timeout_ms = $options['time']['connect_timeout'];
}
if (!empty($options['time']['timeout_ms'])) {
$this->timeout_ms = $options['time']['timeout_ms'];
}
if (!empty($options['headers'])) {
$this->headers = $options['headers'];
}
if (!empty($options['cookies'])) {
$this->cookies = $options['cookies'];
}
$this->method = self::METHOD_GET;
$this->flush();
return $this->response;
}
public function post($url, $post_arr, $options = [])
{
$arr = explode(':', $url);
$scheme = 'https' === $arr[0] ? 'https' : 'http';
$this->scheme = $scheme;
$this->full_url = $url;
$this->post_arr = $post_arr;
if (!empty($options['time']['connect_timeout_ms'])) {
$this->connect_timeout_ms = $options['time']['connect_timeout'];
}
if (!empty($options['time']['timeout_ms'])) {
$this->timeout_ms = $options['time']['timeout_ms'];
}
if (!empty($options['headers'])) {
$this->headers = $options['headers'];
}
if (!empty($options['cookies'])) {
$this->cookies = $options['cookies'];
}
$this->method = self::METHOD_POST;
$this->flush();
return $this->response;
}
/**
* @throws SwoftHttpException
*/
public function flush()
{
register_shutdown_function([$this, 'closeCurlHandle']);
$full_url = $this->full_url;
$parts = parse_url($full_url);
$this->curl_handle = new Client($parts['host'], $parts['port'], 'http' === $parts['scheme'] ? false : true);
$full_url = $this->full_url;
$headers = [];
foreach ($this->headers as $key => $value) {
$headers[] = "$key: $value";
}
if (defined('VERSION_KEY') && defined('VERSION_VALUE_NO_PTEFIX')) {
$options['headers'][VERSION_KEY] = VERSION_VALUE_NO_PTEFIX;
}
if (self::METHOD_POST === $this->method) {
$options['body'] = $this->request_;
}
$options['timeout'] = $this->timeout_ms / 1000;
$this->post_fields = '';
$this->curl_handle->setHeaders($options['headers']);
$this->curl_handle->set(['timeout' => $options['timeout']]);
if (self::METHOD_POST === $this->method) {
$this->curl_handle->post($parts['path'], $options['body']);
} else {
$this->curl_handle->get($parts['path']);
}
$this->response = $this->curl_handle->body;
// Connect failed?
if (!$this->response) {
$this->curl_handle = null;
$error = 'CurlHttpClient: Could not connect to ' . $full_url;
throw new SwooleHttpException($error, SwooleHttpException::NOT_OPEN);
}
}
public function closeCurlHandle()
{
try {
if ($this->curl_handle) {
curl_close($this->curl_handle);
$this->curl_handle = null;
}
} catch (\Exception $x) {
error_log('There was an error closing the curl handle: ' . $x->getMessage());
}
}
public function addHeaders($headers)
{
$this->headers = array_merge($this->headers, $headers);
}
}
<?php
namespace fpf\http\exception;
class SwooleHttpException extends \Exception
{
const NOT_OPEN = 4000;
public function __construct($message, $code = 0, \Exception $previous = null)
{
parent::__construct($message, $code, $previous);
}
public function __toString()
{
return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
}
}
<?php
/**
* Created by PhpStorm.
* User: rlgyzhcn
* Date: 18-7-9
* Time: 下午6:50
*/
namespace fpf\thrift;
use Thrift\Exception\TTransportException;
use Thrift\Factory\TStringFuncFactory;
use Swoft\HttpClient\Client;
class SwooleHttpClient extends \Thrift\Transport\TTransport
{
/**
* The host to connect to
*
* @var string
*/
protected $host_;
/**
* The port to connect on
*
* @var int
*/
protected $port_;
/**
* The URI to request
*
* @var string
*/
protected $uri_;
/**
* The scheme to use for the request, i.e. http, https
*
* @var string
*/
protected $scheme_;
/**
* Buffer for the HTTP request data
*
* @var string
*/
protected $request_;
/**
* Buffer for the HTTP response data.
*
* @var binary string
*/
protected $response_;
/**
* Read timeout
*
* @var float
*/
protected $timeout_;
/**
* http headers
*
* @var array
*/
protected $headers_;
protected $uri_no_func;
/**
* http connect timeout
*
* @var int
*/
protected $connect_timeout_ms;
/**
* http timeout
*
* @var int
*/
protected $timeout_ms;
/**
* Http 客户端
*
* @var Client
*/
protected $handle;
/**
* Make a new HTTP client.
*
* @param string $host
* @param int $port
* @param string $uri_no_func
*/
public function __construct($host, $port = 80, $uri_no_func = '', $scheme = 'http', $config)
{
if ((TStringFuncFactory::create()->strlen($uri_no_func) > 0) && ($uri_no_func{
0} != '/')) {
$uri_no_func = '/' . $uri_no_func;
}
$this->scheme_ = $scheme;
$this->host_ = $host;
$this->port_ = $port;
$this->uri_no_func = $uri_no_func;
$this->uri_ = $uri_no_func;
$this->request_ = '';
$this->response_ = null;
$this->timeout_ = null;
$this->connect_timeout_ms = $config['connect_timeout'] ?? 10;
$this->timeout_ms = $config['timeout'] ?? 100;
$this->headers_ = array();
}
public function setFuncUri($uri_func)
{
$this->uri_ = rtrim($this->uri_no_func, '/') . '/' . $uri_func;
}
/**
* Set read timeout
*
* @param float $timeout
*/
public function setTimeoutSecs($timeout)
{
$this->timeout_ = $timeout;
}
/**
* Whether this transport is open.
*
* @return boolean true if open
*/
public function isOpen()
{
return true;
}
/**
* Open the transport for reading/writing
*
* @throws TTransportException if cannot open
*/
public function open()
{
}
/**
* Close the transport.
*/
public function close()
{
$this->request_ = '';
$this->response_ = null;
}
/**
* Read some data into the array.
*
* @param int $len How much to read
* @return string The data that has been read
* @throws TTransportException if cannot read any more data
*/
public function read($len)
{
if ($len >= strlen($this->response_)) {
return $this->response_;
} else {
$ret = substr($this->response_, 0, $len);
$this->response_ = substr($this->response_, $len);
return $ret;
}
}
/**
* Writes some data into the pending buffer
*
* @param string $buf The data to write
* @throws TTransportException if writing fails
*/
public function write($buf)
{
$this->request_ .= $buf;
}
/**
* Opens and sends the actual request over the HTTP connection
*
* @throws TTransportException if a writing error occurs
*/
public function flush()
{
register_shutdown_function([$this, 'closeCurlHandle']);
$options = [];
$host = $this->host_ . ($this->port_ != 80 ? ':' . $this->port_ : '');
$defaultHeaders = array(
'Accept' => 'application/x-thrift',
'Content-Type' => 'application/x-thrift',
'User-Agent' => 'PHP/TCurlClient',
'Content-Length' => TStringFuncFactory::create()->strlen($this->request_)
);
$options['base_uri'] = $this->scheme_ . "://" . $host;
$options['headers'] = array_merge($defaultHeaders, $this->headers_);
if (defined('VERSION_KEY') && defined('VERSION_VALUE_NO_PTEFIX')) {
$options['headers'][VERSION_KEY] = VERSION_VALUE_NO_PTEFIX;
}
$options['body'] = $this->request_;
$options['timeout'] = $this->timeout_ms / 1000;
$this->request_ = '';
$full_url = $this->scheme_ . "://" . $host . $this->uri_;
$parts = parse_url($full_url);
$this->handle = new Client($parts['host'], $parts['port'], 'http' === $parts['scheme'] ? false : true);
$this->handle->post($this->uri_, $options['body']);
$this->response_ = $this->handle->body;
// Connect failed?
if (!$this->response_) {
$error = 'SwooleHttpClient: Could not connect to ' . $this->scheme_ . "://" . $host . $this->uri_;
throw new TTransportException($error, TTransportException::NOT_OPEN);
}
}
public function closeCurlHandle()
{
if ($this->handle) {
$this->handle = null;
}
}
public function addHeaders($headers)
{
$this->headers_ = array_merge($this->headers_, $headers);
}
}
\ No newline at end of file
......@@ -32,7 +32,7 @@ use Thrift\Factory\TStringFuncFactory;
*/
class TCurlClient extends \Thrift\Transport\TTransport
{
private static $curlHandle;
private $handle;
/**
* The host to connect to
......@@ -104,8 +104,8 @@ class TCurlClient extends \Thrift\Transport\TTransport
*/
public function __construct($host, $port = 80, $uri_no_func = '', $scheme = 'http', $config)
{
if ((TStringFuncFactory::create()->strlen($uri_no_func) > 0) && ($uri_no_func {
0} != '/')) {
if ((TStringFuncFactory::create()->strlen($uri_no_func) > 0) && ($uri_no_func{
0} != '/')) {
$uri_no_func = '/' . $uri_no_func;
}
$this->scheme_ = $scheme;
......@@ -201,54 +201,52 @@ class TCurlClient extends \Thrift\Transport\TTransport
*/
public function flush()
{
if (!self::$curlHandle) {
register_shutdown_function(array($this, 'closeCurlHandle'));
self::$curlHandle = curl_init();
curl_setopt(self::$curlHandle, CURLOPT_RETURNTRANSFER, true);
curl_setopt(self::$curlHandle, CURLOPT_BINARYTRANSFER, true);
curl_setopt(self::$curlHandle, CURLOPT_USERAGENT, 'PHP/TCurlClient');
curl_setopt(self::$curlHandle, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt(self::$curlHandle, CURLOPT_FOLLOWLOCATION, true);
curl_setopt(self::$curlHandle, CURLOPT_MAXREDIRS, 1);
if (defined('SERVICE_FORCE_VERSION_KEY') && !empty($GLOBALS['GLOBAL_VERSION_VALUE_NO_PTEFIX'])) {
$cookie = SERVICE_FORCE_VERSION_KEY . '=' . $GLOBALS['GLOBAL_VERSION_VALUE_NO_PTEFIX'];
curl_setopt(self::$curlHandle, CURLOPT_COOKIE, $cookie);
}
register_shutdown_function([$this, 'closeCurlHandle']);
$this->handle = curl_init();
curl_setopt($this->handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($this->handle, CURLOPT_BINARYTRANSFER, true);
curl_setopt($this->handle, CURLOPT_USERAGENT, 'PHP/TCurlClient');
curl_setopt($this->handle, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($this->handle, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($this->handle, CURLOPT_MAXREDIRS, 1);
if (defined('SERVICE_FORCE_VERSION_KEY') && !empty($GLOBALS['GLOBAL_VERSION_VALUE_NO_PTEFIX'])) {
$cookie = SERVICE_FORCE_VERSION_KEY . '=' . $GLOBALS['GLOBAL_VERSION_VALUE_NO_PTEFIX'];
curl_setopt($this->handle, CURLOPT_COOKIE, $cookie);
}
// God, PHP really has some esoteric ways of doing simple things.
$host = $this->host_ . ($this->port_ != 80 ? ':' . $this->port_ : '');
$fullUrl = $this->scheme_ . "://" . $host . $this->uri_;
$headers = array();
$defaultHeaders = array(
$full_url = $this->scheme_ . "://" . $host . $this->uri_;
$headers = [];
$defaultHeaders = [
'Accept' => 'application/x-thrift',
'Content-Type' => 'application/x-thrift',
'Content-Length' => TStringFuncFactory::create()->strlen($this->request_)
);
];
foreach (array_merge($defaultHeaders, $this->headers_) as $key => $value) {
$headers[] = "$key: $value";
}
curl_setopt(self::$curlHandle, CURLOPT_HTTPHEADER, $headers);
curl_setopt(self::$curlHandle, CURLOPT_TIMEOUT_MS, $this->timeout_ms);
curl_setopt(self::$curlHandle, CURLOPT_CONNECTTIMEOUT_MS, $this->connect_timeout_ms);
curl_setopt(self::$curlHandle, CURLOPT_POSTFIELDS, $this->request_);
curl_setopt($this->handle, CURLOPT_HTTPHEADER, $headers);
curl_setopt($this->handle, CURLOPT_TIMEOUT_MS, $this->timeout_ms);
curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT_MS, $this->connect_timeout_ms);
curl_setopt($this->handle, CURLOPT_POSTFIELDS, $this->request_);
$this->request_ = '';
curl_setopt(self::$curlHandle, CURLOPT_URL, $fullUrl);
$this->response_ = curl_exec(self::$curlHandle);
curl_setopt($this->handle, CURLOPT_URL, $full_url);
$this->response_ = curl_exec($this->handle);
// Connect failed?
if (!$this->response_) {
curl_close(self::$curlHandle);
self::$curlHandle = null;
$error = 'TCurlClient: Could not connect to ' . $fullUrl;
curl_close($this->handle);
$this->handle = null;
$error = 'TCurlClient: Could not connect to ' . $full_url;
throw new TTransportException($error, TTransportException::NOT_OPEN);
}
}
public static function closeCurlHandle()
public function closeCurlHandle()
{
try {
if (self::$curlHandle) {
curl_close(self::$curlHandle);
self::$curlHandle = null;
if ($this->handle) {
curl_close($this->handle);
$this->handle = null;
}
} catch (\Exception $x) {
error_log('There was an error closing the curl handle: ' . $x->getMessage());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment