Beispiel #1
0
 protected function dispatchRequest(HttpRequest $request, HttpDriverContext $context, RouteMatch $match) : \Generator
 {
     // TODO: Add support for param converters.
     $ref = $match->handler->getReflection();
     $args = [];
     foreach ($ref->getParameters() as $param) {
         if (isset($match->params[$param->name])) {
             $args[] = $match->params[$param->name];
             continue;
         }
         $type = $param->getClass();
         if ($type) {
             switch ($type->name) {
                 case HttpRequest::class:
                     $args[] = $request;
                     continue 2;
                 case PathParams::class:
                     $args[] = new PathParams($match->params);
                     continue 2;
             }
             foreach ($this->compiler->getBodyReaders() as $reader) {
                 if ($reader->isSupported($type)) {
                     $args[] = (yield from $reader->readBody($request, $type));
                     continue 2;
                 }
             }
             $args[] = $this->container->get($type->name, $param->isOptional());
         } else {
             if (!$param->isOptional()) {
                 throw new StatusException(Http::CONFLICT, \sprintf('Missing action param "%s"', $param->name));
             }
             $args[] = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null;
         }
     }
     $result = $match->handler->getAction()(...$args);
     if ($result instanceof \Generator) {
         $result = (yield from $result);
     }
     $type = \is_object($result) ? \get_class($result) : \gettype($result);
     foreach ($this->compiler->getBodyWriters() as $writer) {
         $response = $writer->createResponse($request, $result);
         if ($response instanceof \Generator) {
             $response = (yield from $response);
         }
         if ($response !== null) {
             return $response;
         }
     }
     return $context->respond($request, $result);
 }
Beispiel #2
0
 /**
  * Dispatch the given HTTP request to the given action.
  */
 protected function processRequest(HttpDriverContext $context, SocketStream $socket, callable $action, bool &$upgraded, HttpRequest $request, bool $close) : \Generator
 {
     static $remove = ['Keep-Alive', 'Content-Length', 'Transfer-Encoding'];
     // No need for TCP_NODELAY as the connection will be closed anyways flushing the last chunk without delay.
     if ($close) {
         $socket->setTcpNoDelay(false);
     }
     try {
         if ($request->getProtocolVersion() == '1.1' && !$request->hasHeader('Host')) {
             throw new StatusException(Http::BAD_REQUEST, 'Missing HTTP Host header');
         }
         foreach ($remove as $name) {
             $request = $request->withoutHeader($name);
         }
         $next = new NextMiddleware($context->getMiddlewares(), function (HttpRequest $request) use($context, $action) {
             $response = $action($request, $context->withPrependedResponder(function (HttpRequest $request, $result) {
                 return $this->upgradeResult($request, $result);
             }));
             if ($response instanceof \Generator) {
                 $response = (yield from $response);
             }
             if (!$response instanceof HttpResponse) {
                 $response = $this->upgradeResult($request, $response);
             }
             return $context->respond($request, $response);
         }, $this->logger);
         $response = (yield from $next($request));
         $handler = $response->getAttribute(UpgradeResultHandler::class);
         if ($handler instanceof UpgradeResultHandler) {
             $upgraded = true;
             return yield from $this->upgradeResultConnection($handler, $socket, $request, $response);
         }
         return yield from $this->sendResponse($socket, $request, $response, $close);
     } catch (\Throwable $e) {
         return yield from $this->sendErrorResponse($socket, $request, $e);
     }
 }