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 */
@@ -124,6 +143,26 @@ public function __construct(?string $baseUrl = null, ?string $secret = null, ?ar
124143 $ this ->curlOpts = $ opts ['curl ' ] ?? [];
125144 }
126145
146+ /**
147+ * Immutable setter. Sets a http client and factories.
148+ *
149+ * It is recommended for the http client to have a timeout of e.g. 10
150+ * seconds, to avoid hanging requests. The timeout from ->setTimeout() will
151+ * have no effect on an instance created in this way.
152+ */
153+ public function withHttpClient (
154+ ClientInterface $ httpClient ,
155+ RequestFactoryInterface $ requestFactory ,
156+ StreamFactoryInterface $ streamFactory ,
157+ ): static {
158+ $ clone = clone $ this ;
159+ $ clone ->httpClient = $ httpClient ;
160+ $ clone ->requestFactory = $ requestFactory ;
161+ $ clone ->streamFactory = $ streamFactory ;
162+
163+ return $ clone ;
164+ }
165+
127166 /**
128167 * @throws BadResponseException|\RuntimeException
129168 */
@@ -480,6 +519,10 @@ public function setJSessionId(string $jSessionId): void
480519 }
481520
482521 /**
522+ * Sets curl options.
523+ *
524+ * This has no effect if the instance has an http client.
525+ *
483526 * @param array<int, mixed> $curlOpts
484527 */
485528 public function setCurlOpts (array $ curlOpts ): void
@@ -489,6 +532,8 @@ public function setCurlOpts(array $curlOpts): void
489532
490533 /**
491534 * Set Curl Timeout (Optional), Default 10 Seconds.
535+ *
536+ * This has no effect if the instance has an http client.
492537 */
493538 public function setTimeOut (int $ TimeOutInSeconds ): self
494539 {
@@ -534,6 +579,45 @@ public function getUrlBuilder(): UrlBuilder
534579 * @throws BadResponseException|\RuntimeException
535580 */
536581 private function sendRequest (string $ url , string $ payload = '' , string $ contentType = 'application/xml ' ): string
582+ {
583+ if (null === $ this ->httpClient
584+ || null === $ this ->requestFactory
585+ || null === $ this ->streamFactory
586+ ) {
587+ return $ this ->sendRequestWithCurl ($ url , $ payload , $ contentType );
588+ }
589+
590+ $ request = $ this ->requestFactory ->createRequest ('GET ' , $ url );
591+
592+ $ request = $ request ->withHeader ('Content-type ' , $ contentType );
593+
594+ if ($ payload ) {
595+ $ payloadStream = $ this ->streamFactory ->createStream ($ payload );
596+ $ request = $ request ->withBody ($ payloadStream );
597+ assert ($ request instanceof RequestInterface);
598+ $ request = $ request ->withMethod ('POST ' );
599+ }
600+ assert ($ request instanceof RequestInterface);
601+
602+ // @todo Handle cookies.
603+ // @todo Set UTF-8?
604+ // @todo Follow redirect location?
605+ // @todo Recommend timeout.
606+ // @todo Check if clients verify the peer's certificate.
607+
608+ $ response = $ this ->httpClient ->sendRequest ($ request );
609+
610+ // @todo Handle failed requests.
611+
612+ return (string ) $ response ->getBody ();
613+ }
614+
615+ /**
616+ * A private utility method used by other public methods to request HTTP responses.
617+ *
618+ * @throws BadResponseException|\RuntimeException
619+ */
620+ private function sendRequestWithCurl (string $ url , string $ payload = '' , string $ contentType = 'application/xml ' ): string
537621 {
538622 if (!extension_loaded ('curl ' )) {
539623 throw new \RuntimeException ('Post XML data set but curl PHP module is not installed or not enabled. ' );
0 commit comments