Problem/Motivation

This is rather new: we see increasing website exceptions created by simple anonymous GET calls.
Everything in this Drupal install (and a testing web I used to reproduce) is up to date (Drupal 8.6.10). None of both uses any module with REST or json functionality.

See original issue summary for more.

This is still reproducible in the latest versions of Drupal (10.1.x, currently).

Steps to reproduce

  1. Install a fresh Drupal site.
  2. Create a new node.
  3. Navigate to the node view.
  4. Add the query parameter ?_format=hal_json to the node url (e.g., {base_url}/node/1?_format=hal_json).
  5. Observe 406 Not Acceptable response with (plaintext) message The website encountered an unexpected error. Please try again later.The website encountered an unexpected error. Please try again later.<br />

Proposed resolution

Handle all 4xx errors that aren't caught in other exception subscribers and provide a more useful message so we don't fall back on the "The website encountered an unexpected error." message.

Remaining tasks

Review and commit!

User interface changes

None.

API changes

None.

Data model changes

None.

Release notes snippet

None.

Original issue summary

This is rather new: we see increasing website exceptions created by simple anonymous GET calls.
Everything in this Drupal install (and a testing web I used to reproduce) is up to date (Drupal 8.6.10). None of both uses any module with REST or json functionality.

All one gets is if trying a GET like that in a Browser is: "The website encountered an unexpected error. Please try again later. "
In the apache logs this is just a 404, if trying to visit the related watchdog detail, another error is thrown.

I hope, it's OK if I post here, how to reproduce:

wget 'http://your-testing.tld/node/1?_format=hal_json'

Formats that don't even exist should be ignored.

Formats that aren't in use at all (module not installed) probably should be ignored, too.

Comments

indigoxela created an issue. See original summary.

indigoxela’s picture

Issue summary: View changes
indigoxela’s picture

UPDATE: if the node/[ID] exists, the outcome is slightly different: "406 Not Acceptable" in Browser/wget

Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException: Not acceptable format: hal_json in Drupal\Core\EventSubscriber\RenderArrayNonHtmlSubscriber->onRespond() (line 30 of ...core/lib/Drupal/Core/EventSubscriber/RenderArrayNonHtmlSubscriber.php).

But still an exception if trying to see the watchdog detail. Above is the title of the watchdog entry link.

indigoxela’s picture

Title: Website exception via GET » Website exception via GET with QUERY_STRING "?_format=..."
Related issues: +#2827766: PathValidator can get NotAcceptableHttpException

Some more digging: it really seems, 2827766 is related, at least partly.

And I see two base problems, which seem to be unrelated to each other:

1) using query string "?_format=" always causes "406 Not Acceptable", which is obviously wrong. "?_format=1234" for instance should be ignored instead of throwing "No route found for the specified format 1234".

2) a wrong referer string should never cause watchdog to throw an exception. If causing a 404 (hence put into the dblog) with a wrong referer string, watchdog produces an exception, when viewing that detail page. Uncaught PHP Exception InvalidArgumentException: "The URI 'notreally.tld' is invalid." (Referers aren't anything reliable out in the web.)

indigoxela’s picture

The second problem described in #4 (watchdog exception on detail page with invalid urls) is already covered by another issue Refactor how dblog module is rendering links in event details.

The first problem described in #4 ("406 Not Acceptable" on nonsense GET param) is partly covered in the related issue PathValidator can get NotAcceptableHttpException

But there's an important question not covered yet: Do we really want to throw exceptions on nonsense GET params?

Example: /?foo=bar&baz
That's completely ignored as foo and baz have no meaning at all.

But: /?_format=1234
Throws an exception although format 1234 is obviously just rubbish.

I think, we should ignore that, too.

indigoxela’s picture

Issue summary: View changes

Updated summary.

mcannon’s picture

I did some tests on a clean install and it seems like this specific issue is tied to the exact parameter of "_format". I tried it without the leading underscore and it works as expected. I also tried "?foo=bar&baz" as well and no issue.

Is there an unknown reason why the "_format" parameter cause such an error? It might be intentional, not a bug.

indigoxela’s picture

I tried it without the leading underscore and it works as expected.

"_format" is a parameter known to Drupal, but only useful, if one of the implementing modules is installed. "format" without underscore is like "baz" and "foo" - totally ignored.

The question I'm asking is:

1) Shall we really throw a warning using the unimplemented format, if none of the modules implementing "_format" is enabled at all? html is the only known format then.

