Маршрутизация имени хоста в Zend Expressive

Zend Expressive имеет адаптеры для Aura.Router, FastRoute и zend-mvc Router, и маршрут может легко соответствовать методу и пути:

<?php
$app->get('/foo', $middleware);

С помощью компонента zend-mvc Router можно сопоставить имя хоста:

<?php
use Zend\Mvc\Router\Http\Hostname;

$route = Hostname::factory([
    'route' => ':subdomain.example.com/foo',
    'constraints' => [
        'subdomain' => 'api',
    ],
]);

$router->addRoute('foo', $route);

Это также возможно с помощью компонента маршрутизации Symfony:

<?php
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;

$route = new Route(
    '/foo', // path
    array('_controller' => 'SomeController'), // default values
    array('subdomain' => 'api'), // requirements
    array(), // options
    '{subdomain}.example.com', // host
    array(), // schemes
    array() // methods
);

$routes = new RouteCollection();
$routes->add('foo', $route);

Итак, я хотел бы иметь возможность делать что-то подобное с Expressive и отправлять запрос другому промежуточному программному обеспечению в зависимости от поддомена:

// dispatch the requiest to ApiMiddleware
$app->get(':subdomain.example.com/foo', $ApiMiddleware, ['subdomain' => 'api']);

// dispatch the requiest to WebMiddleware
$app->get(':subdomain.example.com/foo', $WebMiddleware, ['subdomain' => 'www']);

Заранее спасибо!


person Vasil Dakov    schedule 01.02.2017    source источник
comment
Я не думаю, что какой-либо из маршрутизаторов поддерживает это. Что вы могли бы сделать, так это написать свой собственный мост для компонента Symfony Router. У него есть некоторые приятные особенности, которых не хватает другим.   -  person xtreamwayz    schedule 02.02.2017
comment
Существует PR для маршрутизации имени хоста.   -  person venca    schedule 03.02.2017


Ответы (1)


Почему вы не создали новое промежуточное ПО для извлечения запроса и не выбрали, какое промежуточное ПО должно вызываться в конвейере следующим?

Вы могли бы сделать что-то вроде этого:

Приложение \ Middleware \ DeciderMiddleware

<?php

namespace Application\Middleware;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

class DeciderMiddleware
{
    protected $apiMiddleware;
    protected $webMiddleware;

    public function __construct(
        callable $apiMiddleware,
        callable $webMiddleware
    ) {
        $this->apiMiddleware = $apiMiddleware;
        $this->webMiddleware = $webMiddleware;
    }

    public function __invoke(
        ServerRequestInterface $request,
        ResponseInterface $response,
        callable $next = null
    ) {
        if (strpos($request->getUri()->getHost(), 'api.') === 0) {
            return ($this->apiMiddleware)($request, $response);
        }

        if (strpos($request->getUri()->getHost(), 'www.') === 0) {
            return ($this->webMiddleware)($request, $response);
        }

        return $next($request, $response);
    }
}

конфигурация / автозагрузка / промежуточное ПО-pipeline.global.php

<?php

return [
    'dependencies' => [
        'factories' => [
            Application\Middleware\DeciderMiddleware::class => Application\Middleware\DeciderMiddlewareFactory::class
        ],
    ],
    'middleware_pipeline' => [
        'always' => [
            'middleware' => [
                Application\Middleware\DeciderMiddleware::class
            ],
            'priority' => 10000,
        ],
    ],
];

Единственное, что вам нужно сделать, это определить apiMiddleware и webMiddleware в DeciderMiddlewareFactory и инициализировать DeciderMiddleware-объект с этими параметрами.

person GreedyBytes    schedule 04.02.2017