5656use BigBlueButton \Responses \SendChatMessageResponse ;
5757use BigBlueButton \Responses \UpdateRecordingsResponse ;
5858use BigBlueButton \Util \UrlBuilder ;
59+ use Psr \Http \Client \ClientInterface ;
60+ use Psr \Http \Message \RequestFactoryInterface ;
61+ use Psr \Http \Message \RequestInterface ;
62+ use Psr \Http \Message \StreamFactoryInterface ;
5963
6064/**
6165 * Class BigBlueButton.
@@ -89,6 +93,21 @@ class BigBlueButton
8993
9094 protected UrlBuilder $ urlBuilder ;
9195
96+ /**
97+ * An http client, or NULL to fall back to curl.
98+ */
99+ private ?ClientInterface $ httpClient = null ;
100+
101+ /**
102+ * An http request factory, or NULL to fall back to curl.
103+ */
104+ private ?RequestFactoryInterface $ requestFactory = null ;
105+
106+ /**
107+ * A stream factory, or NULL to fall back to curl.
108+ */
109+ private ?StreamFactoryInterface $ streamFactory = null ;
110+
92111 /**
93112 * @param null|array<string, mixed> $opts
94113 */
@@ -128,6 +147,26 @@ public function __construct(
128147 $ this ->curlOpts = $ opts ['curl ' ] ?? [];
129148 }
130149
150+ /**
151+ * Immutable setter. Sets a http client and factories.
152+ *
153+ * It is recommended for the http client to have a timeout of e.g. 10
154+ * seconds, to avoid hanging requests. The timeout from ->setTimeout() will
155+ * have no effect on an instance created in this way.
156+ */
157+ public function withHttpClient (
158+ ClientInterface $ httpClient ,
159+ RequestFactoryInterface $ requestFactory ,
160+ StreamFactoryInterface $ streamFactory ,
161+ ): static {
162+ $ clone = clone $ this ;
163+ $ clone ->httpClient = $ httpClient ;
164+ $ clone ->requestFactory = $ requestFactory ;
165+ $ clone ->streamFactory = $ streamFactory ;
166+
167+ return $ clone ;
168+ }
169+
131170 /**
132171 * @throws BadResponseException|\RuntimeException
133172 */
@@ -484,6 +523,10 @@ public function setJSessionId(string $jSessionId): void
484523 }
485524
486525 /**
526+ * Sets curl options.
527+ *
528+ * This has no effect if the instance has an http client.
529+ *
487530 * @param array<int, mixed> $curlOpts
488531 */
489532 public function setCurlOpts (array $ curlOpts ): void
@@ -493,6 +536,8 @@ public function setCurlOpts(array $curlOpts): void
493536
494537 /**
495538 * Set Curl Timeout (Optional), Default 10 Seconds.
539+ *
540+ * This has no effect if the instance has an http client.
496541 */
497542 public function setTimeOut (int $ TimeOutInSeconds ): self
498543 {
@@ -538,6 +583,45 @@ public function getUrlBuilder(): UrlBuilder
538583 * @throws BadResponseException|\RuntimeException
539584 */
540585 private function sendRequest (string $ url , string $ payload = '' , string $ contentType = 'application/xml ' ): string
586+ {
587+ if (null === $ this ->httpClient
588+ || null === $ this ->requestFactory
589+ || null === $ this ->streamFactory
590+ ) {
591+ return $ this ->sendRequestWithCurl ($ url , $ payload , $ contentType );
592+ }
593+
594+ $ request = $ this ->requestFactory ->createRequest ('GET ' , $ url );
595+
596+ $ request = $ request ->withHeader ('Content-type ' , $ contentType );
597+
598+ if ($ payload ) {
599+ $ payloadStream = $ this ->streamFactory ->createStream ($ payload );
600+ $ request = $ request ->withBody ($ payloadStream );
601+ assert ($ request instanceof RequestInterface);
602+ $ request = $ request ->withMethod ('POST ' );
603+ }
604+ assert ($ request instanceof RequestInterface);
605+
606+ // @todo Handle cookies.
607+ // @todo Set UTF-8?
608+ // @todo Follow redirect location?
609+ // @todo Recommend timeout.
610+ // @todo Check if clients verify the peer's certificate.
611+
612+ $ response = $ this ->httpClient ->sendRequest ($ request );
613+
614+ // @todo Handle failed requests.
615+
616+ return (string ) $ response ->getBody ();
617+ }
618+
619+ /**
620+ * A private utility method used by other public methods to request HTTP responses.
621+ *
622+ * @throws BadResponseException|\RuntimeException
623+ */
624+ private function sendRequestWithCurl (string $ url , string $ payload = '' , string $ contentType = 'application/xml ' ): string
541625 {
542626 if (!extension_loaded ('curl ' )) {
543627 throw new \RuntimeException ('Post XML data set but curl PHP module is not installed or not enabled. ' );
0 commit comments