Skip to content

[draft] Issue #267: Http client - first preview #273

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 8 commits into
base: develop
Choose a base branch
from
Draft
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
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,17 @@
"ext-curl": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-simplexml": "*"
"ext-simplexml": "*",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.1"
},
"require-dev": {
"bmitch/churn-php": "^1.7",
"captainhook/captainhook": "^5.23",
"captainhook/hook-installer": "^1.0",
"fakerphp/faker": "^1.23",
"friendsofphp/php-cs-fixer": "^3.54",
"guzzlehttp/guzzle": "^7.9",
"nunomaduro/phpinsights": "^2.11",
"phpstan/phpstan": "^1.10",
"phpunit/php-code-coverage": "^10.1",
Expand Down
83 changes: 83 additions & 0 deletions src/BigBlueButton.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@
use BigBlueButton\Responses\SendChatMessageResponse;
use BigBlueButton\Responses\UpdateRecordingsResponse;
use BigBlueButton\Util\UrlBuilder;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestFactoryInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\StreamFactoryInterface;

/**
* Class BigBlueButton.
Expand Down Expand Up @@ -89,6 +93,21 @@ class BigBlueButton

protected UrlBuilder $urlBuilder;

/**
* An http client, or NULL to fall back to curl.
*/
private ?ClientInterface $httpClient = null;

/**
* An http request factory, or NULL to fall back to curl.
*/
private ?RequestFactoryInterface $requestFactory = null;

/**
* A stream factory, or NULL to fall back to curl.
*/
private ?StreamFactoryInterface $streamFactory = null;

/**
* @param null|array<string, mixed> $opts
*/
Expand Down Expand Up @@ -124,6 +143,31 @@ public function __construct(?string $baseUrl = null, ?string $secret = null, ?ar
$this->curlOpts = $opts['curl'] ?? [];
}

/**
* Creates an instance with http client and factories.
*
* It is recommended for the http client to have a timeout of e.g. 10
* seconds, to avoid hanging requests. The timeout from ->setTimeout() will
* have no effect on an instance created in this way.
*/
public static function createWithHttpClient(
ClientInterface $httpClient,
RequestFactoryInterface $requestFactory,
StreamFactoryInterface $streamFactory,
string $baseUrl,
string $secret,
Copy link
Author

@donquixote donquixote Jun 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we have the UrlBuilder injected instead of passing base url and secret?

): static {
// Extending classes need to override this method, if they change the
// constructor signature.
// @phpstan-ignore new.static
$instance = new static($baseUrl, $secret);
$instance->httpClient = $httpClient;
$instance->requestFactory = $requestFactory;
$instance->streamFactory = $streamFactory;

return $instance;
}

/**
* @throws BadResponseException|\RuntimeException
*/
Expand Down Expand Up @@ -480,6 +524,10 @@ public function setJSessionId(string $jSessionId): void
}

/**
* Sets curl options.
*
* This has no effect if the instance has an http client.
*
* @param array<int, mixed> $curlOpts
*/
public function setCurlOpts(array $curlOpts): void
Expand All @@ -489,6 +537,8 @@ public function setCurlOpts(array $curlOpts): void

/**
* Set Curl Timeout (Optional), Default 10 Seconds.
*
* This has no effect if the instance has an http client.
*/
public function setTimeOut(int $TimeOutInSeconds): self
{
Expand Down Expand Up @@ -534,6 +584,39 @@ public function getUrlBuilder(): UrlBuilder
* @throws BadResponseException|\RuntimeException
*/
private function sendRequest(string $url, string $payload = '', string $contentType = 'application/xml'): string
{
if (null === $this->httpClient
|| null === $this->requestFactory
|| null === $this->streamFactory
) {
return $this->sendRequestWithCurl($url, $payload, $contentType);
}

$request = $this->requestFactory->createRequest('GET', $url);

$request = $request->withHeader('Content-type', $contentType);

if ($payload) {
$payloadStream = $this->streamFactory->createStream($payload);
$request = $request->withBody($payloadStream);
assert($request instanceof RequestInterface);
$request = $request->withMethod('POST');
}
assert($request instanceof RequestInterface);

$response = $this->httpClient->sendRequest($request);

// @todo Handle failed requests.

return (string) $response->getBody();
}

/**
* A private utility method used by other public methods to request HTTP responses.
*
* @throws BadResponseException|\RuntimeException
*/
private function sendRequestWithCurl(string $url, string $payload = '', string $contentType = 'application/xml'): string
{
if (!extension_loaded('curl')) {
throw new \RuntimeException('Post XML data set but curl PHP module is not installed or not enabled.');
Expand Down
53 changes: 53 additions & 0 deletions tests/BigBlueButtonGuzzleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

/*
* BigBlueButton open source conferencing system - https://www.bigbluebutton.org/.
*
* Copyright (c) 2016-2025 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <https://www.gnu.org/licenses/>.
*/

namespace BigBlueButton;

use GuzzleHttp\Client;
use GuzzleHttp\Psr7\HttpFactory;

/**
* Class BigBlueButtonGuzzleTest.
*
* This test verifies that all the functionality that works with curl also works
* with an injected http client. In this case, we use Guzzle.
*
* @internal
*/
class BigBlueButtonGuzzleTest extends BigBlueButtonTest
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a cheap way to run the same tests with curl and with a http client.

In the future we may come up with something better, perhaps.

{
/**
* Setup test class.
*/
public function setUp(): void
{
parent::setUp();

$client = new Client();
$factory = new HttpFactory();
$this->bbb = BigBlueButton::createWithHttpClient(
$client,
$factory,
$factory,
getenv('BBB_SERVER_BASE_URL') ?: $this->fail(),
getenv('BBB_SECRET') ?: getenv('BBB_SECURITY_SALT') ?: $this->fail(),
);
}
}
2 changes: 1 addition & 1 deletion tests/BigBlueButtonTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
*/
class BigBlueButtonTest extends TestCase
{
private BigBlueButton $bbb;
protected BigBlueButton $bbb;

/**
* Setup test class.
Expand Down
49 changes: 49 additions & 0 deletions tests/Util/FixturesGuzzleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

/*
* BigBlueButton open source conferencing system - https://www.bigbluebutton.org/.
*
* Copyright (c) 2016-2025 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <https://www.gnu.org/licenses/>.
*/

namespace BigBlueButton\Util;

use BigBlueButton\BigBlueButton;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\HttpFactory;

/**
* This test verifies that all the functionality that works with curl also works
* with an injected http client. In this case, we use Guzzle.
*
* @internal
*/
class FixturesGuzzleTest extends FixturesTest
{
public function setUp(): void
{
$client = new Client();
$factory = new HttpFactory();
$this->bbb = BigBlueButton::createWithHttpClient(
$client,
$factory,
$factory,
getenv('BBB_SERVER_BASE_URL') ?: $this->fail(),
getenv('BBB_SECRET') ?: getenv('BBB_SECURITY_SALT') ?: $this->fail(),
);

parent::setUp();
}
}
2 changes: 1 addition & 1 deletion tests/Util/FixturesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
*/
class FixturesTest extends TestCase
{
private BigBlueButton $bbb;
protected BigBlueButton $bbb;
private Fixtures $fixtures;

private static Generator $faker;
Expand Down