RequestManager.php 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
  5. *
  6. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  7. *
  8. * @license GNU AGPL version 3 or any later version
  9. *
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Affero General Public License as
  12. * published by the Free Software Foundation, either version 3 of the
  13. * License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU Affero General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Affero General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. *
  23. */
  24. namespace OC\Http\WellKnown;
  25. use OC\AppFramework\Bootstrap\Coordinator;
  26. use OC\AppFramework\Bootstrap\ServiceRegistration;
  27. use OCP\AppFramework\QueryException;
  28. use OCP\Http\WellKnown\IHandler;
  29. use OCP\Http\WellKnown\IRequestContext;
  30. use OCP\Http\WellKnown\IResponse;
  31. use OCP\Http\WellKnown\JrdResponse;
  32. use OCP\IRequest;
  33. use OCP\IServerContainer;
  34. use Psr\Log\LoggerInterface;
  35. use RuntimeException;
  36. use function array_reduce;
  37. class RequestManager {
  38. /** @var Coordinator */
  39. private $coordinator;
  40. /** @var IServerContainer */
  41. private $container;
  42. /** @var LoggerInterface */
  43. private $logger;
  44. public function __construct(Coordinator $coordinator,
  45. IServerContainer $container,
  46. LoggerInterface $logger) {
  47. $this->coordinator = $coordinator;
  48. $this->container = $container;
  49. $this->logger = $logger;
  50. }
  51. public function process(string $service, IRequest $request): ?IResponse {
  52. $handlers = $this->loadHandlers();
  53. $context = new class($request) implements IRequestContext {
  54. /** @var IRequest */
  55. private $request;
  56. public function __construct(IRequest $request) {
  57. $this->request = $request;
  58. }
  59. public function getHttpRequest(): IRequest {
  60. return $this->request;
  61. }
  62. };
  63. $subject = $request->getParam('resource');
  64. $initialResponse = new JrdResponse($subject ?? '');
  65. $finalResponse = array_reduce($handlers, function (?IResponse $previousResponse, IHandler $handler) use ($context, $service) {
  66. return $handler->handle($service, $context, $previousResponse);
  67. }, $initialResponse);
  68. if ($finalResponse instanceof JrdResponse && $finalResponse->isEmpty()) {
  69. return null;
  70. }
  71. return $finalResponse;
  72. }
  73. /**
  74. * @return IHandler[]
  75. */
  76. private function loadHandlers(): array {
  77. $context = $this->coordinator->getRegistrationContext();
  78. if ($context === null) {
  79. throw new RuntimeException("Well known handlers requested before the apps had been fully registered");
  80. }
  81. $registrations = $context->getWellKnownHandlers();
  82. $this->logger->debug(count($registrations) . " well known handlers registered");
  83. return array_filter(
  84. array_map(function (ServiceRegistration $registration) {
  85. /** @var ServiceRegistration<IHandler> $registration */
  86. $class = $registration->getService();
  87. try {
  88. $handler = $this->container->get($class);
  89. if (!($handler) instanceof IHandler) {
  90. $this->logger->error("Well known handler $class is invalid");
  91. return null;
  92. }
  93. return $handler;
  94. } catch (QueryException $e) {
  95. $this->logger->error("Could not load well known handler $class", [
  96. 'exception' => $e,
  97. 'app' => $registration->getAppId(),
  98. ]);
  99. return null;
  100. }
  101. }, $registrations)
  102. );
  103. }
  104. }