Problem/Motivation
PHPUnit test failed due to deprecation notice
Unsilenced deprecation notices (9)
6x: stripos(): Passing null to parameter #1 ($haystack) of type string is deprecated
6x in GatsbyEntityLoggerTest::testEntityInsert from Drupal\Tests\gatsby\Kernel
3x: strpos(): Passing null to parameter #1 ($haystack) of type string is deprecated
3x in GatsbyEntityLoggerTest::testEntityInsert from Drupal\Tests\gatsby\Kernel
in core files.
- web\core\lib\Drupal\Core\EventSubscriber\RssResponseRelativeUrlFilter.php
- web\core\modules\jsonapi\src\EventSubscriber\ResourceResponseValidator.php
- web\core\lib\Drupal\Core\EventSubscriber\ActiveLinkResponseFilter.php
Good summary of why this happends is is comment #54.
Steps to reproduce
PHPUnit test of gatsby module's logger file. gatsby/tests/src/Kernel/GatsbyEntityLoggerTest.php
Error raised here
Proposed resolution
Check headers value first.
Remaining tasks
Create patch as per proposed resolution.
Comments
Comment #2
jaykumar95Comment #3
jaykumar95attaching patch for review.
Comment #5
jaykumar95Comment #6
jaykumar95attached patch #5 while follow up on #3 failed in test.
Comment #12
Kaushik1216 commentedCheck merge request
In code I have check null values before using in stripos that resolve php 8.1 warning
Comment #15
Kaushik1216 commentedComment #16
Kaushik1216 commentedComment #17
Kaushik1216 commentedComment #18
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #19
akram khanadded updated patch and try to fix CCF of MR #14
Comment #20
Kaushik1216 commentedComment #21
smustgrave commentedThink it would worth figuring out what is calling with the empty parameter vs putting the check in. This could be bad code somewhere that should be fixed.
Either way will need a test case.
Comment #22
Kaushik1216 commented@smustgrave null is coming from public function get when headers[0] == NULL which is in vendor folder vendor/symfony/http-foundation/HeaderBag.php online 118 how we can change it ad it's not in code base ?
Comment #23
bbralaI think smustgrave is right. We need to know why there is a response that is built without any headers. That is pretty weird.
We really need to be able to reproduce this in a way, preferably in a test.
Comment #24
berdirWe're seeing this on image generation when adding a webp convert effect to an image style. Agree that there might be an underlying bug about not sending a proper content type in that case, but this seems like something we should just be more defensive about without requiring tests.
I think a simpler fix would be to use $response->headers->get('Content-Type') ?? '' if we can't rely on the default value behaviour in symfony.
Comment #25
pivica commented> We're seeing this on image generation when adding a webp convert effect to an image style
In our case this was a bug in update function, so having this notice helped identifying that there is a problem in the first place.
Comment #26
p4trizio commentedFor some reasons, this patch is already in Drupal 10.1.x
I upgraded a website using this patch from D9 to D10.1 and the patch was obviously failing.
Comment #27
smustgrave commentedIf issue is no longer a problem in D10.1 we can close out!
Comment #28
rahaf albawab commentedStill, the issue exists in D10.1.5
Comment #29
rahaf albawab commentedI rerolled patch #19 to work with d10.1.5
Comment #30
sweetchuckI ran into a very similar issue.
\Drupal\jsonapi\Eventsubscriber\ResourceResponseValidator line 104
$response->headers->all() =
It would be good to know what causes this problem. "content-type" key should not be there if the value is not a valid mimetype.
Comment #31
sweetchuckPatch #5 took care of three occurrences
Patch #29 for an unknown reason does nothing with ResourceResponseValidator.
Comment #32
sweetchuckComment #34
jrbIn our case, we were seeing the 3 deprecation messages when an anonymous user tried to access a Data Export display of a View that required authentication.
The patch in #32 fixes the issue.
Comment #36
penyaskitoThis also break contrib tests: e.g. for jsonapi_extras https://www.drupal.org/project/jsonapi_extras/issues/3621534
Comment #39
f0ns commentedComment #40
ironnuts commentedI have reviewed MR!17048 and read the IS and some of the comments.
Re: #24 it looks like the recommendations have been implemented but tests coverage has also been added though #24 suggests it is unnecessary. Also I ran the test-only test https://git.drupalcode.org/issue/drupal-3344629/-/jobs/12066440 and it does not fail but results instead in a deprecation warning. The warning states that passing in NULL to parameter #1 is now deprecated.
I am changing to Needs work as it might be best to remove the test code especially as one of the test files is edited to fix an unrelated test issue? Not sure whether this issue is outdated since the deprecation landed?
Comment #41
ironnuts commentedIf there is a way of editing the test coverage so it fails on test-only test runs, that could be another possible resolution.
Comment #42
ironnuts commentedComment #43
f0ns commentedThanks, that is a fair catch.
Comment #44
ironnuts commented#43 Thank you f0ns. I have re-read the IS and I see that the issue itself seems to be the deprecation warning triggered by certain tests. In which case if the test-only test is producing that error that could be what is desired as output from test-only?
I think nothing lost by removing the test coverage, though in line with #24.
Comment #45
f0ns commentedTest-only run now fails as requested (job 12070034), since
ActiveLinkResponseFilteris incore/liband gets reverted, with the deprecation promoted to an exception.Comment #46
f0ns commentedComment #47
f0ns commented#44 The test-only run does now fail, see #45 and job 12070034.
On removing the coverage: #24 was written when this was a deprecation notice. Under
declare(strict_types=1)the same NULL is a fatalTypeError, which is what breaks JSON:API Extras (#3621534: phpunit failing in HEAD ). That is why I would keep the test.Happy to drop the
ResourceResponseValidatorTestcase if preferred. Its subject sits under*/tests/*, so test-only never reverts it and it cannot fail there. TheActiveLinkResponseFilterone does.Comment #48
ironnuts commentedThe test-only is now producing a test error as desired. RTBTC.
Comment #49
ironnuts commentedComment #50
ironnuts commentedComment #51
bbralaLooking good, +1 for RTBC
Comment #52
f0ns commentedThanks for looking into it and the review, would love to see this move into core.
Comment #53
larowlanIt would be good to get the bottom of what is setting the header to NULL in these cases?
There doesn't seem to be many places in core that are setting it dynamically
NULL is a valid return here - so one of those two sound like a culprit
jsonapi_extras.... and Gatsby (uses jsonapi) might point to jsonapi - in tests only?
Comment #54
f0ns commentedRequest::getMimeType()returns NULL whenever the format isn't in the staticRequest::$formatsarray, which Drupal only populates inNegotiationMiddleware::handle().So the three writers (jsonapi
ResourceResponseSubscriber:119, restResourceResponseSubscriber:166, serializationDefaultExceptionSubscriber:81) set Content-Type to NULL whenever that middleware didn't run in the process (jsonapi hardcodesapi_json) or the route's_formatrequirement is empty.HeaderBag::set()then stores[null], sohas()is TRUE,Response::prepare()can't repair it (both branches are gated on!has('Content-Type')), andget('Content-Type', '')returns NULL becauseget()explicitly returns NULL before considering the default. Readers have to be NULL-safe either way.Symfony hit the same thing and applied this exact
?? ''pattern insideResponse::prepare()itself. Tightening the writers changes behaviour (no header vs. empty header), so I'd leave that to a follow-up.Comment #55
f0ns commentedComment #56
ironnuts commentedRe: #54 That is a very detailed response to #53. Over to @larowlan
Comment #57
larowlanLeft a comment on the MR
Comment #58
bbralaUpdate is to link to the awesome cmoment in #54.
The open question on the MR feels awnsered.
Comment #63
larowlanCommitted and pushed 9493974a25a to main and c82f5367255 to 12.0.x and 12981cb0915 to 11.5.x and 89f3e765bb2 to 11.x. Thanks!