|
11 | 11 |
|
12 | 12 | namespace FOS\HttpCacheBundle; |
13 | 13 |
|
| 14 | +use FOS\HttpCacheBundle\SymfonyCache\CacheEvent; |
| 15 | +use FOS\HttpCacheBundle\SymfonyCache\Events; |
14 | 16 | use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache as BaseHttpCache; |
| 17 | +use Symfony\Component\EventDispatcher\EventDispatcher; |
| 18 | +use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
| 19 | +use Symfony\Component\EventDispatcher\EventSubscriberInterface; |
15 | 20 | use Symfony\Component\HttpFoundation\Request; |
16 | | -use Symfony\Component\HttpFoundation\Response; |
17 | 21 | use Symfony\Component\HttpKernel\HttpKernelInterface; |
18 | 22 |
|
19 | 23 | /** |
|
26 | 30 | abstract class HttpCache extends BaseHttpCache |
27 | 31 | { |
28 | 32 | /** |
29 | | - * Hash for anonymous user. |
| 33 | + * @var EventDispatcherInterface |
30 | 34 | */ |
31 | | - const ANONYMOUS_HASH = '38015b703d82206ebc01d17a39c727e5'; |
| 35 | + private $eventDispatcher; |
32 | 36 |
|
33 | 37 | /** |
34 | | - * Accept header value to be used to request the user hash to the backend application. |
35 | | - * It must match the one defined in FOSHttpCacheBundle's configuration. |
36 | | - */ |
37 | | - const USER_HASH_ACCEPT_HEADER = 'application/vnd.fos.user-context-hash'; |
38 | | - |
39 | | - /** |
40 | | - * Name of the header the user context hash will be stored into. |
41 | | - * It must match the one defined in FOSHttpCacheBundle's configuration. |
42 | | - */ |
43 | | - const USER_HASH_HEADER = 'X-User-Context-Hash'; |
44 | | - |
45 | | - /** |
46 | | - * URI used with the forwarded request for user context hash generation. |
47 | | - */ |
48 | | - const USER_HASH_URI = '/_fos_user_context_hash'; |
49 | | - |
50 | | - /** |
51 | | - * HTTP Method used with the forwarded request for user context hash generation. |
52 | | - */ |
53 | | - const USER_HASH_METHOD = 'GET'; |
54 | | - |
55 | | - /** |
56 | | - * Prefix for session names. |
57 | | - * Must match your session configuration. |
58 | | - */ |
59 | | - const SESSION_NAME_PREFIX = 'PHPSESSID'; |
60 | | - |
61 | | - /** |
62 | | - * Generated user hash. |
63 | | - * |
64 | | - * @var string |
65 | | - */ |
66 | | - private $userHash; |
67 | | - |
68 | | - public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) |
69 | | - { |
70 | | - if (!$this->isInternalRequest($request)) { |
71 | | - // Prevent tampering attacks on the hash mechanism |
72 | | - if ($request->headers->get('accept') === static::USER_HASH_ACCEPT_HEADER |
73 | | - || $request->headers->get(static::USER_HASH_HEADER) !== null) { |
74 | | - return new Response('', 400); |
75 | | - } |
76 | | - |
77 | | - if ($request->isMethodSafe()) { |
78 | | - $request->headers->set(static::USER_HASH_HEADER, $this->getUserHash($request)); |
79 | | - } |
80 | | - } |
81 | | - |
82 | | - return parent::handle($request, $type, $catch); |
83 | | - } |
84 | | - |
85 | | - /** |
86 | | - * Checks if passed request object is to be considered internal (e.g. for user hash lookup). |
87 | | - * |
88 | | - * @param Request $request |
89 | | - * |
90 | | - * @return bool |
91 | | - */ |
92 | | - private function isInternalRequest(Request $request) |
93 | | - { |
94 | | - return $request->attributes->get('internalRequest', false) === true; |
95 | | - } |
96 | | - |
97 | | - /** |
98 | | - * Returns the user context hash for $request. |
| 38 | + * Set event dispatcher |
99 | 39 | * |
100 | | - * @param Request $request |
| 40 | + * @param EventDispatcherInterface $eventDispatcher |
101 | 41 | * |
102 | | - * @return string |
| 42 | + * @return $this |
103 | 43 | */ |
104 | | - private function getUserHash(Request $request) |
| 44 | + public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) |
105 | 45 | { |
106 | | - if (isset($this->userHash)) { |
107 | | - return $this->userHash; |
108 | | - } |
109 | | - |
110 | | - if ($this->isAnonymous($request)) { |
111 | | - return $this->userHash = static::ANONYMOUS_HASH; |
112 | | - } |
113 | | - |
114 | | - // Forward the request to generate the user hash |
115 | | - $forwardReq = $this->generateForwardRequest($request); |
116 | | - $resp = $this->handle($forwardReq); |
117 | | - // Store the user hash in memory for sub-requests (processed in the same thread). |
118 | | - $this->userHash = $resp->headers->get(static::USER_HASH_HEADER); |
119 | | - |
120 | | - return $this->userHash; |
| 46 | + $this->eventDispatcher = $eventDispatcher; |
121 | 47 | } |
122 | 48 |
|
123 | 49 | /** |
124 | | - * Checks if current request is considered anonymous. |
125 | | - * |
126 | | - * @param Request $request |
| 50 | + * Get event dispatcher |
127 | 51 | * |
128 | | - * @return bool |
| 52 | + * @return EventDispatcherInterface |
129 | 53 | */ |
130 | | - private function isAnonymous(Request $request) |
| 54 | + public function getEventDispatcher() |
131 | 55 | { |
132 | | - foreach ($request->cookies as $name => $value) { |
133 | | - if ($this->isSessionName($name)) { |
134 | | - return false; |
135 | | - } |
| 56 | + if (!$this->eventDispatcher) { |
| 57 | + $this->eventDispatcher = new EventDispatcher(); |
136 | 58 | } |
137 | 59 |
|
138 | | - return true; |
139 | | - } |
140 | | - |
141 | | - /** |
142 | | - * Checks if passed string can be considered as a session name, such as would be used in cookies. |
143 | | - * |
144 | | - * @param string $name |
145 | | - * |
146 | | - * @return bool |
147 | | - */ |
148 | | - private function isSessionName($name) |
149 | | - { |
150 | | - return strpos($name, static::SESSION_NAME_PREFIX) === 0; |
| 60 | + return $this->eventDispatcher; |
151 | 61 | } |
152 | 62 |
|
153 | 63 | /** |
154 | | - * Generates the request object that will be forwarded to get the user context hash. |
| 64 | + * Add subscriber |
155 | 65 | * |
156 | | - * @param Request $request |
| 66 | + * @param EventSubscriberInterface $subscriber |
157 | 67 | * |
158 | | - * @return Request |
| 68 | + * @return $this |
159 | 69 | */ |
160 | | - private function generateForwardRequest(Request $request) |
| 70 | + public function addSubscriber(EventSubscriberInterface $subscriber) |
161 | 71 | { |
162 | | - $forwardReq = Request::create(static::USER_HASH_URI, static::USER_HASH_METHOD, array(), array(), array(), $request->server->all()); |
163 | | - $forwardReq->attributes->set('internalRequest', true); |
164 | | - $forwardReq->headers->set('Accept', static::USER_HASH_ACCEPT_HEADER); |
165 | | - $this->cleanupForwardRequest($forwardReq, $request); |
| 72 | + $this->getEventDispatcher()->addSubscriber($subscriber); |
166 | 73 |
|
167 | | - return $forwardReq; |
| 74 | + return $this; |
168 | 75 | } |
169 | 76 |
|
170 | | - /** |
171 | | - * Cleans up request to forward for user hash generation. |
172 | | - * Cleans cookie header to only get proper sessionIds in it. This is to make the hash request cacheable. |
173 | | - * |
174 | | - * @param Request $forwardReq |
175 | | - * @param Request $originalRequest |
176 | | - */ |
177 | | - protected function cleanupForwardRequest(Request $forwardReq, Request $originalRequest) |
| 77 | + public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) |
178 | 78 | { |
179 | | - $sessionIds = array(); |
180 | | - foreach ($originalRequest->cookies as $name => $value) { |
181 | | - if ( $this->isSessionName($name)) { |
182 | | - $sessionIds[$name] = $value; |
183 | | - $forwardReq->cookies->set($name, $value); |
| 79 | + if ($this->getEventDispatcher()->hasListeners(Events::PRE_HANDLE)) { |
| 80 | + $event = new CacheEvent($this, $request); |
| 81 | + $this->getEventDispatcher()->dispatch(Events::PRE_HANDLE, $event); |
| 82 | + if ($event->getResponse()) { |
| 83 | + return $event->getResponse(); |
184 | 84 | } |
185 | 85 | } |
186 | | - $forwardReq->headers->set('Cookie', http_build_query($sessionIds, '', '; ')); |
| 86 | + |
| 87 | + return parent::handle($request, $type, $catch); |
187 | 88 | } |
188 | 89 | } |
0 commit comments