Problem/Motivation

#2841027: JSON API format should only be used on JSON API routes, but can currently also be used for REST resources added RemoveJsonapiFormatCompilerPass to hide the api_json format from REST module. However, it only removes it from the serializer.formats parameter, and not from the serializer.format_providers parameter. As a result, 'api_json' still leaks to places that use the latter parameter, such as RestExport::getFormatOptions(), which causes it to show up as an option when configuring a RestExport display.

Proposed resolution

Make the compiler pass remove it from the serializer.format_providers parameter as well.

Comments

effulgentsia created an issue. See original summary.

effulgentsia’s picture

Come to think of it, do we need this compiler pass at all? The PHPDoc for it says:

But the JSON:API module also should not have to define an alternative 'serializer' service.

Except it now does, ever since #2923779-15: Normalizers violate NormalizerInterface. So why do we still add a api_json encoder to the 'serializer' service?

wim leers’s picture

As a result, 'api_json' still leaks to places that use the latter parameter, such as RestExport::getFormatOptions(), which causes it to show up as an option when configuring a RestExport display.

Something must have changed then, because that definitely used to be fixed :( Or maybe we missed something! But making sure it doesn't show up in Views was of course a key goal of that issue.

I reproduced the problem.

That's also explicitly documented in #2841027: JSON API format should only be used on JSON API routes, but can currently also be used for REST resources, which introduced that class.

Come to think of it, do we need this compiler pass at all? The PHPDoc for it says:

But the JSON:API module also should not have to define an alternative 'serializer' service.

Except it now does, ever since #2923779-15: Normalizers violate NormalizerInterface.

That is a great point! #2923779: Normalizers violate NormalizerInterface indeed introduced our own serializer service. That means that most of the measures introduced in #2841027 are now obsolete.

So why do we still add a api_json encoder to the 'serializer' service?

Because \Drupal\jsonapi\EventSubscriber\ResourceResponseSubscriber::renderResponseBody() still does

      $response->setContent($serializer->encode($jsonapi_doc_object, $format));

However, we can factor that away, by just using the core serialization module's json encoder.

Then we run into one last blocker: JSON:API's subclass of serialization's JSON encoder does one extra thing. We can just move that into ResourceResponseSubscriber.

Let's see if this passes all tests.

Status: Needs review » Needs work

The last submitted patch, 3: 3029630-3.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

wim leers’s picture

Status: Needs work » Needs review
StatusFileSize
new4.8 KB
new10.31 KB

One CS violation is masking a lot of failures. I can fix those failures, but the changes to fix those failures do show why we had that encoder still around.

I'll be the first to admit that this is where JSON:API module's internals are ugly and confusing. But don't forget we had to do this as well as #2923779: Normalizers violate NormalizerInterface precisely because of architectural flaws in Symfony's Serialization component… 😔

Status: Needs review » Needs work

The last submitted patch, 5: 3029630-5.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

wim leers’s picture

Status: Needs work » Needs review
StatusFileSize
new1.38 KB
new10.57 KB

Sorry for the noise — I'm migrating to a new computer while working on this.

effulgentsia’s picture

StatusFileSize
new5.96 KB
new4.1 KB

How about this approach instead?

Different approach than #5 / #7, so the interdiff is relative to #3.

Status: Needs review » Needs work

The last submitted patch, 8: 3029630-8.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

effulgentsia’s picture

Status: Needs work » Needs review
StatusFileSize
new5.96 KB
new499 bytes
wim leers’s picture

Status: Needs review » Reviewed & tested by the community

Fewer changes. I like it more than my proposal :)

RTBC, but I'd like at least one of my two fellow maintainers to also +1 before committing.

wim leers’s picture

Title: RemoveJsonapiFormatCompilerPass removes api_json from serializer.formats but not from serializer.format_providers » RemoveJsonapiFormatCompilerPass removes api_json from serializer.formats but not from serializer.format_providers, hence allowing it to be selected in REST export View displays

The title doesn't make it clear why this is considered a bug.

gabesullice’s picture

StatusFileSize
new665 bytes
new5.85 KB

Just had one nit. If tests pass, I think this can go in.


+++ b/jsonapi.services.yml
@@ -97,7 +97,7 @@ services:
-      - { name: encoder, priority: 21, format: 'api_json' }
+      - { name: jsonapi_encoder_do_not_use_removal_imminent, priority: 21, format: 'api_json' }

I don't think we need the priority any more then.

effulgentsia’s picture

StatusFileSize
new1.71 KB
new7.56 KB

Here's a test for it. The -test-only patch is also the interdiff.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 14: 3029630-14.patch, failed testing. View results

effulgentsia’s picture

StatusFileSize
new7.54 KB
new490 bytes

https://dispatcher.drupalci.org/job/drupal8_contrib_patches/47662/ shows the test failure in the test-only patch.

The PHPCS error was:

FILE: ...es/jsonapi/tests/src/Functional/RestExportJsonApiUnsupported.php
----------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
----------------------------------------------------------------------
 26 | ERROR | If the line declaring an array spans longer than 80
    |       | characters, each element should be broken into its own
    |       | line
----------------------------------------------------------------------

Since module dependencies are automatically installed, here's one way to fix it :)

effulgentsia’s picture

Status: Needs work » Reviewed & tested by the community

gabesullice’s picture

Status: Reviewed & tested by the community » Fixed

WFM! Thanks for adding a tests :)

wim leers’s picture

👌

Status: Fixed » Closed (fixed)

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