Right now Drupal shows a warning in the format (xml/json) "No route found for the specified format hal_json. Supported formats: html."

In how far does this make sense at all?

2) Shall we really throw exceptions, if the value is obvious rubbish.

"?_format=1234" shouldn't cause an exception, but does (reproducible).

"The website encountered an unexpected error. Please try again later."

Wouldn't it be better to check against a list of plausible formats, check if the one being asked for is implemented and possibly show a Drupal message if not. Or even totally ignore, if the format is either not active or it's a nonsense format.

slip’s picture

Status: Active » Needs review
StatusFileSize
new6.25 KB

I agree that this is a bug. We should catch this exception and show the proper, HTML-formatted error page. Attached is a patch for consideration.

With this patch:
http://localhost:8080/user/1/?_format=json - Shows json error message as before
http://localhost:8080/user/1/?_format=NOPE - Shows an HTML 406 error page saying "A client error happened"
http://localhost:8080/user/1/?_format=html - Shows HTML user page
http://localhost:8080/user/1 - Shows HTML user page

Status: Needs review » Needs work

The last submitted patch, 9: no-format-3035589-9.patch, failed testing. View results

slip’s picture

Status: Needs work » Needs review
StatusFileSize
new6.19 KB

Reroll

Status: Needs review » Needs work

The last submitted patch, 11: no-format-3035589-11.patch, failed testing. View results

indigoxela’s picture

@slip many thanks for your patch.

It's a lot better already, tested it on a fresh Drupal standard install. No more website exceptions with unknown/nonsense formats.

I guess, it's by intention that even if none of the modules (Serialization, HAL, REST...) is active and the only available format is html, still http error is "406".

dblog still shows: Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException: Not acceptable format: ...

But that's probably a job for the related issue. Is that correct? Or should both problems get fixed at once? The related issue (PathValidator can get NotAcceptableHttpException) has stalled a bit.

indigoxela’s picture

And: wow, as the test is failing now, someone really thought, throwing exceptions for nonsense GET request is a good idea...

I don't get the concept.

slip’s picture

StatusFileSize
new4.75 KB

Here's another patch which fixes @indigoxela point about the exception still being logged, and it also reduces the scope of the fix to the problem at hand.

slip’s picture

Status: Needs work » Needs review
StatusFileSize
new4.42 KB
indigoxela’s picture

Patch #16 really makes sense.

Tested with and without rest module enabled (but without any actual format other than html in use). It would be cool, if someone who is actually using formats (services), takes a look.

No more website exceptions on unknown/nonsense formats. And a useful message in the dblog ("client error").
Besides the fixed exceptions, the behavior is the same as without patch (error 406).

We probably can't accomplish more without bigger changes.

indigoxela’s picture

I do have one concern: shouldn't there be some escaping for the request?

The original test checked for escaped markup, but your test accepts the script tag directly.

slip’s picture

StatusFileSize
new4.51 KB

It's text/plain so that risk is mitigated. You definitely do have a point tho. Updated the patch.

indigoxela’s picture

@slip many thanks for your patch!

From my point of view, this looks good for a commit.

But as mentioned before, I don't use any of the other formats/services.
It's not that I'm really worried about side effects, but you never know.

Status: Needs review » Needs work

The last submitted patch, 19: no-format-3035589-19.patch, failed testing. View results

slip’s picture

Status: Needs work » Reviewed & tested by the community

Moving to "Reviewed & tested by the community" per comment #20 now that the tests are passing.

