5454use BigBlueButton \Responses \PutRecordingTextTrackResponse ;
5555use BigBlueButton \Responses \UpdateRecordingsResponse ;
5656use BigBlueButton \Util \UrlBuilder ;
57+ use Psr \Http \Client \ClientInterface ;
58+ use Psr \Http \Message \RequestFactoryInterface ;
59+ use Psr \Http \Message \RequestInterface ;
60+ use Psr \Http \Message \StreamFactoryInterface ;
5761
5862/**
5963 * Class BigBlueButton.
@@ -87,6 +91,21 @@ class BigBlueButton
8791
8892 protected UrlBuilder $ urlBuilder ;
8993
94+ /**
95+ * A http client, or NULL to fall back to curl.
96+ */
97+ private ?ClientInterface $ httpClient = null ;
98+
99+ /**
100+ * A http request factory, or NULL to fall back to curl.
101+ */
102+ private ?RequestFactoryInterface $ requestFactory = null ;
103+
104+ /**
105+ * A stream factory, or NULL to fall back to curl.
106+ */
107+ private ?StreamFactoryInterface $ streamFactory = null ;
108+
90109 /**
91110 * @param null|array<string, mixed> $opts
92111 */
@@ -122,6 +141,26 @@ public function __construct(?string $baseUrl = null, ?string $secret = null, ?ar
122141 $ this ->curlOpts = $ opts ['curl ' ] ?? [];
123142 }
124143
144+ /**
145+ * Immutable setter. Sets a http client and factories.
146+ *
147+ * It is recommended for the http client to have a timeout of e.g. 10
148+ * seconds, to avoid hanging requests. The timeout from ->setTimeout() will
149+ * have no effect on an instance created in this way.
150+ */
151+ public function withHttpClient (
152+ ClientInterface $ httpClient ,
153+ RequestFactoryInterface $ requestFactory ,
154+ StreamFactoryInterface $ streamFactory ,
155+ ): static {
156+ $ clone = clone $ this ;
157+ $ clone ->httpClient = $ httpClient ;
158+ $ clone ->requestFactory = $ requestFactory ;
159+ $ clone ->streamFactory = $ streamFactory ;
160+
161+ return $ clone ;
162+ }
163+
125164 /**
126165 * @throws BadResponseException|\RuntimeException
127166 */
@@ -476,6 +515,10 @@ public function setJSessionId(string $jSessionId): void
476515 }
477516
478517 /**
518+ * Sets curl options.
519+ *
520+ * This has no effect if the instance has a http client.
521+ *
479522 * @param array<int, mixed> $curlOpts
480523 */
481524 public function setCurlOpts (array $ curlOpts ): void
@@ -485,6 +528,8 @@ public function setCurlOpts(array $curlOpts): void
485528
486529 /**
487530 * Set Curl Timeout (Optional), Default 10 Seconds.
531+ *
532+ * This has no effect if the instance has a http client.
488533 */
489534 public function setTimeOut (int $ TimeOutInSeconds ): self
490535 {
@@ -530,6 +575,45 @@ public function getUrlBuilder(): UrlBuilder
530575 * @throws BadResponseException|\RuntimeException
531576 */
532577 private function sendRequest (string $ url , string $ payload = '' , string $ contentType = 'application/xml ' ): string
578+ {
579+ if (null === $ this ->httpClient
580+ || null === $ this ->requestFactory
581+ || null === $ this ->streamFactory
582+ ) {
583+ return $ this ->sendRequestWithCurl ($ url , $ payload , $ contentType );
584+ }
585+
586+ $ request = $ this ->requestFactory ->createRequest ('GET ' , $ url );
587+
588+ $ request = $ request ->withHeader ('Content-type ' , $ contentType );
589+
590+ if ($ payload ) {
591+ $ payloadStream = $ this ->streamFactory ->createStream ($ payload );
592+ $ request = $ request ->withBody ($ payloadStream );
593+ assert ($ request instanceof RequestInterface);
594+ $ request = $ request ->withMethod ('POST ' );
595+ }
596+ assert ($ request instanceof RequestInterface);
597+
598+ // @todo Handle cookies.
599+ // @todo Set UTF-8?
600+ // @todo Follow redirect location?
601+ // @todo Recommend timeout.
602+ // @todo Check if clients verify the peer's certificate.
603+
604+ $ response = $ this ->httpClient ->sendRequest ($ request );
605+
606+ // @todo Handle failed requests.
607+
608+ return (string ) $ response ->getBody ();
609+ }
610+
611+ /**
612+ * A private utility method used by other public methods to request HTTP responses.
613+ *
614+ * @throws BadResponseException|\RuntimeException
615+ */
616+ private function sendRequestWithCurl (string $ url , string $ payload = '' , string $ contentType = 'application/xml ' ): string
533617 {
534618 if (!extension_loaded ('curl ' )) {
535619 throw new \RuntimeException ('Post XML data set but curl PHP module is not installed or not enabled. ' );
0 commit comments