Skip to content

Commit

Permalink
feat: Allow http options to be passed into ParseClient (#513)
Browse files Browse the repository at this point in the history
  • Loading branch information
dplewis committed May 13, 2023
1 parent eba6f4b commit ee2a5fa
Show file tree
Hide file tree
Showing 24 changed files with 651 additions and 1 deletion.
12 changes: 12 additions & 0 deletions src/Parse/HttpClients/ParseCurlHttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,18 @@ public function setCAFile($caFile)
$this->parseCurl->setOption(CURLOPT_CAINFO, $caFile);
}

/**
* Sets multiple curl options
* https://www.php.net/manual/en/function.curl-setopt.php
*
* @param array $options Array of options to set
* @throws ParseException
*/
public function setHttpOptions($options)
{
$this->parseCurl->setOptionsArray($options);
}

/**
* Gets the error code
*
Expand Down
7 changes: 7 additions & 0 deletions src/Parse/HttpClients/ParseHttpable.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ public function setTimeout($timeout);
*/
public function setCAFile($caFile);

/**
* Sets http options to pass to the http client
*
* @param string $httpOptions Options to set
*/
public function setHttpOptions($httpOptions);

/**
* Gets the error code
*
Expand Down
25 changes: 25 additions & 0 deletions src/Parse/HttpClients/ParseStreamHttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ class ParseStreamHttpClient implements ParseHttpable
*/
private $caFile;

/**
* Options to pass to the stream context.
*
* @var array
*/
private $httpOptions;

/**
* Optional timeout for this request
*
Expand Down Expand Up @@ -195,6 +202,12 @@ public function send($url, $method = 'GET', $data = array())
$this->options['ssl']['cafile'] = $this->caFile;
}

if (isset($this->httpOptions)) {
foreach ($this->httpOptions as $key => $value) {
$this->options[$key] = $value;
}
}

// add additional options for this request
$this->options['http'] = array(
'method' => $method,
Expand Down Expand Up @@ -264,6 +277,7 @@ public function send($url, $method = 'GET', $data = array())

// clear options
$this->options = array();
$this->httpOptions = array();

// flush our existing headers
$this->headers = array();
Expand Down Expand Up @@ -348,6 +362,17 @@ public function setCAFile($caFile)
$this->caFile = $caFile;
}

/**
* Sets http options to pass to the stream context
* https://www.php.net/manual/en/context.php
*
* @param array $httpOptions options to set
*/
public function setHttpOptions($httpOptions)
{
$this->httpOptions = $httpOptions;
}

/**
* Sets the request timeout
*
Expand Down
25 changes: 25 additions & 0 deletions src/Parse/ParseClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ final class ParseClient
*/
private static $caFile;

/**
* Options to pass to the http client.
*
* @var array
*/
private static $httpOptions;

/**
* Constant for version string to include with requests.
*
Expand Down Expand Up @@ -301,6 +308,21 @@ public static function setCAFile($caFile)
self::$caFile = $caFile;
}

/**
* Sets http options to pass to the http client
* For curl
* https://www.php.net/manual/en/function.curl-setopt.php
*
* For stream context
* https://www.php.net/manual/en/context.php
*
* @param array $httpOptions options to set
*/
public static function setHttpOptions($httpOptions)
{
self::$httpOptions = $httpOptions;
}

