Problem/Motivation
While working on #2737719: EntityResource: Provide comprehensive test coverage: for every entity type, every format, every method, I also worked on ensuring that every format is also tested with every authentication provider, including cookie
. But when using cookie
, the user.login.http
route would not ever accept the hal_json
format, despite it automatically supporting every format. See #2737719-85: EntityResource: Provide comprehensive test coverage: for every entity type, every format, every method.
Turns out the reason is a tiny error in \Drupal\serialization\EventSubscriber\UserRouteAlterSubscriber::onRoutingAlterAddFormats()
's logic:
$formats = array_unique($formats + $this->serializerFormats);
should be
$formats = array_unique(array_merge($formats, $this->serializerFormats));
Because array_unique(['json'] + ['hal_json', 'json', 'xml']) === ['json', 'xml']
, and array_unique(array_merge(['json'], ['hal_json', 'json', 'xml'])) === ['hal_json', 'json', 'xml']
!
Note that it could very well be another format that is being ignored, it just depends on which format is listed first in $this->serializerFormats
(which is the serializer.formats
container parameter).
Proposed resolution
Fix the logic.
Remaining tasks
TBD
User interface changes
None.
API changes
None.
Data model changes
None.
Comment | File | Size | Author |
---|---|---|---|
#9 | interdiff.txt | 1.58 KB | lhangea |
#9 | 2820888-add_hal_json_login_support-9.patch | 2.41 KB | lhangea |
#2 | 2820888-2.patch | 975 bytes | Wim Leers |
Comments
Comment #2
Wim LeersThis is the fix. Still needs test coverage.
Comment #3
almaudoh CreditAttribution: almaudoh commented:o Interesting bug
array_unique(['json'] + ['hal_json', 'json', 'xml']) === ['json', 'xml']
, I had to check again to confirm. I wonder how many places in core that bug exists?Comment #4
Wim LeersWe're fairly good about only using
array + array
when it's an associative array. But yes, it's definitely happened before :)Comment #5
dawehnerThis indeed is quite a clusterfuck in php. There is this excellent phpstorm plugin: https://plugins.jetbrains.com/plugin/7622?pr=phpStorm which shows you those kind of problems.
Comment #6
Wim LeersComment #7
damiankloip CreditAttribution: damiankloip commentedNot sure why \Drupal\serialization\EventSubscriber\UserRouteAlterSubscriber was added to serialization module to be honest. Looks like #2403307: RPC endpoints for user authentication: log in, check login status, log out added it under the guise of the REST module...
Comment #8
lhangea CreditAttribution: lhangea commentedComment #9
lhangea CreditAttribution: lhangea commentedWe need to close this one in order to be able to close #2800873: Add XML GET REST test coverage, work around XML encoder quirks
Comment #10
Wim Leers@damiankloip: because it's the Serialization module which handles the "registered formats in the system". So once that module is installed, more formats become available for the User module's RPC routes too. Oh, but I see what you mean now, it still actually belongs in the
user
module… You're right! However, that really belongs in a separate issue. Want to file one?#9: thanks! That looks perfect :)
Comment #11
dawehnerI just ran the test locally to prove it actually fails, and well, indeed it doesn.
Comment #12
damiankloip CreditAttribution: damiankloip commentedThanks Wim. I'll file an issue :)
I would say this needs a unit test for the event subscriber to be honest. Not sure how it got I without one ;)
Comment #13
alexpottCommitted and pushed bf124f3 to 8.3.x and 29658ab to 8.2.x. Thanks!
Comment #16
damiankloip CreditAttribution: damiankloip commentedThat event subscriber should still have a unit test IMO. If it had that to start with this bug wouldn't have snuck in.
Comment #17
Wim Leers@damiankloip:
UserLoginHttpTest::testLogin()
is a functional test. I think that's sufficient here. It's much more valuable to test the integration rather than the unit. The logic isn't complex. There aren't many edge cases. What matters most, is that all intended formats are supported. That's what the functional test ensures.Comment #18
damiankloip CreditAttribution: damiankloip commentedNot saying we should not have a functional test, but those kind of bugs are exactly why you have unit test coverage, no matter how simple the class you're testing is.
Comment #19
Wim LeersYou're right. But unit tests come with a cost too: we need to write, maintain and run them. All I'm saying is that I think in this case the value doesn't outweigh the cost. I think that in this case, the functional test coverage is sufficient.
Comment #20
damiankloip CreditAttribution: damiankloip commentedfair enough :)
Comment #22
Wim LeersThis forgot to also update
\Drupal\Tests\rest\Functional\CookieResourceTestTrait::initAuthentication()
:Opened #2849474: \Drupal\Tests\rest\Functional\CookieResourceTestTrait::initAuthentication() should use the current test format, and should not send an Accept header to fix that.