PathValidator::getUrlIfValid() does not support non-HTML/non-GET routes

Created on 13 February 2017, almost 8 years ago
Updated 24 February 2023, almost 2 years ago

Problem/Motivation

As we have seen in #2822190: PathValidator validates based on a RequestContext leaked from the current request, resulting in false negatives during CLI requests and POST submissions β†’ the PathValidator service is far from being perfect. It was designed to be used for menu links, but got added to all kind of places over time.

One problem we have is that it filters out non GET routes. On top of that it also filters out non HTML routes.

Which means that PathValidator::getUrlIfValid() doesn't do what its name says: it doesn't validate paths/URLs β€” it only does that for routes returning HTML responses for GET requests.

Proposed resolution

  • Agree on the expected behaviour
  • Write tests for that
  • Implement that.

Remaining tasks

User interface changes

API changes

Data model changes

πŸ› Bug report
Status

Active

Version

9.5

Component
RoutingΒ  β†’

Last updated 3 days ago

Created by

πŸ‡©πŸ‡ͺGermany dawehner

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡ΊπŸ‡¦Ukraine mykola dolynskyi Poltava

    had such issue, first request respects _format=json and next for the same server invocations are not.

    after wasted hours of tracing and debugging I ended up with adding custom middleware

    <?php
    
    namespace Drupal\xxx;
    
    use Drupal\Core\Http\InputBag;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpKernel\HttpKernelInterface;
    use Symfony\Component\HttpFoundation\InputBag as SymfonyInputBag;
    
    /**
     * FirstMiddleware middleware.
     */
    class RequestFormatMiddleware implements HttpKernelInterface {
    
        /**
         * The kernel.
         *
         * @var \Symfony\Component\HttpKernel\HttpKernelInterface
         */
        protected $httpKernel;
    
        /**
         * Constructs the FirstMiddleware object.
         *
         * @param \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel
         *   The decorated kernel.
         */
        public function __construct(HttpKernelInterface $http_kernel) {
            $this->httpKernel = $http_kernel;
        }
    
        /**
         * {@inheritdoc}
         */
        public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {
    
    		if(empty($request->getRequestFormat(null)) && !empty($request->get('_format'))) {
    			$request->setRequestFormat($request->get('_format'));
    		}
    
    		Request::setFactory(
    			function ($query, $request, $attributes, $cookies, $files, $server, $content) {
    				$current = \Drupal::request();
    				if(empty($attributes['_format']) && !empty($current->getRequestFormat(null))) {
    					$attributes['_format'] = $current->getRequestFormat(null);
    				}
    				$request = new Request($query, $request, $attributes, $cookies, $files, $server, $content);
    				foreach (['request', 'query', 'cookies'] as $bag) {
    					if (!($bag instanceof SymfonyInputBag)) {
    					$request->$bag = new InputBag($request->$bag->all());
    					}
    				}
    				return $request;
    			}
    		  );
    
            return $this->httpKernel->handle($request, $type, $catch);
        }
    
    }
Production build 0.71.5 2024