Mercurial > hg > cmmr2012-drupal-site
comparison core/modules/jsonapi/src/EventSubscriber/JsonApiRequestValidator.php @ 5:12f9dff5fda9 tip
Update to Drupal core 8.7.1
author | Chris Cannam |
---|---|
date | Thu, 09 May 2019 15:34:47 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
4:a9cd425dd02b | 5:12f9dff5fda9 |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\jsonapi\EventSubscriber; | |
4 | |
5 use Drupal\Core\Cache\CacheableMetadata; | |
6 use Drupal\jsonapi\JsonApiSpec; | |
7 use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |
8 use Symfony\Component\HttpFoundation\Request; | |
9 use Symfony\Component\HttpKernel\Event\GetResponseEvent; | |
10 use Drupal\Core\Http\Exception\CacheableBadRequestHttpException; | |
11 use Symfony\Component\HttpKernel\KernelEvents; | |
12 | |
13 /** | |
14 * Request subscriber that validates a JSON:API request. | |
15 * | |
16 * @internal JSON:API maintains no PHP API. The API is the HTTP API. This class | |
17 * may change at any time and could break any dependencies on it. | |
18 * | |
19 * @see https://www.drupal.org/project/jsonapi/issues/3032787 | |
20 * @see jsonapi.api.php | |
21 */ | |
22 class JsonApiRequestValidator implements EventSubscriberInterface { | |
23 | |
24 /** | |
25 * Validates JSON:API requests. | |
26 * | |
27 * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event | |
28 * The event to process. | |
29 */ | |
30 public function onRequest(GetResponseEvent $event) { | |
31 $request = $event->getRequest(); | |
32 if ($request->getRequestFormat() !== 'api_json') { | |
33 return; | |
34 } | |
35 | |
36 $this->validateQueryParams($request); | |
37 } | |
38 | |
39 /** | |
40 * Validates custom (implementation-specific) query parameter names. | |
41 * | |
42 * @param \Symfony\Component\HttpFoundation\Request $request | |
43 * The request for which to validate JSON:API query parameters. | |
44 * | |
45 * @return \Drupal\jsonapi\ResourceResponse|null | |
46 * A JSON:API resource response. | |
47 * | |
48 * @see http://jsonapi.org/format/#query-parameters | |
49 */ | |
50 protected function validateQueryParams(Request $request) { | |
51 $invalid_query_params = []; | |
52 foreach (array_keys($request->query->all()) as $query_parameter_name) { | |
53 // Ignore reserved (official) query parameters. | |
54 if (in_array($query_parameter_name, JsonApiSpec::getReservedQueryParameters())) { | |
55 continue; | |
56 } | |
57 | |
58 if (!JsonApiSpec::isValidCustomQueryParameter($query_parameter_name)) { | |
59 $invalid_query_params[] = $query_parameter_name; | |
60 } | |
61 } | |
62 | |
63 // Drupal uses the `_format` query parameter for Content-Type negotiation. | |
64 // Using it violates the JSON:API spec. Nudge people nicely in the correct | |
65 // direction. (This is special cased because using it is pretty common.) | |
66 if (in_array('_format', $invalid_query_params, TRUE)) { | |
67 $uri_without_query_string = $request->getSchemeAndHttpHost() . $request->getBaseUrl() . $request->getPathInfo(); | |
68 $exception = new CacheableBadRequestHttpException((new CacheableMetadata())->addCacheContexts(['url.query_args:_format']), 'JSON:API does not need that ugly \'_format\' query string! 🤘 Use the URL provided in \'links\' 🙏'); | |
69 $exception->setHeaders(['Link' => $uri_without_query_string]); | |
70 throw $exception; | |
71 } | |
72 | |
73 if (empty($invalid_query_params)) { | |
74 return NULL; | |
75 } | |
76 | |
77 $message = sprintf('The following query parameters violate the JSON:API spec: \'%s\'.', implode("', '", $invalid_query_params)); | |
78 $exception = new CacheableBadRequestHttpException((new CacheableMetadata())->addCacheContexts(['url.query_args']), $message); | |
79 $exception->setHeaders(['Link' => 'http://jsonapi.org/format/#query-parameters']); | |
80 throw $exception; | |
81 } | |
82 | |
83 /** | |
84 * {@inheritdoc} | |
85 */ | |
86 public static function getSubscribedEvents() { | |
87 $events[KernelEvents::REQUEST][] = ['onRequest']; | |
88 return $events; | |
89 } | |
90 | |
91 } |