/**
* ParseClient::_encode, internal method for encoding object values.
*
Expand Down Expand Up @@ -452,6 +474,9 @@ private static function getPreparedHttpClient()
// set CA file
$httpClient->setCAFile(self::$caFile);
}
if (isset(self::$httpOptions)) {
$httpClient->setHttpOptions(self::$httpOptions);
}

return $httpClient;
}
Expand Down
6 changes: 6 additions & 0 deletions tests/Parse/Helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,10 @@ public static function print($text)
{
fwrite(STDOUT, $text . "\n");
}

public static function printArray($array)
{
print_r($array);
ob_end_flush();
}
}
53 changes: 53 additions & 0 deletions tests/Parse/ParseClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

use PHPUnit\Framework\TestCase;

defined('CURLOPT_PINNEDPUBLICKEY') || define('CURLOPT_PINNEDPUBLICKEY', 10230);

class ParseClientTest extends TestCase
{
public static function setUpBeforeClass() : void
Expand All @@ -35,6 +37,9 @@ public function tearDown() : void

// unset CA file
ParseClient::setCAFile(null);

// unset http options
ParseClient::setHttpOptions(null);
}

/**
Expand Down Expand Up @@ -667,4 +672,52 @@ public function testCheckBadServer()
$this->assertTrue(isset($health['error_message']));
}
}

/**
* @group test-http-options
*/
public function testCurlHttpOptions()
{
if (function_exists('curl_init')) {
ParseClient::setHttpClient(new ParseCurlHttpClient());
ParseClient::setServerURL('https://localhost:1338', 'parse');
ParseClient::setHttpOptions([
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_PINNEDPUBLICKEY => 'sha256//Oz+R70/uIv0irdBWc7RNPyCGeZNbN+CBiPLjJxXWigg=',
CURLOPT_SSLCERT => dirname(__DIR__).'/keys/client.crt',
CURLOPT_SSLKEY => dirname(__DIR__).'/keys/client.key',
]);
$health = ParseClient::getServerHealth();

$this->assertNotNull($health);
$this->assertEquals($health['status'], 200);
$this->assertEquals($health['response']['status'], 'ok');
Helper::setServerURL();
}
}

/**
* @group test-http-options
*/
public function testStreamHttpOptions()
{
ParseClient::setHttpClient(new ParseStreamHttpClient());
ParseClient::setServerURL('https://localhost:1338', 'parse');
ParseClient::setHttpOptions([
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true,
'local_cert' => dirname(__DIR__).'/keys/client.crt',
'local_pk' => dirname(__DIR__).'/keys/client.key',
'peer_fingerprint' => '29F36676EFA0CA18B5B571C6144580044CB289C2',
]
]);
$health = ParseClient::getServerHealth();

$this->assertNotNull($health);
$this->assertEquals($health['status'], 200);
$this->assertEquals($health['response']['status'], 'ok');
Helper::setServerURL();
}
}
75 changes: 75 additions & 0 deletions tests/gencerts.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/bin/bash
# https://gist.github.com/ryankurte/bc0d8cff6e73a6bb1950
# https://curl.se/libcurl/c/CURLOPT_PINNEDPUBLICKEY.html
# ./gencerts.sh parseca localhost parsephp keys/
# ./gencerts.sh parseca client parsephp keys/

set -e

if [ "$#" -ne 3 ] && [ "$#" -ne 4 ]; then
echo "Usage: $0 CA NAME ORG"
echo "CA - name of fake CA"
echo "NAME - name of fake client"
echo "ORG - organisation for both"
echo "[DIR] - directory for cert output"
exit
fi

CA=$1
NAME=$2
ORG=$3

if [ -z "$4" ]; then
DIR=./
else
DIR=$4
fi

if [ ! -d "$DIR" ]; then
mkdir -p $DIR
fi

LENGTH=4096
DAYS=1000

SUBJECT=/C=NZ/ST=AKL/L=Auckland/O=$ORG

if [ ! -f "$DIR/$CA.key" ]; then

echo Generating CA
openssl genrsa -out $DIR/$CA.key $LENGTH

echo Signing CA
openssl req -x509 -new -nodes -key $DIR/$CA.key -sha256 -days 1024 -out $DIR/$CA.crt -subj $SUBJECT/CN=$CA

openssl x509 -in $DIR/$CA.crt -out $DIR/$CA.pem -text
openssl x509 -sha1 -noout -in $DIR/$CA.pem -fingerprint | sed 's/SHA1 Fingerprint=//g' >> $DIR/$CA.fp

else
echo Located existing CA
fi

if [ ! -f "$DIR/$NAME.key" ]; then

echo Generating keys
openssl genrsa -out $DIR/$NAME.key $LENGTH

echo Generating CSR
openssl req -new -out $DIR/$NAME.csr -key $DIR/$NAME.key -subj $SUBJECT/CN=$NAME

echo Signing cert
openssl x509 -req -days $DAYS -in $DIR/$NAME.csr -out $DIR/$NAME.crt -CA $DIR/$CA.crt -CAkey $DIR/$CA.key -CAcreateserial

