Chris@18: getRequest(); Chris@18: if ($request->getRequestFormat() !== 'api_json') { Chris@18: return; Chris@18: } Chris@18: Chris@18: $this->validateQueryParams($request); Chris@18: } Chris@18: Chris@18: /** Chris@18: * Validates custom (implementation-specific) query parameter names. Chris@18: * Chris@18: * @param \Symfony\Component\HttpFoundation\Request $request Chris@18: * The request for which to validate JSON:API query parameters. Chris@18: * Chris@18: * @return \Drupal\jsonapi\ResourceResponse|null Chris@18: * A JSON:API resource response. Chris@18: * Chris@18: * @see http://jsonapi.org/format/#query-parameters Chris@18: */ Chris@18: protected function validateQueryParams(Request $request) { Chris@18: $invalid_query_params = []; Chris@18: foreach (array_keys($request->query->all()) as $query_parameter_name) { Chris@18: // Ignore reserved (official) query parameters. Chris@18: if (in_array($query_parameter_name, JsonApiSpec::getReservedQueryParameters())) { Chris@18: continue; Chris@18: } Chris@18: Chris@18: if (!JsonApiSpec::isValidCustomQueryParameter($query_parameter_name)) { Chris@18: $invalid_query_params[] = $query_parameter_name; Chris@18: } Chris@18: } Chris@18: Chris@18: // Drupal uses the `_format` query parameter for Content-Type negotiation. Chris@18: // Using it violates the JSON:API spec. Nudge people nicely in the correct Chris@18: // direction. (This is special cased because using it is pretty common.) Chris@18: if (in_array('_format', $invalid_query_params, TRUE)) { Chris@18: $uri_without_query_string = $request->getSchemeAndHttpHost() . $request->getBaseUrl() . $request->getPathInfo(); Chris@18: $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\' 🙏'); Chris@18: $exception->setHeaders(['Link' => $uri_without_query_string]); Chris@18: throw $exception; Chris@18: } Chris@18: Chris@18: if (empty($invalid_query_params)) { Chris@18: return NULL; Chris@18: } Chris@18: Chris@18: $message = sprintf('The following query parameters violate the JSON:API spec: \'%s\'.', implode("', '", $invalid_query_params)); Chris@18: $exception = new CacheableBadRequestHttpException((new CacheableMetadata())->addCacheContexts(['url.query_args']), $message); Chris@18: $exception->setHeaders(['Link' => 'http://jsonapi.org/format/#query-parameters']); Chris@18: throw $exception; Chris@18: } Chris@18: Chris@18: /** Chris@18: * {@inheritdoc} Chris@18: */ Chris@18: public static function getSubscribedEvents() { Chris@18: $events[KernelEvents::REQUEST][] = ['onRequest']; Chris@18: return $events; Chris@18: } Chris@18: Chris@18: }