alexpott’s picture

Status: Reviewed & tested by the community » Needs review

@slip thanks you so much for working on this. It is community policy to not rtbc your own patches and @indigoxela's comment in #20 says that whilst they think the code is good they don't feel they can rtbc.

alexpott’s picture

Status: Needs review » Needs work

I think the test needs to assert that the error is a 406. Maybe an explicit 406 test ala \Drupal\KernelTests\Core\Routing\ExceptionHandlingTest::test405().

  1. +++ b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionUnknownFormatSubscriber.php
    @@ -0,0 +1,49 @@
    +    // A very low priority so that custom handlers are almost certain to fire
    +    // before it, even if someone forgets to set a priority.
    +    // This is also lower than json and HTML so that those have priority.
    +    return -200;
    

    This is a good comment. I think we should consider setting this to -250 to be even closer to the -256 of the final subscriber.

  2. +++ b/core/lib/Drupal/Core/EventSubscriber/ExceptionLoggingSubscriber.php
    @@ -53,6 +53,17 @@ public function on404(GetResponseForExceptionEvent $event) {
    +    $this->logger->get('client error')->warning('@uri', ['@uri' => $request->getRequestUri()]);
    

    Can we not log something more specific?

indigoxela’s picture

Can we not log something more specific?

The question is: what could be helpful for admins reading the message?

To me it already makes sense.
For example: "client error" and "/node/1?_format=xml" when there's no such format available.

Possibly "No such format available." could make sense, or "Drupal can't handle format %format for that type of entity."
Not sure.

slip’s picture

StatusFileSize
new5.33 KB

For logging I was mimicking what the other loggers do in that class for access denied and page not found. In this patch I'm adding all the information I think it makes sense to add.

The test is also added and I lowered the priority as suggested.

@alexpott thanks a lot for the feedback!

alexpott’s picture

+++ b/core/lib/Drupal/Core/EventSubscriber/ExceptionLoggingSubscriber.php
@@ -53,6 +53,21 @@ public function on404(GetResponseForExceptionEvent $event) {
+  /**
+   * Log 406 errors.
+   *
+   * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
+   *   The event to process.
+   */
+  public function on406(GetResponseForExceptionEvent $event) {
+    $exception = $event->getException();
+    $request = $event->getRequest();
+    $this->logger->get('client error')->warning(
+      'There was an error in the client request: "@message" at @uri.',
+      ['@message' => $exception->getMessage(), '@uri' => $request->getRequestUri()]
+    );
+  }

So... I was wondering do we actually want to log these? I'm not sure it is necessary to bring them into the Drupal logs. It's not quite the same as access denied or 404.

Imo we could drop this code. It's not necessary to fix the bug.

indigoxela’s picture

I'm not sure it is necessary to bring them into the Drupal logs. It's not quite the same as access denied or 404.

Wait... not so fast. ;)
Let's say, something went totally wrong with an actual service. For sure it would be helpful for admins to find something in the logs. To my opinion a 406 isn't less interesting than a 404 or 403.

slip’s picture

@alexpott I get what you're saying. I personally think if we're logging 404s we should also log these. Something's going on with their request and they're not getting what they're asking for.

Additionally, if we remove this on406, an exception would get logged, which is part of the original problem and something I think we definitely don't want.

So I think we should keep this logging message or, if not, would you prefer to swallow the error with an empty function:
public function on406(GetResponseForExceptionEvent $event) {}

slip’s picture

StatusFileSize
new5.33 KB
new722 bytes
slip’s picture

Status: Needs work » Needs review

This is ready for more feedback.

indigoxela’s picture

Status: Needs review » Reviewed & tested by the community

@slip many thanks for your patience.

As we had some feedback by alexpott, I'd set this issue to rtbc now.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/lib/Drupal/Core/EventSubscriber/ExceptionLoggingSubscriber.php
@@ -53,6 +53,21 @@ public function on404(GetResponseForExceptionEvent $event) {
+  /**
+   * Log 406 errors.
+   *
+   * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
+   *   The event to process.
+   */
+  public function on406(GetResponseForExceptionEvent $event) {
+    $exception = $event->getException();
+    $request = $event->getRequest();
+    $this->logger->get('client error')->warning(
+      'There was an error in the client request: "@message" at @uri.',
+      ['@message' => $exception->getMessage(), '@uri' => $request->getRequestUri()]
+    );
+  }

406 doesn't mean client error. It has a specific HTTP meaning. Imo it's fine to remove this. Yes that means we'll get the standard message by onError but that's no change. What the user sees is fixed. We should open a follow-up to log 400s differently as the message $this->logger->get('php')->log($error['severity_level'], '%type: @message in %function (line %line of %file).', $error); doesn't work for 405s either (for example).

alexpott’s picture

+++ b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionUnknownFormatSubscriber.php
@@ -0,0 +1,49 @@
+  /**
+   * Handles a 406 error for any unknown format.
+   *
+   * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
+   *   The event to process.
+   */
+  public function on406(GetResponseForExceptionEvent $event) {

Hmmm thinking about this even more let's make this more generic and do

  /**
   * Handles all 4xx errors for all serialization failures.
   *
   * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
   *   The event to process.
   */
  public function on4xx(GetResponseForExceptionEvent $event) {

And then we can fix logging to be more generic for 400s as well.

slip’s picture

StatusFileSize
new4.69 KB
new3.33 KB

Updates made. This is now a generic handler.

I also added support for cacheable responses like ExceptionJsonSubscriber

Moved logging changes to https://www.drupal.org/project/drupal/issues/3039266

slip’s picture

Status: Needs work » Needs review
alexpott’s picture

  1. +++ b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionUnknownFormatSubscriber.php
    @@ -32,15 +34,24 @@
    +   * Handles all 4xx errors for all serialization failures.
    

    Not sure that we are specific to serialization failures - however there's no harm in including an example here - so we could mention 406s generated when handling unsupported formats.

  2. +++ b/core/core.services.yml
    @@ -1275,6 +1275,10 @@ services:
    +  exception.default_unknown_format:
    

    Needs a new name.

  3. +++ b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionUnknownFormatSubscriber.php
    @@ -0,0 +1,60 @@
    +class DefaultExceptionUnknownFormatSubscriber extends HttpExceptionSubscriberBase {
    

    Needs a new name.

  4. +++ b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionUnknownFormatSubscriber.php
    @@ -0,0 +1,60 @@
    +      $message = Html::escape($exception->getMessage());
    

    If we're outputting plain text I think we should strip HTML. We can use \Drupal\Component\Render\PlainTextOutput::renderFromHtml()

  5. However rather than adding new names I suggest we merge this into \Drupal\Core\EventSubscriber\FinalExceptionSubscriber() that way it is clearer it is generic and should be last.

    A single subscriber can register more than one listener so we could do something like:

    
      /**
       * {@inheritdoc}
       */
      public static function getSubscribedEvents() {
        // Run as the final (very late) KernelEvents::EXCEPTION subscriber.
        $events[KernelEvents::EXCEPTION][] = ['on4xx', -250];
        $events[KernelEvents::EXCEPTION][] = ['onException', -256];
        return $events;
      }
    
      public function on4xx(GetResponseForExceptionEvent $event) {
        if (substr($exception->getStatusCode(), 0, 1) !== '4') {
           // Do nothing.
           return;
        }
        // Do the new logic...
      }
    
slip’s picture

StatusFileSize
new3.87 KB
new5.44 KB

All valid comments. New patch attached.

krzysztof domański’s picture

Version: 8.6.10 » 8.8.x-dev

Developments changes should now be targeted the 8.8.x-dev branch.
Allowed changes during the Drupal 8 release cycle
Drupal 8 minor version schedule

alexpott’s picture

Version: 8.8.x-dev » 8.7.x-dev

@Krzysztof Domański - yeah but this is a bug fix so should target 8.7.x

alexpott’s picture

  1. +++ b/core/lib/Drupal/Core/EventSubscriber/FinalExceptionSubscriber.php
    @@ -138,11 +139,38 @@ public function onException(GetResponseForExceptionEvent $event) {
    +   * Handles all 4xx errors that aren't caught in other exception subscribers.
    +   * ¶
    

    There's a space after the * on the blank line.

  2. +++ b/core/lib/Drupal/Core/EventSubscriber/FinalExceptionSubscriber.php
    @@ -138,11 +139,38 @@ public function onException(GetResponseForExceptionEvent $event) {
    +   * For example, we catch 406s and 403s generated when handling unsupported formats.
    

    This comment needs to wrap at 80 chars.

  3. This fix is beginning to make me ponder if we're on the right path. Not every HttpException has a good message - see \Drupal\Core\Form\Exception\BrokenPostRequestException for example. I'm also questioning the premise of the issue itself. Drupal does not emit an exception when you do http://your-testing.tld/node/1?_format=something_odd - it emits a 406 with a message saying The website encountered an unexpected error. Please try again later.. What is actually wrong with that?
slip’s picture

StatusFileSize
new3.87 KB
new711 bytes

Styling fixed.

This original issue was definitely a bug. Site's are showing that error (which is basically Drupal's version of a fatal error) and exceptions are being logged. The logging part is perhaps most severe issue but we split that off. Still I'd like to finish this issue before dedicating time to that one.

I do take issue with the message displayed. The Drupal message "The website encountered an unexpected error. Please try again later." makes me think an unrecoverable fatal error happened. Additionally, If you have your site set up to show exceptions, one will be printed. This seems like overkill for something easily reproduced on every D8 site.

For messaging we could use the messaging in Http4xxController. At one point I had those simple messages being output.

Another point is that the json subscriber is actually doing something very similar to us and is outputting exception messages. for example (logged out):
https://www.site.tld/admin/?_format=json

If exception messages shouldn't be shown, that page shouldn't show them either.

If you disagree we can close this issue and tackle the logging issue. Otherwise please let me know what you think and I'll take it from there.

indigoxela’s picture

I do have a problem here with patch #42 applied.

My test path: /node/1?_format=htmlccc (rubbish)

I get an almost empty page with "Not acceptable format: htmlccc" as only content. Nothing else, no markup at all. Is this intended?

The http code is 406 as expected.

Drupal dblog detail page renders normally, the message is:

Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException: Not acceptable format: htmlccc in Drupal\Core\EventSubscriber\RenderArrayNonHtmlSubscriber->onRespond() (line 30 of /var/www/dev3/html/core/lib/Drupal/Core/EventSubscriber/RenderArrayNonHtmlSubscriber.php).

Drupal Version is 8.6.13.

slip’s picture

@indigoxela yes, that's intended. We scaled back this patch significantly and since the user is requesting a format that isn't html, it didn't seem to make sense to return HTML, although that is easy enough to do. Additionally, the logging fix was moved to a different issue. That's why the logging is still an issue even with this patch.

alexpott’s picture

@slip I think using the messages in \Drupal\system\Controller\Http4xxController is a very good idea. Those messages are indeed way better than The website encountered an unexpected error. Please try again later.

It would be neat if somehow the messages could be shared between Http4xxController and FinalExceptionSubscriber.

Another thought is that maybe if you are getting these on your site it might be helpful to get the additional backtrace info added by \Drupal\Core\EventSubscriber\FinalExceptionSubscriber::onException() so perhaps we should roll this content change into that method.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.9 was released on November 6 and is the final full bugfix release for the Drupal 8.7.x series. Drupal 8.7.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.8.0 on December 4, 2019. (Drupal 8.8.0-beta1 is available for testing.)

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

wim leers’s picture

Status: Needs review » Needs work
Issue tags: +API-First Initiative
+++ b/core/lib/Drupal/Core/EventSubscriber/FinalExceptionSubscriber.php
@@ -138,11 +139,39 @@ public function onException(GetResponseForExceptionEvent $event) {
+    $events[KernelEvents::EXCEPTION][] = ['on4xx', -250];

This needs to document the reasoning for this particular priority. Why -250 compared to -256?

Also: the comment above this line belongs with the -256 event.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

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

berdir’s picture

Version: 8.9.x-dev » 9.1.x-dev
Status: Needs work » Needs review
StatusFileSize
new4.35 KB
new2.35 KB

Reroll for D9.

Added a comment, but there's not too much to say. It has to run before the final exception handler, that's pretty much all there is to it I think.

Not sure what to do about #45.

I think it would be nice to finally resolve this, there are still bots out there looking for vulnerable sites for the hal_json security issue and it's filling up logs.

wells’s picture

StatusFileSize
new4.03 KB
new1.41 KB

Adding a reroll for D8.9.x.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

berdir’s picture

StatusFileSize
new4.35 KB

Another reroll, and I can already see this conflicting again because that assertEqual() line is going to change again :-/.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

wells’s picture

Status: Needs review » Reviewed & tested by the community

Upgrading an 8.9 site to 9.x today and the reroll in #52 still applies and resolves the issue. Marking RTBC as #47 has been addressed and its not clear if #45 if necessary. @alexpott or someone else can revert back to needs work if necessary.

berdir’s picture

Status: Reviewed & tested by the community » Needs work

It does apply, but it has coding style issues that need to be resolved sadly.

neslee canil pinto’s picture

Status: Needs work » Needs review
StatusFileSize
new4 KB
new663 bytes

Updating #52 to pass drupalCI.

neslee canil pinto’s picture

How can we handle this /var/www/html/core/tests/Drupal/KernelTests/Core/Routing/ExceptionHandlingTest.php:215:59 - Unknown word (jsonalert) here - $this->assertStringStartsWith('Not acceptable format: jsonalert(123);', $response->getContent());
Should we use it as we did it before inside em tag

berdir’s picture

StatusFileSize
new4 KB

Yeah, I'm unsure what to do about that. The reason that we end up with jsonalert is that this is all that's left over of json<script>alert(123);</script>, this is is specifically testing that we're escaping that format.

Except now, we just strip out the HTML and don't escape it, due to `$message = PlainTextOutput::renderFromHtml($exception->getMessage());`. Similar cases of that are in \Drupal\jsonapi\Normalizer\UnprocessableHttpEntityExceptionNormalizer::buildErrorObjects and \Drupal\rest\Plugin\rest\resource\EntityResourceValidationTrait::validate().

Should we just add that word to the exception list? Or somehow handle it differently? We could change the test to add a space in front of

We should then also update the comment above that change, because that talks about escaped HTML that is no longer there.

Just a basic reroll for now.

wells’s picture

Just cleaning up the default displayed patches to the working D8 and D9 versions. #52 and #56 no longer apply to 9.1.10 -- #58 applies and continues to work.

berdir’s picture

StatusFileSize
new4 KB

Another reroll for 9.3, question in #58 remains.

alexpott’s picture

+++ b/core/tests/Drupal/KernelTests/Core/Routing/ExceptionHandlingTest.php
@@ -199,7 +212,7 @@ public function testExceptionEscaping() {
-    $this->assertStringStartsWith('The website encountered an unexpected error. Please try again later.<br><br><em class="placeholder">Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException</em>: Not acceptable format: json&lt;script&gt;alert(123);&lt;/script&gt; in <em class="placeholder">', $response->getContent());
+    $this->assertStringStartsWith('Not acceptable format: jsonalert(123);', $response->getContent());

Add a comment

// cspell:ignore jsonalert

before the assertion and then this spelling error will only be ignored here.

paulocs’s picture

StatusFileSize
new652 bytes
new4.03 KB

Addressing comment #61.

weseze’s picture

The patch fixes the fatal error issue.

I am however wondering why we are not simply ignoring unknown query parameters/values?
In several places in core where the "_format" parameter is handled there is comment indicating that the "html" value should be the default.
With that information I would assume it would be more logical to fallback to HTML when an unknown value is encountered?
Or to just completely ignore unknown query parameter/values, that would then also fallback to html.

What is the advantage of showing a custom error page instead?

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

mfb’s picture

This patch has logic to potentially make it a cacheable response, but I'm wondering what a site would have to do to make it actually cacheable, as it wasn't in my testing, i.e. adding _format=something is a reliable way to bypass the page cache and proxy cache.

berdir’s picture

I think the logic for that is just copied. For the 406 errors to be cacheable, \Drupal\Core\Routing\RequestFormatRouteFilter::filter() would need to throw a cacheable http exception, which feels like a different issue.

mfb’s picture

ok, and for posterity, looks like there are a couple other places where a cacheable http exception would need to be thrown - \Drupal\Core\EventSubscriber\RenderArrayNonHtmlSubscriber::onRespond() and \Drupal\Core\Routing\Enhancer\ParamConversionEnhancer::onException()

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

berdir’s picture

StatusFileSize
new4.04 KB

Reroll for D10.

Re #63: That too is a different issue. This isn't about whether or not core should throw such errors, it's how to handle them if it happens, and they are a valid HTTP response. As for _format throwing an exception on invalid values, that kind of makes sense as the client would expect a certain format and not returning in that would likely cause the client to fail.

catch’s picture

  1. +++ b/core/lib/Drupal/Core/EventSubscriber/FinalExceptionSubscriber.php
    @@ -138,10 +141,39 @@ public function onException(ExceptionEvent $event) {
    +  public function on4xx(ExceptionEvent $event) {
    +    $exception = $event->getThrowable();
    +    if ($exception && $exception instanceof HttpExceptionInterface && substr($exception->getStatusCode(), 0, 1) === '4') {
    +      $message = PlainTextOutput::renderFromHtml($exception->getMessage());
    

    Can this be str_starts_with() now we require PHP 8.1?

  2. +++ b/core/tests/Drupal/KernelTests/Core/Routing/ExceptionHandlingTest.php
    @@ -42,6 +42,19 @@ public function test405() {
     
    +  /**
    +   * Tests on a route with a non-supported _format parameter.
    +   */
    

    Should this say "Tests a route"?

Overall looks good to me though.

wells’s picture

StatusFileSize
new4.03 KB
new1.41 KB

Attaching #70 patch with updates from #71 review.

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs issue summary update

Can the issue summary be updated please? Mentions Drupal 8 are the steps still the same for D10?
What was the proposed solution?
Any remaining tasks?
etc.

wells’s picture

Issue summary: View changes
Status: Needs work » Needs review

I have updated the issue description with the standard template. Hope that helps!

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: -Needs issue summary update

So if the node exists I get

Not acceptable format: hal_json

If the node doesn't exist I get

The "node" parameter was not converted for the path "/node/{node}" (route name: "entity.node.canonical")

Is that expected?

wells’s picture

Status: Needs work » Needs review

Yes. See #45 from @alexpott --

@slip I think using the messages in \Drupal\system\Controller\Http4xxController is a very good idea. Those messages are indeed way better than The website encountered an unexpected error. Please try again later.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Ah thanks for the follow up!

Then I don't see any issue on this.

  • catch committed 92fcdbfd on 10.1.x
    Issue #3035589 by slip, Berdir, wells, Neslee Canil Pinto, paulocs,...
catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed 92fcdbf and pushed to 10.1.x. Thanks!

Debating whether to backport this due to the new event subscriber, it should not break anything and seems unlikely someone would have registered a competing exception subscriber, but since this is just improving an error message, going to leave it in 10.1.x - however if you've got strong objections re-open and we can probably backport with a change record.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.