Hi everyone,

I'm a little bit surprised to see so many suggestions about how 
ServerMiddlewareInterface and ClientMiddlewareInterface should look like, 
obviously without much knowledge about the client-side.

The current state 
<https://github.com/php-fig/fig-standards/blob/82e2d1c1fd9a3782e0707cf0d4449b28cca8ffa9/proposed/http-middleware/middleware.md>
 
is:

interface MiddlewareInterface {}

interface ClientMiddlewareInterface extends MiddlewareInterface
{
    public function process(RequestInterface $request, DelegateInterface $next);
}

interface ServerMiddlewareInterface extends MiddlewareInterface
{
    public function process(ServerRequestInterface $request, DelegateInterface 
$frame);
}

interface DelegateInterface
{
    public function next(RequestInterface $request);
}

<https://github.com/php-fig/fig-standards/blob/master/proposed/http-middleware/middleware.md#23-psrhttpmiddlewareclientmiddlewareinterface>



Here are some falsehoods about the client-side, the list seems, by far, not 
exhaustive.

*1. HTTP Clients return their results synchronously*
It would be very clumsy to load a web page nowadays with all its assets 
sequentially. Thus HTTP clients like Guzzle 
<https://github.com/guzzle/guzzle> use asynchronous techniques like 
Promises (e.g. Guzzle Promises <https://github.com/guzzle/promises>), 
callbacks (e.g. node.js), generator based control flow, etc.

An example:

$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org');
$promise = $client->sendAsync($request)->then(function ($response) {
    echo 'I completed! ' . $response->getBody();
});


*2. Client Middlewares just transform Requests to Responses, doing it 
**synchronously 
is not a problem*
Maybe, this is appropriate on the server side, but not on the client. Just 
think about a Middleware which adds cookies to requests.

>From GuzzleHttp/Middleware 
<https://github.com/guzzle/guzzle/blob/5a5893c19f798175869eb94a88bb0b73e7acfb05/src/Middleware.php#L17-L44>
:
return function ($request, array $options) use ($handler) {
    // …
    $request = $cookieJar->withCookieHeader($request);
    return $handler($request, $options)
        ->then(function ($response) use ($cookieJar, $request) {
            $cookieJar->extractCookies($request, $response);
            return $response;
        }
    );
};

The Middleware have to:

   1. add the current cookie to the header: ->withCookieHeader($request)
   2. call the delegate: $handler($request, $options)
   3. extract the cookie

As the delegate returns a promise, we need to: $handler(…)->then(…).
Can we do better, e.g. use a sync delegate/handler? Nope, this would lead 
to call $promise->wait() within the delegate, which isn't performant. 

*3. Client Middlewares call their delegate almost once*
For the client-side it's absolutely valid to retry a request, e.g. 
GuzzleHttp/RetryMiddleware 
<https://github.com/guzzle/guzzle/blob/113071af3b2b9eb96b05dab05472cbaed64a3df4/src/RetryMiddleware.php>

*4. Client Middlewares don't need to create requests, they can modify the 
given $request*
Just think about an authorization middleware, e.g. for OAuth or similar.
It would be dangerous or at least very odd to reuse $request for login 
endpoints:
class AuthMiddleware implements ClientMiddlewareInterface
{
    // …
    public function process(RequestInterface $request, DelegateInterface 
$next)
    {
        if ($this->accessToken === null) {
            $loginRequest = $this->createLoginRequest();
            $this->accessToken = $next->next($loginRequest)->getBody()->
getContents();
        }

        $request = $request->withHeader('Authorization', $this->accessToken
);
        return $next($request);
    }


    private function createLoginRequest()
    {
        $req = $this->requestFactory->createRequest('POST', '/login');
        // add $login, $password…
        return $req;
    }
}

This was just some food for thought, hopefully pushing PSR-15 a bit forward.

Best regards,
Michael

-- 
You received this message because you are subscribed to the Google Groups "PHP 
Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/php-fig/f57bb59a-5784-4e6d-aaea-bd738e49a00b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to