Skip to content

Commit 2348686

Browse files
authored
Merge pull request #199 from CyberSource/connection-pooling
Re-using old connection via curl_share_init and adding config for setting idle connection timeout.
2 parents 53f0bbc + aeb36ad commit 2348686

File tree

4 files changed

+258
-2
lines changed

4 files changed

+258
-2
lines changed

generator/cybersource-php-template/ApiClient.mustache

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ $stream_headers = array();
3636
class ApiClient
3737
{
3838
private static $logger = null;
39-
39+
private static $shareHandle;
4040
public static $PATCH = "PATCH";
4141
public static $POST = "POST";
4242
public static $GET = "GET";
@@ -101,6 +101,11 @@ class ApiClient
101101
echo "Merchant Configuration cannot be null.";
102102
}
103103

104+
if (self::$shareHandle === null) {
105+
self::$shareHandle = curl_share_init();
106+
curl_share_setopt(self::$shareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
107+
}
108+
104109
$this->config = $config;
105110
$this->merchantConfig = $merchantConfig;
106111
$this->serializer = new ObjectSerializer();
@@ -291,6 +296,8 @@ class ApiClient
291296
self::$logger->debug("Request Headers :\n" . \CyberSource\Utilities\Helpers\DataMasker::maskAuthenticationData(\CyberSource\Utilities\Helpers\ListHelper::toString($reqHeaders)));
292297

293298
$curl = curl_init();
299+
300+
curl_setopt($curl, CURLOPT_SHARE, self::$shareHandle);
294301
// set timeout, if needed
295302
if ($this->config->getCurlTimeout() !== 0) {
296303
curl_setopt($curl, CURLOPT_TIMEOUT, $this->config->getCurlTimeout());
@@ -329,6 +336,32 @@ class ApiClient
329336
curl_setopt($curl, CURLOPT_PROXYUSERPWD, $this->config->getCurlProxyUser() . ':' .$this->config->getCurlProxyPassword());
330337
}
331338

339+
if ($this->config->getTlsVersion()) {
340+
curl_setopt($curl, CURLOPT_SSLVERSION, $this->config->getTlsVersion());
341+
}
342+
343+
if ($this->config->getTlsCipherList()) {
344+
if (
345+
defined('CURL_SSLVERSION_TLSv1_3') &&
346+
defined('CURLOPT_TLS13_CIPHERS') &&
347+
$this->config->getTlsVersion() === CURL_SSLVERSION_TLSv1_3
348+
) {
349+
curl_setopt($curl, CURLOPT_TLS13_CIPHERS, $this->config->getTlsCipherList());
350+
} else {
351+
curl_setopt($curl, CURLOPT_SSL_CIPHER_LIST, $this->config->getTlsCipherList());
352+
}
353+
}
354+
355+
// Set maximum age for connection reuse in the connection pool
356+
if ($this->config->getKeepAliveTime()) {
357+
if (defined('CURLOPT_MAXAGE_CONN')) {
358+
curl_setopt($curl, CURLOPT_MAXAGE_CONN, $this->config->getKeepAliveTime());
359+
} else {
360+
self::$logger->warning("CURLOPT_MAXAGE_CONN is not supported in your cURL version. Keep-alive time setting will be ignored.");
361+
}
362+
}
363+
364+
332365
if (!empty($queryParams)) {
333366
$url = ($url . '?' . http_build_query($queryParams));
334367
}

generator/cybersource-php-template/configuration.mustache

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,27 @@ class Configuration
157157
*/
158158
protected $proxyPassword;
159159
160+
/**
161+
* TLS version to use for HTTPS requests
162+
*
163+
* @var string
164+
*/
165+
protected $tlsVersion;
166+
167+
/**
168+
* TLS cipher list to use for HTTPS requests
169+
*
170+
* @var string
171+
*/
172+
protected $tlsCipherList;
173+
174+
/**
175+
* Free socket time allowed for reusing a connection
176+
*
177+
* @var int
178+
*/
179+
protected $keepAliveTime;
180+
160181
/**
161182
* Allow Curl encoding header
162183
*
@@ -678,6 +699,80 @@ class Configuration
678699
return $this->proxyPassword;
679700
}
680701

702+
/**
703+
* Gets the TLS version to use for HTTPS requests
704+
*
705+
* @return string
706+
*/
707+
public function getTlsVersion()
708+
{
709+
return $this->tlsVersion;
710+
}
711+
712+
/**
713+
* Sets the TLS version to use for HTTPS requests
714+
*
715+
* @param string $tlsVersion
716+
*
717+
* @return $this
718+
*/
719+
public function setTlsVersion($tlsVersion)
720+
{
721+
$this->tlsVersion = $tlsVersion;
722+
return $this;
723+
}
724+
725+
/**
726+
* Gets the TLS cipher list to use for HTTPS requests
727+
*
728+
* @return string
729+
*/
730+
public function getTlsCipherList()
731+
{
732+
return $this->tlsCipherList;
733+
}
734+
735+
/**
736+
* Sets the TLS cipher list to use for HTTPS requests
737+
*
738+
* @param string $tlsCipherList
739+
*
740+
* @return $this
741+
*/
742+
public function setTlsCipherList($tlsCipherList)
743+
{
744+
$this->tlsCipherList = $tlsCipherList;
745+
return $this;
746+
}
747+
748+
/**
749+
* Gets free socket time allowed for reusing a connection
750+
*
751+
* @return int
752+
*/
753+
public function getKeepAliveTime()
754+
{
755+
return $this->keepAliveTime;
756+
}
757+
758+
/**
759+
* Sets keep-alive time allowed for reusing a connection
760+
*
761+
* @param int $keepAliveTime
762+
*
763+
* @return $this
764+
*/
765+
public function setKeepAliveTime($keepAliveTime)
766+
{
767+
if (!is_numeric($keepAliveTime) || $keepAliveTime < 0) {
768+
self::$logger->error("InvalidArgumentException : Keep-alive time value must be numeric and a non-negative number.");
769+
self::$logger->close();
770+
throw new \InvalidArgumentException('Keep-alive time value must be numeric and a non-negative number.');
771+
}
772+
$this->keepAliveTime = $keepAliveTime;
773+
return $this;
774+
}
775+
681776
/**
682777
* Sets if SSL verification should be enabled or disabled
683778
*

lib/ApiClient.php

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
class ApiClient
4747
{
4848
private static $logger = null;
49-
49+
private static $shareHandle;
5050
public static $PATCH = "PATCH";
5151
public static $POST = "POST";
5252
public static $GET = "GET";
@@ -111,6 +111,11 @@ public function __construct(\CyberSource\Configuration $config = null, \CyberSou
111111
echo "Merchant Configuration cannot be null.";
112112
}
113113

114+
if (self::$shareHandle === null) {
115+
self::$shareHandle = curl_share_init();
116+
curl_share_setopt(self::$shareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
117+
}
118+
114119
$this->config = $config;
115120
$this->merchantConfig = $merchantConfig;
116121
$this->serializer = new ObjectSerializer();
@@ -311,6 +316,8 @@ public function callApi($resourcePath, $method, $queryParams, $postData, $header
311316
self::$logger->debug("Request Headers :\n" . \CyberSource\Utilities\Helpers\DataMasker::maskAuthenticationData(\CyberSource\Utilities\Helpers\ListHelper::toString($reqHeaders)));
312317

313318
$curl = curl_init();
319+
320+
curl_setopt($curl, CURLOPT_SHARE, self::$shareHandle);
314321
// set timeout, if needed
315322
if ($this->config->getCurlTimeout() !== 0) {
316323
curl_setopt($curl, CURLOPT_TIMEOUT, $this->config->getCurlTimeout());
@@ -349,6 +356,32 @@ public function callApi($resourcePath, $method, $queryParams, $postData, $header
349356
curl_setopt($curl, CURLOPT_PROXYUSERPWD, $this->config->getCurlProxyUser() . ':' .$this->config->getCurlProxyPassword());
350357
}
351358

359+
if ($this->config->getTlsVersion()) {
360+
curl_setopt($curl, CURLOPT_SSLVERSION, $this->config->getTlsVersion());
361+
}
362+
363+
if ($this->config->getTlsCipherList()) {
364+
if (
365+
defined('CURL_SSLVERSION_TLSv1_3') &&
366+
defined('CURLOPT_TLS13_CIPHERS') &&
367+
$this->config->getTlsVersion() === CURL_SSLVERSION_TLSv1_3
368+
) {
369+
curl_setopt($curl, CURLOPT_TLS13_CIPHERS, $this->config->getTlsCipherList());
370+
} else {
371+
curl_setopt($curl, CURLOPT_SSL_CIPHER_LIST, $this->config->getTlsCipherList());
372+
}
373+
}
374+
375+
// Set maximum age for connection reuse in the connection pool
376+
if ($this->config->getKeepAliveTime()) {
377+
if (defined('CURLOPT_MAXAGE_CONN')) {
378+
curl_setopt($curl, CURLOPT_MAXAGE_CONN, $this->config->getKeepAliveTime());
379+
} else {
380+
self::$logger->warning("CURLOPT_MAXAGE_CONN is not supported in your cURL version. Keep-alive time setting will be ignored.");
381+
}
382+
}
383+
384+
352385
if (!empty($queryParams)) {
353386
$url = ($url . '?' . http_build_query($queryParams));
354387
}

lib/Configuration.php

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,27 @@ class Configuration
166166
*/
167167
protected $proxyPassword;
168168

169+
/**
170+
* TLS version to use for HTTPS requests
171+
*
172+
* @var string
173+
*/
174+
protected $tlsVersion;
175+
176+
/**
177+
* TLS cipher list to use for HTTPS requests
178+
*
179+
* @var string
180+
*/
181+
protected $tlsCipherList;
182+
183+
/**
184+
* Free socket time allowed for reusing a connection
185+
*
186+
* @var int
187+
*/
188+
protected $keepAliveTime;
189+
169190
/**
170191
* Allow Curl encoding header
171192
*
@@ -687,6 +708,80 @@ public function getCurlProxyPassword()
687708
return $this->proxyPassword;
688709
}
689710

711+
/**
712+
* Gets the TLS version to use for HTTPS requests
713+
*
714+
* @return string
715+
*/
716+
public function getTlsVersion()
717+
{
718+
return $this->tlsVersion;
719+
}
720+
721+
/**
722+
* Sets the TLS version to use for HTTPS requests
723+
*
724+
* @param string $tlsVersion
725+
*
726+
* @return $this
727+
*/
728+
public function setTlsVersion($tlsVersion)
729+
{
730+
$this->tlsVersion = $tlsVersion;
731+
return $this;
732+
}
733+
734+
/**
735+
* Gets the TLS cipher list to use for HTTPS requests
736+
*
737+
* @return string
738+
*/
739+
public function getTlsCipherList()
740+
{
741+
return $this->tlsCipherList;
742+
}
743+
744+
/**
745+
* Sets the TLS cipher list to use for HTTPS requests
746+
*
747+
* @param string $tlsCipherList
748+
*
749+
* @return $this
750+
*/
751+
public function setTlsCipherList($tlsCipherList)
752+
{
753+
$this->tlsCipherList = $tlsCipherList;
754+
return $this;
755+
}
756+
757+
/**
758+
* Gets free socket time allowed for reusing a connection
759+
*
760+
* @return int
761+
*/
762+
public function getKeepAliveTime()
763+
{
764+
return $this->keepAliveTime;
765+
}
766+
767+
/**
768+
* Sets keep-alive time allowed for reusing a connection
769+
*
770+
* @param int $keepAliveTime
771+
*
772+
* @return $this
773+
*/
774+
public function setKeepAliveTime($keepAliveTime)
775+
{
776+
if (!is_numeric($keepAliveTime) || $keepAliveTime < 0) {
777+
self::$logger->error("InvalidArgumentException : Keep-alive time value must be numeric and a non-negative number.");
778+
self::$logger->close();
779+
throw new \InvalidArgumentException('Keep-alive time value must be numeric and a non-negative number.');
780+
}
781+
$this->keepAliveTime = $keepAliveTime;
782+
return $this;
783+
}
784+
690785
/**
691786
* Sets if SSL verification should be enabled or disabled
692787
*

0 commit comments

Comments
 (0)