3434namespace OC \Http \Client ;
3535
3636use GuzzleHttp \Client as GuzzleClient ;
37+ use GuzzleHttp \Promise \PromiseInterface ;
3738use GuzzleHttp \RequestOptions ;
3839use OCP \Http \Client \IClient ;
40+ use OCP \Http \Client \IPromise ;
3941use OCP \Http \Client \IResponse ;
4042use OCP \Http \Client \LocalServerException ;
4143use OCP \ICertificateManager ;
4244use OCP \IConfig ;
4345use OCP \Security \IRemoteHostValidator ;
46+ use Psr \Log \LoggerInterface ;
4447use function parse_url ;
4548
4649/**
@@ -61,7 +64,8 @@ public function __construct(
6164 IConfig $ config ,
6265 ICertificateManager $ certificateManager ,
6366 GuzzleClient $ client ,
64- IRemoteHostValidator $ remoteHostValidator
67+ IRemoteHostValidator $ remoteHostValidator ,
68+ protected LoggerInterface $ logger ,
6569 ) {
6670 $ this ->config = $ config ;
6771 $ this ->client = $ client ;
@@ -205,7 +209,7 @@ protected function preventLocalAddress(string $uri, array $options): void {
205209 * 'headers' => [
206210 * 'foo' => 'bar',
207211 * ],
208- * 'cookies' => ['
212+ * 'cookies' => [
209213 * 'foo' => 'bar',
210214 * ],
211215 * 'allow_redirects' => [
@@ -236,7 +240,7 @@ public function get(string $uri, array $options = []): IResponse {
236240 * 'headers' => [
237241 * 'foo' => 'bar',
238242 * ],
239- * 'cookies' => ['
243+ * 'cookies' => [
240244 * 'foo' => 'bar',
241245 * ],
242246 * 'allow_redirects' => [
@@ -271,7 +275,7 @@ public function head(string $uri, array $options = []): IResponse {
271275 * 'headers' => [
272276 * 'foo' => 'bar',
273277 * ],
274- * 'cookies' => ['
278+ * 'cookies' => [
275279 * 'foo' => 'bar',
276280 * ],
277281 * 'allow_redirects' => [
@@ -312,7 +316,7 @@ public function post(string $uri, array $options = []): IResponse {
312316 * 'headers' => [
313317 * 'foo' => 'bar',
314318 * ],
315- * 'cookies' => ['
319+ * 'cookies' => [
316320 * 'foo' => 'bar',
317321 * ],
318322 * 'allow_redirects' => [
@@ -347,7 +351,7 @@ public function put(string $uri, array $options = []): IResponse {
347351 * 'headers' => [
348352 * 'foo' => 'bar',
349353 * ],
350- * 'cookies' => ['
354+ * 'cookies' => [
351355 * 'foo' => 'bar',
352356 * ],
353357 * 'allow_redirects' => [
@@ -370,7 +374,7 @@ public function delete(string $uri, array $options = []): IResponse {
370374 }
371375
372376 /**
373- * Sends a options request
377+ * Sends an OPTIONS request
374378 *
375379 * @param string $uri
376380 * @param array $options Array such as
@@ -382,7 +386,7 @@ public function delete(string $uri, array $options = []): IResponse {
382386 * 'headers' => [
383387 * 'foo' => 'bar',
384388 * ],
385- * 'cookies' => ['
389+ * 'cookies' => [
386390 * 'foo' => 'bar',
387391 * ],
388392 * 'allow_redirects' => [
@@ -403,4 +407,215 @@ public function options(string $uri, array $options = []): IResponse {
403407 $ response = $ this ->client ->request ('options ' , $ uri , $ this ->buildRequestOptions ($ options ));
404408 return new Response ($ response );
405409 }
410+
411+ protected function wrapGuzzlePromise (PromiseInterface $ promise ): IPromise {
412+ return new GuzzlePromiseAdapter (
413+ $ promise ,
414+ $ this ->logger
415+ );
416+ }
417+
418+ /**
419+ * Sends an asynchronous GET request
420+ *
421+ * @param string $uri
422+ * @param array $options Array such as
423+ * 'query' => [
424+ * 'field' => 'abc',
425+ * 'other_field' => '123',
426+ * 'file_name' => fopen('/path/to/file', 'r'),
427+ * ],
428+ * 'headers' => [
429+ * 'foo' => 'bar',
430+ * ],
431+ * 'cookies' => [
432+ * 'foo' => 'bar',
433+ * ],
434+ * 'allow_redirects' => [
435+ * 'max' => 10, // allow at most 10 redirects.
436+ * 'strict' => true, // use "strict" RFC compliant redirects.
437+ * 'referer' => true, // add a Referer header
438+ * 'protocols' => ['https'] // only allow https URLs
439+ * ],
440+ * 'sink' => '/path/to/file', // save to a file or a stream
441+ * 'verify' => true, // bool or string to CA file
442+ * 'debug' => true,
443+ * 'timeout' => 5,
444+ * @return IPromise
445+ */
446+ public function getAsync (string $ uri , array $ options = []): IPromise {
447+ $ this ->preventLocalAddress ($ uri , $ options );
448+ $ response = $ this ->client ->requestAsync ('get ' , $ uri , $ this ->buildRequestOptions ($ options ));
449+ return $ this ->wrapGuzzlePromise ($ response );
450+ }
451+
452+ /**
453+ * Sends an asynchronous HEAD request
454+ *
455+ * @param string $uri
456+ * @param array $options Array such as
457+ * 'headers' => [
458+ * 'foo' => 'bar',
459+ * ],
460+ * 'cookies' => [
461+ * 'foo' => 'bar',
462+ * ],
463+ * 'allow_redirects' => [
464+ * 'max' => 10, // allow at most 10 redirects.
465+ * 'strict' => true, // use "strict" RFC compliant redirects.
466+ * 'referer' => true, // add a Referer header
467+ * 'protocols' => ['https'] // only allow https URLs
468+ * ],
469+ * 'sink' => '/path/to/file', // save to a file or a stream
470+ * 'verify' => true, // bool or string to CA file
471+ * 'debug' => true,
472+ * 'timeout' => 5,
473+ * @return IPromise
474+ */
475+ public function headAsync (string $ uri , array $ options = []): IPromise {
476+ $ this ->preventLocalAddress ($ uri , $ options );
477+ $ response = $ this ->client ->requestAsync ('head ' , $ uri , $ this ->buildRequestOptions ($ options ));
478+ return $ this ->wrapGuzzlePromise ($ response );
479+ }
480+
481+ /**
482+ * Sends an asynchronous POST request
483+ *
484+ * @param string $uri
485+ * @param array $options Array such as
486+ * 'body' => [
487+ * 'field' => 'abc',
488+ * 'other_field' => '123',
489+ * 'file_name' => fopen('/path/to/file', 'r'),
490+ * ],
491+ * 'headers' => [
492+ * 'foo' => 'bar',
493+ * ],
494+ * 'cookies' => [
495+ * 'foo' => 'bar',
496+ * ],
497+ * 'allow_redirects' => [
498+ * 'max' => 10, // allow at most 10 redirects.
499+ * 'strict' => true, // use "strict" RFC compliant redirects.
500+ * 'referer' => true, // add a Referer header
501+ * 'protocols' => ['https'] // only allow https URLs
502+ * ],
503+ * 'sink' => '/path/to/file', // save to a file or a stream
504+ * 'verify' => true, // bool or string to CA file
505+ * 'debug' => true,
506+ * 'timeout' => 5,
507+ * @return IPromise
508+ */
509+ public function postAsync (string $ uri , array $ options = []): IPromise {
510+ $ this ->preventLocalAddress ($ uri , $ options );
511+
512+ if (isset ($ options ['body ' ]) && is_array ($ options ['body ' ])) {
513+ $ options ['form_params ' ] = $ options ['body ' ];
514+ unset($ options ['body ' ]);
515+ }
516+
517+ return $ this ->wrapGuzzlePromise ($ this ->client ->requestAsync ('post ' , $ uri , $ this ->buildRequestOptions ($ options )));
518+ }
519+
520+ /**
521+ * Sends an asynchronous PUT request
522+ *
523+ * @param string $uri
524+ * @param array $options Array such as
525+ * 'body' => [
526+ * 'field' => 'abc',
527+ * 'other_field' => '123',
528+ * 'file_name' => fopen('/path/to/file', 'r'),
529+ * ],
530+ * 'headers' => [
531+ * 'foo' => 'bar',
532+ * ],
533+ * 'cookies' => [
534+ * 'foo' => 'bar',
535+ * ],
536+ * 'allow_redirects' => [
537+ * 'max' => 10, // allow at most 10 redirects.
538+ * 'strict' => true, // use "strict" RFC compliant redirects.
539+ * 'referer' => true, // add a Referer header
540+ * 'protocols' => ['https'] // only allow https URLs
541+ * ],
542+ * 'sink' => '/path/to/file', // save to a file or a stream
543+ * 'verify' => true, // bool or string to CA file
544+ * 'debug' => true,
545+ * 'timeout' => 5,
546+ * @return IPromise
547+ */
548+ public function putAsync (string $ uri , array $ options = []): IPromise {
549+ $ this ->preventLocalAddress ($ uri , $ options );
550+ $ response = $ this ->client ->requestAsync ('put ' , $ uri , $ this ->buildRequestOptions ($ options ));
551+ return $ this ->wrapGuzzlePromise ($ response );
552+ }
553+
554+ /**
555+ * Sends an asynchronous DELETE request
556+ *
557+ * @param string $uri
558+ * @param array $options Array such as
559+ * 'body' => [
560+ * 'field' => 'abc',
561+ * 'other_field' => '123',
562+ * 'file_name' => fopen('/path/to/file', 'r'),
563+ * ],
564+ * 'headers' => [
565+ * 'foo' => 'bar',
566+ * ],
567+ * 'cookies' => [
568+ * 'foo' => 'bar',
569+ * ],
570+ * 'allow_redirects' => [
571+ * 'max' => 10, // allow at most 10 redirects.
572+ * 'strict' => true, // use "strict" RFC compliant redirects.
573+ * 'referer' => true, // add a Referer header
574+ * 'protocols' => ['https'] // only allow https URLs
575+ * ],
576+ * 'sink' => '/path/to/file', // save to a file or a stream
577+ * 'verify' => true, // bool or string to CA file
578+ * 'debug' => true,
579+ * 'timeout' => 5,
580+ * @return IPromise
581+ */
582+ public function deleteAsync (string $ uri , array $ options = []): IPromise {
583+ $ this ->preventLocalAddress ($ uri , $ options );
584+ $ response = $ this ->client ->requestAsync ('delete ' , $ uri , $ this ->buildRequestOptions ($ options ));
585+ return $ this ->wrapGuzzlePromise ($ response );
586+ }
587+
588+ /**
589+ * Sends an asynchronous OPTIONS request
590+ *
591+ * @param string $uri
592+ * @param array $options Array such as
593+ * 'body' => [
594+ * 'field' => 'abc',
595+ * 'other_field' => '123',
596+ * 'file_name' => fopen('/path/to/file', 'r'),
597+ * ],
598+ * 'headers' => [
599+ * 'foo' => 'bar',
600+ * ],
601+ * 'cookies' => [
602+ * 'foo' => 'bar',
603+ * ],
604+ * 'allow_redirects' => [
605+ * 'max' => 10, // allow at most 10 redirects.
606+ * 'strict' => true, // use "strict" RFC compliant redirects.
607+ * 'referer' => true, // add a Referer header
608+ * 'protocols' => ['https'] // only allow https URLs
609+ * ],
610+ * 'sink' => '/path/to/file', // save to a file or a stream
611+ * 'verify' => true, // bool or string to CA file
612+ * 'debug' => true,
613+ * 'timeout' => 5,
614+ * @return IPromise
615+ */
616+ public function optionsAsync (string $ uri , array $ options = []): IPromise {
617+ $ this ->preventLocalAddress ($ uri , $ options );
618+ $ response = $ this ->client ->requestAsync ('options ' , $ uri , $ this ->buildRequestOptions ($ options ));
619+ return $ this ->wrapGuzzlePromise ($ response );
620+ }
406621}
0 commit comments