Problem/Motivation
When viewing a Views RSS feed display uncached, the header is correctly set as application/rss+xml. However, when cached, the header is incorrectly set as text/html.
Steps to reproduce
0. Uninstall the following modules that could cache the HTTP response headers: Internal Page Cache (page_cache), Internal Dynamic Page Cache (dynamic_page_cache).
1. Create a views RSS feed display.
2. Enable caching for the view
3. View the display output in a separate tab.
4. Refresh (to load the cached version).
5. Observe that it renders as "text/html". Expected: "application/rss+xml"
Proposed resolution
MR to use
11.x: MR 4756
Set the content type header for the response in the Feed prior to preprocessing.
Remaining tasks
Review
User interface changes
NA
API changes
NA
Data model changes
NA
Release notes snippet
NA
| Comment | File | Size | Author |
|---|
Issue fork drupal-3272985
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
xjmPossibly this fix should be used for all display plugins, or added in a different layer of the API? See #1312962: Cache HTTP headers sent by view result/output.
Comment #4
shree.yesare commentedAfter applying the patch there is no Content-Type header set in the response headers.
Comment #5
recrit commentedI ran into this same issue with a cached RSS feed. The patch proposed in #2 does not work. The issue with the patch is that it is assuming
$build['#content_type']exists, which is does not. This results in always nullifying the Content-Type header.Comment #6
recrit commentedCause for this bug:
The template_preprocess_views_view_rss() is the only place where the response header "Content-Type" is set to 'application/rss+xml; charset=utf-8'. This works when the theme "views_view_rss" is not cached. Once it is render cached, then the response header "Content-Type" is never set.
Comment #8
recrit commentedThe MR posted in #7 provides a way for the style plugins (RSS, OPML) to alter the response object built by the display plugin (Feed). This sets the correct response Content-Type header even when the style's theme is render cached.
Cleanup / Future considerations:
The template_preprocess_views_view_rss() and template_preprocess_views_view_opml() no longer need to set the response headers. This was bad practice to begin which has led to this issue. A theme that can be cached should not set the HTTP response headers. It will eventually cause the issue found here.
Comment #9
recrit commentedPassed tests and validation, so attached a static patch for MR 2063 at commit f49f4274. This can be used for builds that want to use the patch as of now while not receiving future updates to the MR that could break their builds.
Comment #11
recrit commentedComment #15
binoli lalani commentedHello,
I applied #9 patch but it display the RSS feeds in HTML format not in XML format with proper structure so
I created MR !2619 for it.
Also, fixed below coding standard warnings.
Please review MR.
Thanks
Comment #16
recrit commented@Binoli Lalani please do not turn this issue into a code cleanup task. The patch should focus on the bug in this issue only.
Comment #17
recrit commented@Binoli Lalani - Your new "branch 3272985-change-views-rss-feeds-format" steals the work done in my branch "3272985-views-rss-feed-response-content-type" and claims it as its own. If you want to contribute to make a better patch, it's best practice to branch off of the original branch "3272985-views-rss-feed-response-content-type" and then make your changes. This keeps the commit authors for credit and makes it easier to see what you are changing.
Comment #18
binoli lalani commentedHello @recrit,
I've not stolen your work. I applied your patch but it seems that feeds are showing in HTML format, I wanted to show in XML format with proper structure same as an attached screenshot so I just extended your patch and change only below line in my MR.
$response->headers->set('Content-Type', 'application/rss+xml; charset=utf-8');to
$response->headers->set('Content-Type', 'application/xml; charset=utf-8');.Thank you for providing the patch. I will take care of your point to branch off of the original branch.
Thanks!
Comment #19
recrit commented@Binoli Lalani The problem is that you did not extend my patch. You applied the patch to a new branch and then committed it is as your own.
Your branch: 3272985-change-views-rss-feeds-format - All commits are authored by you.
To contribute to the patch, the following makes it easier to see exactly what you are changing and it keeps the authors of the original commits.
Comment #20
recrit commentedComment #22
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or 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 #25
recrit commentedcreated a new issue branch "327985-11.x" for 11.x with patch #9 rolled on 11.x. Let's use this for development and then only post static patches based on the MR 4756.
Comment #26
recrit commentedAttached is a static patch of Drupal 11.x MR 4756 at commit c952438a.
Work Pending: Add automated tests for RSS header content-type.
Comment #32
recrit commentedAttached is the static patch for 10.1.x MR 4789.
Comment #33
recrit commentedPending: Automated tests
Comment #34
recrit commentedAdded Step 0 to uninstall page cache modules that could be caching the HTTP response headers.
Added expected HTTP header.
Added new PHP interface.
Comment #35
recrit commentedAttached is a patch for 11.x that adds only the new test. This patch should fail which proves that a fix to core is needed.
Comment #36
recrit commentedComment #37
recrit commentedFYI - "PHP 8.1 & MySQL 5.7 Not currently mergeable." is for some reason using the closed merge request 4788 without anyway to change it to the correct MR 4789. For that reason, I was unable to run the 10.1 test with PHP 8.1 & MySQL 5.7
Comment #38
recrit commentedSummary up until now:
3272985-D10.1.x-MR4789-f56a2633c6--20230928.diff"
Comment #39
recrit commentedComment #43
quietone commentedIn Slack, #gitlab, smustgrave asked for all MRs except 4756 and 4789 were closed. I have closed MR !2619, MR !2063 and MR !2042,
Cheers
Comment #44
smustgrave commentedThanks @quietone!
Tested on a fresh installed of 11.x with standard profile
I used the rss view that is installed
Confirmed the issue following the steps in the IS and that MR 4756 solved the issue.
For the new trait believe we will need a change record
Good example would be https://www.drupal.org/node/3392235
Comment #45
recrit commented@smustgrave - Draft CR created at https://www.drupal.org/node/3402518
Comment #46
smustgrave commentedCR reads fine.
Comment #47
catchI'm pretty sure this can be implemented using
#attached, see comment on the MR. This would mean that views.theme.inc wouldn't need to do anything then either, and would save the API addition.Comment #48
recrit commented@catch this will not work in any preprocess function once it has been rendered cached. It will work the first time, but any request to the page after that will break. See comment #6 and #8 for more details.
Comment #49
recrit commentedComment #50
catch#6 and #8 don't mention using #attached, they just talk about the preprocess function, which is also not using #attached (hence why it doesn't work properly).
#attached does work with the cache system and I think it could be implemented in the style plugin directly rather than preprocess.
Comment #51
recrit commented@catch thanks .. When I first read your comment, I thought that you meant the preprocess function. I'll try using the #attached approach in
Drupal\views\Plugin\views\style\Opml::render()andDrupal\views\Plugin\views\style\Rss::render()to see if the test passes.Comment #52
recrit commented@catch Adding the
"['#attached']['http_header']"to\Drupal\views\Plugin\views\style\Opml::render()and\Drupal\views\Plugin\views\style\Rss::render()does not work since the Feed display plugin usesreturns_response = TRUEwhich get its own custom response processing. The views HTTPStatusCode area plugin get's added to page displays, so the displays build area gets processed in a way that the "#attached" is propagated to the response inDrupal\Core\Render\HtmlResponseAttachmentsProcessor.Feed Display Response processing:
The Feed display plugin is the only core Views display plugin that uses the
returns_response = TRUE. When the "returns_response" plugin property is set, the\Drupal\views\Routing\ViewPageController::handle()uses the response as built by the display plugin with itsbuildResponse. TheFeed::buildResponse()renders the$buildarray with aRendererInterface::renderRoot(), adds only the cacheable metadata withCacheableMetadata::createFromRenderArray(), and then returns the\Drupal\Core\Cache\CacheableResponseinstead of a build array. With that processing, the attachments do not get added to the response as expected.The
"['#attached']['http_header']"approach could theoretically work if we added the code to process"['#attached']['http_header']"inFeed::buildResponse()similar to howDrupal\Core\Render\HtmlResponseAttachmentsProcessorprocesses it.To test this approach, I created the "3272985-attached-approach-10.1.x-DO_NOT_USE-51.patch" for 10.1.x in order to show that it fails the new automated tests added in the MR. The same issue exists for 11.x too.
Test Result: Failed for
Drupal\Tests\views\Functional\Plugin\DisplayFeedTest::testFeedCacheabilityas expected.For reference
\Drupal\views\Routing\ViewPageController::handle():Comment #53
recrit commentedComment #54
catchThanks for trying it out. This approach sounds encouraging.
Comment #55
smustgrave commentedSeems the feedback has been addressed?
Comment #56
catch@smustgrave - no it hasn't, there haven't been any commits on the MR, only discussion.
Comment #57
recrit commented@catch I do not have any commits unless you are looking for the approach in #54 to be used instead of the current implementation.
Comment #58
catch@recrit yes I think we should try the approach in #54 - i.e. make things work with the existing API rather than adding a new one.
Comment #59
recrit commented@catch I updated the MRs to use
#attached['http_header']instead of a custom trait.10.1.x MR 4789 (this MR)
11.x MR 4756
Comment #60
catchThat looks much better to me, and great to get rid of that logic from preprocess.
Last question I have is does this still work for the live preview situation?
Comment #61
recrit commented@catch Yes, it worked in my testing. Now, the HTTP headers are only added when the route is visited via the route callback
\Drupal\views\Routing\ViewPageController::handle()instead of a theme function as it was before.Comment #62
smustgrave commentedRemoved the Data model change from the IS as that no longer seems to be true.
Current CR is outdated and can be deleted.
Not sure if we need one for announcing headers being added but going to assume no.
Appears feedback has been addressed though and it's clear in the IS which MR to be committed.
Comment #63
catchAsked for an addition to the comment in the MR.
Agreed this doesn't need a change record, just a bugfix now.
Comment #64
recrit commentedUpdated both MRs with a comment to reference
\Drupal\Core\Render\HtmlResponseAttachmentsProcessor::setHeaders()Comment #65
catchThanks! Moving back to RTBC.
Comment #66
catchNearly went to commit this then spotted a couple more small issues, feel free to re-RTBC once these are resolved.
Comment #67
recrit commented@catch resolved
Comment #70
catchCommitted/pushed to 11.x and cherry-picked to 10.2.x, thanks!
Comment #71
recrit commentedthanks! Attached is the final patch for 10.1.x for anyone still on that version.
Comment #72
grasmash commentedHooray!