Completed
Pull Request — master (#419)
by Yanick
03:08
created

KernelClient::__construct()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 15
rs 9.4285
cc 3
eloc 8
nc 3
nop 1
1
<?php
2
3
/*
4
 * This file is part of the FOSHttpCache package.
5
 *
6
 * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace FOS\HttpCache\SymfonyCache;
13
14
use Http\Client\HttpAsyncClient;
15
use Http\Promise\FulfilledPromise;
16
use Psr\Http\Message\RequestInterface;
17
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
18
use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;
19
use Symfony\Component\HttpFoundation\Request;
20
use Symfony\Component\HttpKernel\HttpKernelInterface;
21
use Zend\Diactoros\ServerRequest;
22
23
/**
24
 * An implementation of HttpAsyncClient that allows direct routing through the
25
 * Symfony HttpCache kernel without executing a real HTTP request.
26
 * It uses the HttpFoundationFactory and the Zend DiactorosFactory to convert
27
 * between PSR-7 requests and responses. Both are optional dependencies of this
28
 * package thus existence of the respective classes is checked for in the
29
 * constructor of this client. It is only needed if you have a single node
30
 * setup of Symfony and serves as kind of a shortcut for easier configuration.
31
 * If you use Varnish or have a multiple node Symfony setup, this class is entirely
32
 * useless to you and you can happily ignore it.
33
 *
34
 * @author Yanick Witschi <[email protected]>
35
 */
36
class KernelClient implements HttpAsyncClient
37
{
38
    /**
39
     * @var HttpCacheAwareKernelInterface
40
     */
41
    private $kernel;
42
43
    /**
44
     * @var HttpFoundationFactory
45
     */
46
    private $httpFoundationFactory;
47
48
    /**
49
     * @var DiactorosFactory
50
     */
51
    private $psr7Factory;
52
53
    /**
54
     * KernelClient constructor.
55
     *
56
     * @param HttpCacheAwareKernelInterface $kernel
57
     */
58
    public function __construct(HttpCacheAwareKernelInterface $kernel)
59
    {
60
        $this->kernel = $kernel;
61
62
        if (!class_exists(HttpFoundationFactory::class)) {
63
            throw new \RuntimeException('Install symfony/psr-http-message-bridge to use this client.');
64
        }
65
66
        if (!class_exists(DiactorosFactory::class)) {
67
            throw new \RuntimeException('Install zendframework/zend-diactoros to use this client.');
68
        }
69
70
        $this->httpFoundationFactory = new HttpFoundationFactory();
71
        $this->psr7Factory = new DiactorosFactory();
72
    }
73
74
    /**
75
     * Converts a PSR-7 request to a Symfony HttpFoundation request, runs
76
     * it through the HttpCache kernel and converts the response back to a PSR-7
77
     * response.
78
     *
79
     * {@inheritdoc}
80
     */
81
    public function sendAsyncRequest(RequestInterface $request)
82
    {
83
        $symfonyRequest = Request::createFromGlobals();
84
        $symfonyRequest->server->set('REMOTE_ADDR', '127.0.0.1');
85
86
        $query = [];
87
        $parts = explode('&', $request->getUri()->getQuery());
88
        foreach ($parts as $part) {
89
            $chunks = explode('=', $part, 2);
90
            $query[$chunks[0]] = $chunks[1];
91
        }
92
93
        $serverRequest = new ServerRequest(
94
            $symfonyRequest->server->all(),
95
            [],
96
            $request->getUri(),
97
            $request->getMethod(),
98
            $request->getBody(),
99
            $request->getHeaders(),
100
            $symfonyRequest->cookies->all(),
101
            $query
102
        );
103
104
        $symfonyRequest = $this->httpFoundationFactory->createRequest($serverRequest);
105
        $symfonyResponse = $this->kernel->getHttpCache()->handle($symfonyRequest, HttpKernelInterface::MASTER_REQUEST, false);
106
        $psrResponse = $this->psr7Factory->createResponse($symfonyResponse);
107
108
        return new FulfilledPromise($psrResponse);
109
    }
110
}
111