Make WordPress Core

Opened 9 years ago

Last modified 5 years ago

#36334 reopened defect (bug)

Custom RSS feed has wrong MIME type and forces download in browser

Reported by: missilesilo's profile Missilesilo Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version: 2.1
Component: Feeds Keywords: needs-docs needs-codex has-patch
Focuses: Cc:

Description

When adding a custom RSS feed using add_feed(), the resulting feed is transferred to the document with the wrong MIME type and forces a download. Built in feeds behave properly.

<?php

add_action('init', 'customRSS');
function customRSS(){
	add_feed('feedname', 'customRSSFunc');
}

function customRSSFunc(){
	echo 'say anything';
	// get_template_part('rss', 'feedname');
}
?>

Navigating to http://wordpress.dev/feed/feedname/ results in forced download and console message:

Resource interpreted as Document but transferred with MIME type application/octet-stream: "http://wordpress.dev/feed/feedname/".

This occurs on a fresh install of WordPress 4.4.2 with no added plugins. The above code is the only contents of functions.php in a child theme of Twenty Sixteen. Browser/OS is Google Chrome 48.0.2564.116 (64-bit) on Mac OSX 10.11.3. Test website is running on a local Vagrant/VirtualBox server.

Attachments (2)

36334.patch (484 bytes) - added by stevenkword 8 years ago.
Change default customer feed mime type to text/html
36334.2.patch (654 bytes) - added by stevenkword 8 years ago.
A little modification since http-rss is gone.

Download all attachments as: .zip

Change History (18)

#1 @mpol
9 years ago

Just to add some info...
Setting a custom HTTP header in customRSSFunc() above will not set a header there. Even setting a custom header will fail:
header('X-test_rss: test',true);

Overwriting the Content_type header won't function thaen as well:
header('Content-Type: ' . feed_content_type('rss-http') . '; charset=' . get_option('blog_charset'), true);
header('Content-Type: application/rss+xml; charset=UTF-8', true);

Last edited 9 years ago by mpol (previous) (diff)

#2 @swissspidy
9 years ago

  • Version changed from 4.4.2 to 2.1

You need to filter feed_content_type() to set the content type for your custom feed. The content type defaults to application/octet-stream, therefore this bug is expected behaviour.

Although /wp-includes/feed-rss2.php and the like use header() as well, that declaration seems to be useless.

I'd say feed_content_type() should be mentioned in the add_feed() docblock.

#3 @Missilesilo
9 years ago

  • Resolution set to invalid
  • Status changed from new to closed

I agree with mentioning the usage of the feed_content_type() function and/or filter. I was finally able to get my custom feed working. It seems there were some plugins and caching issues in the first environment that I was attempting this in, and then in the clean WP install, I was failing to set the header correctly because I assumed it would default to some form of plain text. I'm not sure if the application/octet-stream default is documented anywhere, but that would be quite helpful as well.

#4 @netweb
9 years ago

  • Milestone Awaiting Review deleted

#5 @mpol
9 years ago

@Missilesilo: Can you explain how you got it working?

Sorry, but documentation is really lacking here, and looking at the source leaves me clueless. The default feeds are just called with an include() it seems, not with a proper function.
How am I supposed to filter feed_content_type() to get a correct header?

#6 @mpol
9 years ago

  • Resolution invalid deleted
  • Status changed from closed to reopened

Posting again and re-opening :).
I would think filtering feed_content_type is for adding a custom content_type. If using $type='rss' there is no need to filter this (correct?).
I really think there is a bug here, because I don't think there is a way to set the correct header for a custom rss-feed.

Using this code for example, will only add the header test-0 and test-1. But inside those first two functions it is not possible to set the Content-type header for just the feed that was added, it will just add it to any request.
The third function will only run on that feed, but it is not possible to set a header anymore.
Looking at all the code there is for RSS feeds, I suspect that once, long ago, it was possible to set a header inside this third function, so I would say this is a bug.

<?php
function gwolle_gb_rss_init(){
        add_feed('gwolle_gb', 'gwolle_gb_rss');
        // will add it to any request
        header( 'X-Test-0: Test=0' );
}
add_action('init', 'gwolle_gb_rss_init');

function gwolle_gb_rss_header() {
        header( 'X-Test-1: Test=1' );
        // will add it to any request
        //header('Content-Type: ' . feed_content_type('rss') . '; charset=' . get_option('blog_charset'), true);
}
add_action( 'send_headers', 'gwolle_gb_rss_header' );