echo Generating PEM
openssl x509 -in $DIR/$NAME.crt -out $DIR/$NAME.pem -text

openssl x509 -sha1 -noout -in $DIR/$NAME.pem -fingerprint | sed 's/SHA1 Fingerprint=//g' > $DIR/$NAME.fp

echo Cleaning Up
rm $DIR/*.csr

else
echo Located existing client certificate
fi

echo Done
30 changes: 30 additions & 0 deletions tests/keys/client.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
-----BEGIN CERTIFICATE-----
MIIFITCCAwkCCQDEwoQengRnzDANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJO
WjEMMAoGA1UECAwDQUtMMREwDwYDVQQHDAhBdWNrbGFuZDERMA8GA1UECgwIcGFy
c2VwaHAxEDAOBgNVBAMMB3BhcnNlY2EwHhcNMjMwNTEyMjA0MzAzWhcNMjYwMjA1
MjA0MzAzWjBSMQswCQYDVQQGEwJOWjEMMAoGA1UECAwDQUtMMREwDwYDVQQHDAhB
dWNrbGFuZDERMA8GA1UECgwIcGFyc2VwaHAxDzANBgNVBAMMBmNsaWVudDCCAiIw
DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMlKDLogZSNxm5S4h97XM8A1+MsP
RaK15g8ebVEP7OGrwX1bvLVis0U/ixwHs0mqjQ9tbuefMZyiRgdds+8tpRCCuqGo
dwSk8YMmOlrF5xIpBT2cXJLhGvDyY0F0RLFZYBoioTYFth4i91DkzhmBaL6vjyB7
dXduR1JQbzTpQHkhofPziQsNtinf8qBqLbH1dFaqwUUEgtsKJyaPlxJR21TF3Fv+
2K/fmoyzP6Er7eUSCvJRRH1hCwzHxl7GqTKyQeaS1RLdrHYqZmSeiJpxwl8uSdBs
x4y8wG4lhRdantCCANlTwLd7zPiuIu+RBP276o2+02K8my9N2STZUgHXefSoNx4M
alYujKBUV+2qmhR9H2HlUB/C/h5Sb8PSlfWyD/bo3+agyw/1+9rfMUYCmiEtdik7
amoBaahoqAHL8S3K19L0ytWkgFejSMzn+i4VDifnwupXHifDL7CPDX0vevFNDvC7
HMLkBWmkNaTduDL5P3ximtIXE7akhK+ufiNoO3KLItenCENxCzUdNdDHguei2U5E
vhTyaTmIIrkUGxQ+aVDXRF2njAeQNMdTjsCAiiSN1corYX8RXvNo8QZQUEaHG42u
O6Yolsw8EZotbpExo1jbiDlI2pVIuwJdtaDCucPN/X6uZ8odGQ0LUeyTBYda/1OG
VIQzPZnxSHzqPzuZAgMBAAEwDQYJKoZIhvcNAQELBQADggIBAHOLgs6FLIv+Vvpx
fNtwabgOI2JxkFwaAujwWJS10tmczJp9qZilOlVBBhDFRBwBKqAaanHKCYkEfP6u
dgC8RMOOYOb0gk6Tj3+zhvM4Qz+n8Cn2fA2+EtFXTKyMfJHuG/zddTLep2Phh9c9
t5s/8aHAuqM9RGiA66V7mJiR9G5E8cNpyHniCh8Z11kABPMzAy92LyEGUlRwCrWx
fCwItnzY2/7J8IW20rPIpb0EWmYHhxkUUzu7APQgvJpAUTdhmVKb9GLCUyY+oICE
1WrnV9OQiqYVGFQkry9FXyKbsLVM6b6ar8DIXpYTYnd11sqFdiUUo4oItYYrO/1O
0Bt0PX6hWYjR4r7ZT23KWAHZdlU4EFfrLJeZ6HDeYttJF68x9s8RZGgVU9Xlb/7X
KGRVyCWI7aWzvI1lBVAnc7b7B9LrIkdHnYDt/ettmRvI/zZRBh73T7EPOQB7bEzP
M8BXfAr/+qa2ToBWNd9AJrw7rg+OWGD801iXqsREyLr15nRIR12mGdKuyMkfghk1
9J1Sd0fkfB2ci7Rn3afRdKksGuADQ2fvYihw0lALOPzSq/FYRqZBzwv9Qmw43CKd
euEPcCfT7VYY47lmfFfKBcVv8d7NiJZRGkIUYUxS/UAsrLiBCgRkaUACcbLok7sJ
jrdaTDx4EZu93dmJbEozNO6dRiLb
-----END CERTIFICATE-----
Binary file added tests/keys/client.der
Binary file not shown.
1 change: 1 addition & 0 deletions tests/keys/client.fp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
D7:10:BE:24:E6:85:A2:F8:79:F8:36:EF:42:A0:EC:B3:EC:93:C2:FB
51 changes: 51 additions & 0 deletions tests/keys/client.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
-----BEGIN RSA PRIVATE KEY-----
MIIJJwIBAAKCAgEAyUoMuiBlI3GblLiH3tczwDX4yw9ForXmDx5tUQ/s4avBfVu8
tWKzRT+LHAezSaqND21u558xnKJGB12z7y2lEIK6oah3BKTxgyY6WsXnEikFPZxc
kuEa8PJjQXREsVlgGiKhNgW2HiL3UOTOGYFovq+PIHt1d25HUlBvNOlAeSGh8/OJ
Cw22Kd/yoGotsfV0VqrBRQSC2wonJo+XElHbVMXcW/7Yr9+ajLM/oSvt5RIK8lFE
fWELDMfGXsapMrJB5pLVEt2sdipmZJ6ImnHCXy5J0GzHjLzAbiWFF1qe0IIA2VPA
t3vM+K4i75EE/bvqjb7TYrybL03ZJNlSAdd59Kg3HgxqVi6MoFRX7aqaFH0fYeVQ
H8L+HlJvw9KV9bIP9ujf5qDLD/X72t8xRgKaIS12KTtqagFpqGioAcvxLcrX0vTK
1aSAV6NIzOf6LhUOJ+fC6lceJ8MvsI8NfS968U0O8LscwuQFaaQ1pN24Mvk/fGKa
0hcTtqSEr65+I2g7cosi16cIQ3ELNR010MeC56LZTkS+FPJpOYgiuRQbFD5pUNdE
XaeMB5A0x1OOwICKJI3VyithfxFe82jxBlBQRocbja47piiWzDwRmi1ukTGjWNuI
OUjalUi7Al21oMK5w839fq5nyh0ZDQtR7JMFh1r/U4ZUhDM9mfFIfOo/O5kCAwEA
AQKCAgB9ZG3NPQUEMW+UE+hAP5tzb6vPA3KDzADHBlNfHiaY5qAgcZd6/0NiLhWA
nqNnjqFVLPzbuWX0h3pMeGjw5GRhhq6wqfuKnx38b0IG7iXmQDuNh+x7a1OXKcf/
LGjmeiDN5yi6OJCc8XdTo1Vouh8AOulUeNRSVBaGBqlgMrYBP5xeFiYXBrGmIGZK
3BofNCMHIlRHpGnH/ekpsmWP+gJCKwf9HyLpXMgwQjGvO2h1POoozct2t49kpMbE
n8kjVbyL4IhvujwHWJ50q/W5EIjfNjyxZDJjT+ooM6NXSxKIHZRdzjjNlIe5mvEU
gCi1z+xr5KZWadvaegp9VAwsLYlAbrFjpUY1gh5jEWmereVdAQI6io0m6lSkAIPC
e7OjV08Hv8rsLbnc8OroJ1YYsDiRnYjASGTgUlYXgZ/GOzrx16NP9Xx/fLXDcry5
/FayKwQ6rNE56+UzwBZisUHFQTaj854ljqT14my0pSkBUJqWu/J8sMoWtCCu31gp
via9/3Cb/+0Pvc3ShDgGEt+ulf962tcVR48mbG/rWLvMgTzbpr4+qrHDEPe0fL3/
p5awpvMQOTr1y/inhf4aOkZgQH83e2072mCvgNDZ6eW5AmCtVEVVP8erWQ9MI2ky
HZY8/i0vs0icbqqmA9M4vnJWuQsgOmB/XIwajmnuP9/OnjfrIQKCAQEA7b/wm0+q
LveojHoKvL3vByb+MmY6UZV8kPx2R8r2wYjFXaXN3+PIjUTpeaPM5Os+yPfBlzs2
T17ySnc7WQsj/RIgTx0fOdARjnopMR8av6RUpgShF69Kb3U7VXiLcEoApJGbg9QV
CSae4f40DzN3ou8kIR+LCRrYSSv1bkrFwRVSgTP/gqLbVWn4/HJN93+Sem8tHmqd
o85/zFEKiVMQqR46amLNh1+ntvLSNi5noETj5y3T/8MYjuPs7GAMrywg77cR06YS
MvT4MFaXfpo7Yg9/lN9jRfTASTiNo1jQd8lSt29HSId/rvZ9F25BQuF8QlEQZj7J
Io94D5frKlUDfQKCAQEA2L2eS1tKdvkgKgIt+kmvws0p0TCLECSut0GL39uk0FU8
aWmAgFrAppsFGNzYWbv3NcN7YuN2UX+YQnBIqyZ3paI7/dOa/pbwnGy9XdXUh6zi
T+CueNBSty2HjLNqcrQ/90v6AAZfE3oOR8fcMq8svgh0oM0PjyYI+81z3lo9+SA1
lLfHW1qIFli+80qebg38t27OeaiRzw9bwniexYPSpozoF8Zmj2UWnml/Ma2ZME8j
2t6YrwiJzwIdrC5JVbKc8Le/iksSjUA98zpFacFjNhVwLNtbUWAf5rUmV3Y312XJ
9qL8cnXmo2bLYv79Hz6I2TGH4Zim8jPT/ZFtR7sbTQKCAQBCPCD6A92zrAdm63Em
V/vJkFFtFRHWPMExW0RQh/jqvgHOLy0F3N24jaRF4R5qACfDsVJboYFl51u05za/
fd0O2gfqQoC6iH77pIjpSHMZRNzYS53djVY9avmWvDiMlfFL58zdky4xGHNXHoy+
V2ZTHDCCkdkYNkRfTkHX8jjZq+kKWcQrTtewGg/ltKqH8yCJv4NgX+9+/T6ZW1KG
I4AWvXckwFXmCv4cd9Wchp0UB10+wIO5U076MAGHcNLX0oFyhxwOTMvxKlIilV0r
RiiZDxxKC1oK2T7gp0K+aTXayVmkBPpk+GrYAY+kAXFpAoytpQvekEtUt4eJQJeh
eYG5AoIBAFpayjfOCgAJIVCB8hrqRxxlnS45F3AWasO4zo/3KAE112Z2dfyMWM3b
yEcyIftesdM2+CQkgTm+gIIJ/zFiavSg6nOJmI7T6+C6MEODFgOtnfcAyptQ9Xqp
v113mkPRQu1cPg9umIotEvD3r6NthbB/I+e5NOhPSeV3I/upETbfJ5ck+jXqSttO
CeSw0dU9fYIW7nqnPInedDlhQYdDyjhme4cVzcGvubs2bbEPFtKd22ut6mbln1Wu
IyKZdTcFrAlqAK6tV0GNa4YPX8qTtUFhtI7ur2YANaxfDmndva/NHmH0Vlt9LTYn
b1iIxosU7cXlsSjqE4ba9mA6FR2XMe0CggEAFCrg/EhBXX8sagXGGXt7Hp1ozpBJ
EqY4xj1KSDPGNh1x1sOJP7MYIg+Sa8AxVRH+T6VBcXBuyxy3FtNH4iRpKzE5Kept
Jdxglsfo5EGqCNsIh45xa1owHiHr3/p2VpASiPy0OsvM4zDWCNffyz0i3wM4NvRb
sVYi/eQtbML2+Ro8e3eW8f3SRbrKahQX+vMg+d3+BddX6GuPd+RE5qdIkQQhvugj
4oOR1Gx1ktv//ex4T2LkEGm0c2TLrlmFdOGPURbFIVeqLT26KJ6PdeMaVHvCkwAX
4krazNZR4HTOLAL5iWx74xr7uGz8Z3My34laVpTaS6YONX9mW7cfT8U2ww==
-----END RSA PRIVATE KEY-----
Loading

0 comments on commit ee2a5fa

Please sign in to comment.