Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ jobs:
fail-fast: false
matrix:
php-version: [7.2, 7.3, 7.4, 8.0, 8.1]
protocol: [ 'json', 'msgpack' ]

steps:
- uses: actions/checkout@v2
Expand All @@ -26,6 +27,7 @@ jobs:
with:
php-version: ${{ matrix.php-version }}


- name: Validate composer.json and composer.lock
run: composer validate

Expand All @@ -34,5 +36,7 @@ jobs:

# the test script is configured in composer.json.
# see: https://getcomposer.org/doc/articles/scripts.md
- name: Run test suite
- name: Run test
env:
PROTOCOL: ${{ matrix.protocol }}
run: composer run-script test
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"homepage": "https://www.ably.com/",
"require": {
"php": "^7.2 || ^8.0",
"rybakit/msgpack": ">=0.9.1",
"ext-json" : "*",
"ext-curl" : "*",
"ext-openssl" : "*"
Expand Down
28 changes: 23 additions & 5 deletions src/AblyRest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
use Ably\Models\HttpPaginatedResponse;
use Ably\Models\PaginatedResult;
use Ably\Utils\Miscellaneous;
use MessagePack\MessagePack;
use MessagePack\PackOptions;

/**
* Ably REST client
Expand All @@ -24,6 +26,14 @@ class AblyRest {
*/
protected static $agents = array();

private function getAcceptHeader()
{
if($this->options->useBinaryProtocol)
return 'application/x-msgpack';

return 'application/json';
}

static function ablyAgentHeader()
{
$sdkIdentifier = 'ably-php/'.Defaults::LIB_VERSION;
Expand Down Expand Up @@ -170,14 +180,26 @@ public function getHosts() {
*/
public function requestInternal( $method, $path, $headers = [], $params = [], $returnHeaders = false, $auth = true ) {
$mergedHeaders = array_merge( [
'Accept: application/json',
'Accept: ' . $this->getAcceptHeader(),
'X-Ably-Version: ' .Defaults::API_VERSION,
'Ably-Agent: ' .self::ablyAgentHeader(),
], $headers );
if ( $auth ) { // inject auth headers
$mergedHeaders = array_merge( $this->auth->getAuthHeaders(), $mergedHeaders );
}
$attempt = 0;
if(!in_array($method, ['GET', 'DELETE'], true) && !is_string($params)) {
if($this->options->useBinaryProtocol) {
if(is_object($params)){
Miscellaneous::deepConvertObjectToArray($params);
}
$params = MessagePack::pack($params, PackOptions::FORCE_STR);
}
else {
$params = json_encode($params);
}
}

$maxPossibleRetries = min(count($this->options->getFallbackHosts()), $this->options->httpMaxRetryCount);
foreach ($this->getHosts() as $host) {
$hostUrl = $this->options->getHostUrl($host). $path;
Expand Down Expand Up @@ -243,10 +265,6 @@ public function request( $method, $path, $params = [], $body = '', $headers = []
throw new AblyException( 'GET requests cannot have a JSON body', 400, 40000 );
}

if ( !is_string( $body ) ) {
$body = json_encode( $body );
}

return new HttpPaginatedResponse( $this, 'Ably\Models\Untyped', null, $method, $path, $body, $headers ); // RSC19d
}

Expand Down
2 changes: 1 addition & 1 deletion src/Auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ public function requestToken( $tokenParams = [], $authOptions = [] ) {
$res = $this->ably->post(
"/keys/{$keyName}/requestToken",
$headers = [],
$params = json_encode( $signedTokenRequest->toArray() ),
$params = $signedTokenRequest->toArray(),
$returnHeaders = false,
$authHeaders = false
);
Expand Down
42 changes: 28 additions & 14 deletions src/Channel.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
use Ably\Models\PaginatedResult;
use Ably\Models\Status\ChannelDetails;
use Ably\Utils\Stringifiable;
use MessagePack\MessagePack;
use MessagePack\PackOptions;

/**
* Represents a channel
Expand All @@ -21,7 +23,7 @@ class Channel {
private $ably;
private $presence;
/**
* @var Ably\Models\ChannelOptions
* @var \Ably\Models\ChannelOptions
*/
public $options;

Expand Down Expand Up @@ -90,18 +92,30 @@ public function __publish_request_body($first) {
}

// Serialize
$json = '';
if ( count($messages) == 1) {
$json = $messages[0]->toJSON();
} else {
$jsonArray = [];
foreach ( $messages as $msg ) {
$jsonArray[] = $msg->toJSON();
if($this->ably->options->useBinaryProtocol) {
if ( count($messages) == 1) {
$serialized = MessagePack::pack($messages[0]->encodeAsArray(), PackOptions::FORCE_STR);
} else {
$array = [];
foreach ( $messages as $msg ) {
$array[] = $msg->encodeAsArray();
}
$serialized = MessagePack::pack($array, PackOptions::FORCE_STR);
}
}
else {
if ( count($messages) == 1) {
$serialized = $messages[0]->toJSON();
} else {
$jsonArray = [];
foreach ( $messages as $msg ) {
$jsonArray[] = $msg->toJSON();
}
$serialized = '[' . implode( ',', $jsonArray ) . ']';
}
$json = '[' . implode( ',', $jsonArray ) . ']';
}

return $json;
return $serialized;
}

public function publish(...$args) {
Expand All @@ -124,9 +138,9 @@ public function publish(...$args) {
$msg->extras = $args[3];
}

$json = $this->__publish_request_body($msg);
$request_body = $this->__publish_request_body($msg);
} else {
$json = $this->__publish_request_body($first);
$request_body = $this->__publish_request_body($first);
if ( count($args) > 1 ) {
$params = $args[1];
}
Expand All @@ -137,7 +151,7 @@ public function publish(...$args) {
$url .= '?' . Stringifiable::buildQuery( $params );
}

$this->ably->post( $url, $headers = [], $json );
$this->ably->post( $url, $headers = [], $request_body );
return true;
}

Expand Down Expand Up @@ -183,7 +197,7 @@ public function getCipherParams() {
}

/**
* @return \Ably\Models\ChannelOptions
* @return ChannelOptions
*/
public function getOptions() {
return $this->options;
Expand Down
23 changes: 19 additions & 4 deletions src/Http.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
use Ably\Exceptions\AblyException;
use Ably\Exceptions\AblyRequestException;
use Ably\Utils\CurlWrapper;
use Ably\Utils\Miscellaneous;
use MessagePack\MessagePack;
use MessagePack\PackOptions;

/**
* Makes HTTP requests using cURL
Expand All @@ -14,7 +17,7 @@ class Http {

/**
* @var string $postDataFormat How $params is interpreted when sent as a string.
* Default: 'json'. 'msgpack' support may be added in future
* Default: 'json'.
*/
protected $postDataFormat;

Expand Down Expand Up @@ -133,8 +136,11 @@ public function request( $method, $url, $headers = [], $params = [] ) {
if ($this->postDataFormat == 'json') {
array_push( $headers, 'Content-Type: application/json' );
}
elseif ($this->postDataFormat == 'msgpack') {
array_push( $headers, 'Content-Type: application/x-msgpack' );
}
} else {
throw new AblyRequestException( 'Unknown $params format' );
throw new AblyRequestException( 'Unknown $params format', -1, -1 );
}
}

Expand All @@ -154,6 +160,7 @@ public function request( $method, $url, $headers = [], $params = [] ) {
$info = $this->curl->getInfo( $ch );
$err = $this->curl->getErrNo( $ch );
$errmsg = $err ? $this->curl->getError( $ch ) : '';
$contentType = $this->curl->getContentType( $ch );

$this->curl->close( $ch );

Expand All @@ -164,11 +171,19 @@ public function request( $method, $url, $headers = [], $params = [] ) {

$resHeaders = substr( $raw, 0, $info['header_size'] );
$body = substr( $raw, $info['header_size'] );
$decodedBody = json_decode( $body );

$decodedBody = null;
if(strpos($contentType, 'application/x-msgpack') === 0) {
$decodedBody = MessagePack::unpack($body, PackOptions::FORCE_STR);

Miscellaneous::deepConvertArrayToObject($decodedBody);
}
elseif(strpos($contentType, 'application/json') === 0)
$decodedBody = json_decode( $body );

$response = [
'headers' => $resHeaders,
'body' => $decodedBody ? $decodedBody : $body,
'body' => $decodedBody ?: $body,
'info' => $info,
];

Expand Down
11 changes: 10 additions & 1 deletion src/Models/BaseMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
use Ably\Exceptions\AblyException;
use Ably\Utils\Crypto;
use Ably\Log;
use Ably\Utils\Miscellaneous;
use stdClass;

/**
* Base class for messages sent over channels.
Expand Down Expand Up @@ -86,7 +88,7 @@ public function toJSON() {
public function fromJSON( $json, $keepOriginal = false ) {
$this->clearFields();

if (is_object( $json )) {
if (!is_string( $json )) {
$obj = $json;
} else {
$obj = @json_decode($json);
Expand Down Expand Up @@ -282,4 +284,11 @@ protected function clearFields() {
public function setCipherParams( CipherParams $cipherParams ) {
$this->cipherParams = $cipherParams;
}

public function encodeAsArray() {
$encoded = (array)$this->encode();

Miscellaneous::deepConvertObjectToArray($encoded);
return $encoded;
}
}
2 changes: 1 addition & 1 deletion src/Models/BaseOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public function toArray() {
}

public function fromJSON( $json ) {
if (is_object( $json )) {
if (!is_string( $json )) {
$obj = $json;
} else {
$obj = @json_decode($json);
Expand Down
5 changes: 3 additions & 2 deletions src/Models/ClientOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ class ClientOptions extends AuthOptions {
public $logHandler;

/**
* TO3f
* @var bool If true, msgpack is used for communication, otherwise JSON is used
* note that msgpack is currently NOT SUPPORTED because of lack of working msgpack libraries for PHP

*/
public $useBinaryProtocol = false;
public $useBinaryProtocol = true;

/**
* @var string alternate server domain
Expand Down
14 changes: 8 additions & 6 deletions src/Models/Stats.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<?php
namespace Ably\Models;

use Ably\Exceptions\AblyException;
use stdClass;

/**
* Model for stats
*/
Expand Down Expand Up @@ -53,18 +56,17 @@ public function fromJSON( $json ) {

if (is_object( $json )) {
$obj = $json;
} else {
}
else if(is_array( $json) ){
$obj = (object)$json;
}
else {
$obj = @json_decode($json);
if (!$obj) {
throw new AblyException( 'Invalid object or JSON encoded object' );
}
}

// stats are usually wrapped in an array
if ( is_array( $obj ) ) {
$obj = $obj[0];
}

self::deepCopy( $obj, $this );
}

Expand Down
2 changes: 1 addition & 1 deletion src/Models/Untyped.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Untyped {
* @throws AblyException
*/
public function fromJSON( $json ) {
if (is_object( $json )) {
if (!is_string( $json )) {
$obj = $json;
} else {
$obj = @json_decode($json);
Expand Down
1 change: 0 additions & 1 deletion src/PushAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ public function publish ( array $recipient, array $data, $returnHeaders = false
}

$params = array_merge( $data, [ 'recipient' => $recipient ] );
$params = json_encode( $params );
$this->ably->post( '/push/publish', [], $params, $returnHeaders );
}

Expand Down
2 changes: 1 addition & 1 deletion src/PushChannelSubscriptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public function save ( $subscription ) {
$obj = new PushChannelSubscription( $subscription );
$path = '/push/channelSubscriptions' ;
$params = $obj->toArray();
$body = $this->ably->post( $path, [], json_encode($params) );
$body = $this->ably->post( $path, [], $params );
$body = json_decode(json_encode($body), true); // Convert stdClass to array
return new PushChannelSubscription ( $body );
}
Expand Down
2 changes: 1 addition & 1 deletion src/PushDeviceRegistrations.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function save ( $device ) {
$deviceDetails = new DeviceDetails( $device );
$path = '/push/deviceRegistrations/' . $deviceDetails->id;
$params = $deviceDetails->toArray();
$body = $this->ably->put( $path, [], json_encode($params) );
$body = $this->ably->put( $path, [], $params );
$body = json_decode(json_encode($body), true); // Convert stdClass to array
return new DeviceDetails ( $body );
}
Expand Down
4 changes: 4 additions & 0 deletions src/Utils/CurlWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ public function getError( $handle ) {
return curl_error( $handle );
}

public function getContentType( $handle ) {
return curl_getinfo( $handle, CURLINFO_CONTENT_TYPE );
}

/**
* Retrieve a command pastable to terminal for a handle
*/
Expand Down
Loading