function gwolle_gb_rss() {
        header( 'X-Test-2: Test=2' );
        // does not set the header
        header('Content-Type: ' . feed_content_type('rss') . '; charset=' . get_option('blog_charset'), true);
}
Last edited 9 years ago by mpol (previous) (diff)

#7 follow-up: @swissspidy
8 years ago

Ignore my previous comment. I just had another look at this and couldn't find any problem.

<?php
// Example A:

function trac_36334_add_superfeed() {
        add_feed( 'superfeed', 'trac_36334_superfeed_cb' );
}

add_action( 'init', 'trac_36334_add_superfeed' );

function trac_36334_superfeed_cb() {
        header( 'Content-Type: text/html' );
        echo 'Do something...';
}
<?php
// Example B:

function trac_36334_add_superduperfeed() {
        add_feed( 'superduperfeed', 'trac_36334_superduperfeed_cb' );
}

add_action( 'init', 'trac_36334_add_superduperfeed' );

function trac_36334_superduperfeed_cb() {
        header( 'Content-Type: text/html' ); // or any other content type
        echo 'Do something...';
}

function trac_36334_superduperfeed_type( $content_type, $type ) {
        if ( 'superduperfeed' === $type ) {
                return feed_content_type( 'rss2' );
        }

        return $content_type;
}

add_filter( 'feed_content_type', 'trac_36334_superduperfeed_type', 10, 2 );

Both examples work as expected running WordPress 4.5 and no additional plugins.

#8 @SergeyBiryukov
8 years ago

  • Milestone set to Awaiting Review

#9 @mpol
8 years ago

Thank you, Example B works as expected, though I don't understand how :).

I will see if I understand it enough to add this to the Codex.

To be clear, Example A does not set any header for the RSS Feed:

$ HEAD domain.com/?feed=superfeed
200 OK
Connection: close
Date: Mon, 18 Apr 2016 09:55:56 GMT
ETag: "a74e88ee3b1032ef8aae37c9d51c6eb4"
Server: Apache/2.4.20 (Mageia) OpenSSL/1.0.2g PHP/7.0.5
Content-Type: application/octet-stream; charset=UTF-8
Last-Modified: Mon, 18 Apr 2016 09:51:53 GMT
Client-Date: Mon, 18 Apr 2016 09:55:56 GMT
Client-Peer: 192.168.0.3:80
Client-Response-Num: 1
Link: <http://domain.com/?rest_route=/>; rel="https://api.w.org/"
X-Powered-By: PHP/7.0.5

Example B does have the header

Content-Type: application/rss+xml; charset=UTF-8
Last edited 8 years ago by mpol (previous) (diff)

#10 @johnbillion
8 years ago

#36620 was marked as a duplicate.

#11 @stevenkword
8 years ago

  • Keywords needs-docs needs-codex added

#12 @stevenkword
8 years ago

I've put a suggestion here for documentation. https://developer.wordpress.org/reference/functions/add_feed/#comment-2086

However, I'm wondering if the default behavior should not be 'text/xml' for custom feeds unless otherwise specified.

@stevenkword
8 years ago

Change default customer feed mime type to text/html

#13 @stevenkword
8 years ago

After looking at #36620, I've added 36334.patch which will set the default mime type for feeds to 'text/html'. In my opinion this is the better default than 'application/octet-stream'.

@johnbillion, I'd love to get your take on this since you fixed #36620 which addressed the same issue.

#14 @stevenkword
8 years ago

  • Keywords has-patch added

@stevenkword
8 years ago

A little modification since http-rss is gone.

#15 @stevenkword
7 years ago

  • Milestone changed from Awaiting Review to Future Release

#16 in reply to: ↑ 7 @DrLightman
5 years ago

Replying to swissspidy:

<?php
// Example A:
...
// Example B:
...

Both examples work as expected running WordPress 4.5 and no additional plugins.

Thanks for Example B, it works in WP 5.3.2

Example A instead, doesn't work and the line:

<?php
header( 'Content-Type: ' . feed_content_type( 'rss2' ) . '; charset=' . get_option( 'blog_charset' ), true );

in the file \wordpress\wp-includes\feed-rss2.php is misleading and has no effects, I suppose in either the standard /feed/ or any other custom /feed/custom/ one creates taking and including that file as a starting template (as I usually do).

Note: See TracTickets for help on using tickets.