If we go to node view we receive non catchable MethodNotAllowedException.
Step to reproduce:
1. Install module rest.
2. Install module language.
3. Install module page_manager(Seams that this step can be excluded).
4. Create some language.
5. go to /admin/config/regional/language/detection and check Account administration pages.
6. Go to user edit page and set some language in "Administration pages language".
7. Go to node view.

You will receive:

Symfony\Component\Routing\Exception\MethodNotAllowedException: in Symfony\Component\Routing\Matcher\UrlMatcher->match() (line 97 of vendor/symfony/routing/Matcher/UrlMatcher.php).

Drupal\Core\Routing\UrlMatcher->finalMatch(Object, Object) (Line: 152)
Symfony\Cmf\Component\Routing\NestedMatcher\NestedMatcher->matchRequest(Object) (Line: 258)
Symfony\Cmf\Component\Routing\DynamicRouter->matchRequest(Object) (Line: 185)
Symfony\Cmf\Component\Routing\ChainRouter->doMatch('/node/212', Object) (Line: 155)
Symfony\Cmf\Component\Routing\ChainRouter->matchRequest(Object) (Line: 89)
Drupal\Core\Routing\AccessAwareRouter->matchRequest(Object) (Line: 138)
Drupal\Core\Routing\AccessAwareRouter->match('/node/212') (Line: 139)
Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUserAdmin->isAdminPath(Object) (Line: 109)
Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUserAdmin->getLangcode(Object) (Line: 191)
Drupal\language\LanguageNegotiator->negotiateLanguage('language_interface', 'language-user-admin') (Line: 136)
Drupal\language\LanguageNegotiator->initializeType('language_interface') (Line: 223)
Drupal\language\ConfigurableLanguageManager->getCurrentLanguage() (Line: 84)
Drupal\language\EventSubscriber\LanguageRequestSubscriber->onKernelRequestLanguage(Object, 'kernel.request', Object) (Line: 116)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.request', Object) (Line: 120)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 62)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 62)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 53)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 103)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 55)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 632)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)


george.karaivanov created an issue. See original summary.

george.karaivanov’s picture

Method Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUserAdmin\isAdminPath

should catch MethodNotAllowedException as well.

I've create patch that fix it

george.karaivanov’s picture

Status: Active » Needs review
dawehner’s picture

This reads totally reasonable. Do you think its possible to write a test for that?

george.karaivanov’s picture

Same story was on https://www.drupal.org/node/2619700
Was fixed same way

dawehner’s picture

Fair, but some test coverage would be nice nevertheless.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

lslinnet’s picture

Status: Needs review » Needs work

I am currently experiencing this issue on a project I am working on where we have a route similar to this:

  path: '/mymodule/something'
    _controller: '\Drupal\mymodule_api\Controller\MyModuleApiController::fetchSomething'
    _title: 'title'
    _access: 'TRUE'
    _method: 'POST'

When a logged in user tries to access it the Language negotiation fails because of the route matching creates an incomplete request object (it basically thinks a POST request can be matched like a GET request).

It do not seem farfetched to have a route where only POST is a valid method and not allowing for proper route matching due to the request method seems to be an wrong way to "solve" the issue.

I would aim for a solution that takes the current request into account when doing the route matching instead of mocking a new request.

lslinnet’s picture

I tried with the following implementation which takes the request method into consideration, haven't verified if it passes any of the internal tests, but seems to solve the problem at hand.

diff --git a/core/modules/user/src/Plugin/LanguageNegotiation/LanguageNegotiationUserAdmin.php b/core/modules/user/src/Plugin/LanguageNegotiation/LanguageNegotiationUserAdmin.php
index c00509f..a3a5c10 100644
--- a/core/modules/user/src/Plugin/LanguageNegotiation/LanguageNegotiationUserAdmin.php
+++ b/core/modules/user/src/Plugin/LanguageNegotiation/LanguageNegotiationUserAdmin.php
@@ -11,6 +11,7 @@
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
+use Symfony\Component\Routing\Exception\MethodNotAllowedException;
 use Symfony\Component\Routing\Exception\ResourceNotFoundException;
 use Symfony\Component\Routing\Matcher\UrlMatcherInterface;

@@ -131,7 +132,12 @@ protected function isAdminPath(Request $request) {
           // prefixes and other path components that inbound processing would
           // clear out, so we can attempt to load the route clearly.
           $path = $this->pathProcessorManager->processInbound(urldecode(rtrim($request->getPathInfo(), '/')), $request);
-          $attributes = $this->router->match($path);
+          if (method_exists($this->router, 'matchRequest')) {
+            $attributes = $this->router->matchRequest(Request::create($path, $request->getMethod()));
+          }
+          else {
+            $attributes = $this->router->match($path);
+          }
         catch (ResourceNotFoundException $e) {
           return FALSE;
lslinnet’s picture

Second though, here is a patch fil with a minor update checking if we are dealing with an instance of RequestMatcherInterface as the router.

lslinnet’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 10: not_allowed_exception_2706241-10.patch, failed testing.

dpi’s picture

I cannot reproduce this issue using the steps in the issue summary.

Including with page_manager-alpha14

Is this still a problem?

lslinnet’s picture

@dpi, this is reproducible without page_manager module - so yes this is still an issue.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

sathish.redcrackle’s picture

I checked in drupal 8.3 and couldn't reproduce this issue.
Steps i followed:
1. Enabled Rest, language, page_manager
2. Created languages
3. changed settings in /admin/config/regional/language/detection and checked Account administration pages
4. and in user edit page i have set language in "Administration pages language".
5. went to node/view pages and i found no error.

lslinnet’s picture

#16 the steps above might not reproduce the issue, but I could not at a quick glance at the 8.3.x codebase see changes that would prevent this from happening in the previous mentioned case I ran into.

Will take a look at this over the weekend and see where we are in regards to this functioning as needed.

Wim Leers’s picture

Title: MethodNotAllowedException on node view for admin » LanguageNegotiationUserAdmin does not catch MethodNotAllowedException and hence fails when negotiating the language for REST routes (e.g. REST export views)
Issue tags: +API-First Initiative
Wim Leers’s picture

Wim Leers’s picture

This is very similar to #2822190: PathValidator validates based on a RequestContext leaked from the current request, resulting in false negatives during CLI requests and POST submissions, which fixed \Drupal\Core\Path\PathValidator::getPathAttributes(). That method is very similar to \Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUserAdmin::isAdminPath().

Wim Leers’s picture

Issue tags: +Routing, +language negotiation
Wim Leers’s picture

Actually, I think this belongs in routing system, since that's where the root cause lies.