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 */
@@ -470,6 +509,10 @@ public function setJSessionId(string $jSessionId): void
470509 }
471510
472511 /**
512+ * Sets curl options.
513+ *
514+ * This has no effect if the instance has a http client.
515+ *
473516 * @param array<int, mixed> $curlOpts
474517 */
475518 public function setCurlOpts (array $ curlOpts ): void
@@ -479,6 +522,8 @@ public function setCurlOpts(array $curlOpts): void
479522
480523 /**
481524 * Set Curl Timeout (Optional), Default 10 Seconds.
525+ *
526+ * This has no effect if the instance has a http client.
482527 */
483528 public function setTimeOut (int $ TimeOutInSeconds ): self
484529 {
@@ -524,6 +569,45 @@ public function getUrlBuilder(): UrlBuilder
524569 * @throws BadResponseException|\RuntimeException
525570 */
526571 private function sendRequest (string $ url , string $ payload = '' , string $ contentType = 'application/xml ' ): string
572+ {
573+ if (null === $ this ->httpClient
574+ || null === $ this ->requestFactory
575+ || null === $ this ->streamFactory
576+ ) {
577+ return $ this ->sendRequestWithCurl ($ url , $ payload , $ contentType );
578+ }
579+
580+ $ request = $ this ->requestFactory ->createRequest ('GET ' , $ url );
581+
582+ $ request = $ request ->withHeader ('Content-type ' , $ contentType );
583+
584+ if ($ payload ) {
585+ $ payloadStream = $ this ->streamFactory ->createStream ($ payload );
586+ $ request = $ request ->withBody ($ payloadStream );
587+ assert ($ request instanceof RequestInterface);
588+ $ request = $ request ->withMethod ('POST ' );
589+ }
590+ assert ($ request instanceof RequestInterface);
591+
592+ // @todo Handle cookies.
593+ // @todo Set UTF-8?
594+ // @todo Follow redirect location?
595+ // @todo Recommend timeout.
596+ // @todo Check if clients verify the peer's certificate.
597+
598+ $ response = $ this ->httpClient ->sendRequest ($ request );
599+
600+ // @todo Handle failed requests.
601+
602+ return (string ) $ response ->getBody ();
603+ }
604+
605+ /**
606+ * A private utility method used by other public methods to request HTTP responses.
607+ *
608+ * @throws BadResponseException|\RuntimeException
609+ */
610+ private function sendRequestWithCurl (string $ url , string $ payload = '' , string $ contentType = 'application/xml ' ): string
527611 {
528612 if (!extension_loaded ('curl ' )) {
529613 throw new \RuntimeException ('Post XML data set but curl PHP module is not installed or not enabled. ' );
0 commit comments