Tag Archives: wordpress

Make Feedly Notice an Updated WordPress Post by Changing the GUID

Sometimes it’s better to update an existing post than to write a new one. Maybe there’s an ongoing conversation in the comments thread, or news is breaking over the course of a day. Sometimes I’ll post a poll, then reuse the same post for the results, to keep discussion together. The problem is that not everyone will get the notice that the article has changed.

After posting a question on Feedly’s Google+ page, I confirmed that Feedly (and no doubt other readers) uses the post GUID to decide whether to fetch content. If it’s seen the GUID before, it assumes it’s already seen the content, and stops looking at it.

If you’ve never delved into RSS markup, you’ve probably never noticed this field, but the GUID is a “generally unique identifier” used to tell feed readers whether they’ve seen an article before. A new GUID means a new post. Most of the time, you don’t want that to happen, because you don’t want it adding the same post over and over again every time you fix a typo or change a headline.

Under limited circumstances, though, it might make sense to tell reader software that the updated post is a new one.

A StackExchange post pointed me to a filter hook that can be used to change the GUID. WordPress uses the ID-style permalink by default, because it should be unique, but it’s important to remember that the field is only an ID, and isn’t used as a link — so you can modify it without worrying about it staying a valid URL.

The response suggested to just append the modification date, but I didn’t want to do that. I frequently update old posts to fix typos, update links, remove dead links, etc. So instead, I added a custom field that I can fill out when I make a big enough change that I want the post to show up as new again.

// Modify the GUID in the RSS feed after major revisions (but not after every
// little change) so that clients like Feedly will pull the updated content.
function ktv_feed_guid_revisions($content) {
	$revised = get_post_meta( get_the_ID(), 'updated', true );
	if ($revised != "") {
		$content .= "?updated=$revised";
	}
	return $content;
}
add_filter('get_the_guid', 'ktv_feed_guid_revisions', 7);

I’ve got it in a functionality plugin for now. When I make a change that I really want to update everywhere, I add a custom field called “updated” and give it a value – usually a number, so that I can add to it if I have something that I update more than once while it’s still new enough to show up in feeds.

I wrote this months ago, but never got around to publishing it. Yesterday’s 10 ways to optimize your feed for feedly reminded me it was still sitting in my drafts, so I dusted it off.

Jetpack Related Posts Missing on an SSL WordPress Site? Check for RC4 and Turn it Off!

After switching one of my self-hosted WordPress blogs to all-HTTPS, I ran into an odd problem: Jetpack Related comments stopped working after a while.

After going back and forth with Jetpack support and my web host, it turned out the problem was with the SSL configuration on my site. Jetpack has to download a copy of your posts in order to calculate recommendations, and it uses libcurl to do that. Curl has stopped supporting the RC4 cipher in SSL connections because weaknesses have been found in it…and that’s what my server was using! (Ack!) I assume it was an old compatibility setting that never got updated.

Jetpack needed to reindex the site, but couldn’t retrieve anything, so it got stuck on “Indexing request queued and waiting…” Disconnecting and reconnecting didn’t work. Jetpack thought it was connected, so it didn’t report an error. (I assume it uses a different library for some things.) Pages were loading the script and the placeholder, but didn’t have suggestions to put there. And of course it wasn’t done indexing, so it didn’t offer a reindex button on the debug page.

What to do:

SSL ciphers are a server configuration setting, not a problem with your SSL certificate, so you don’t need to revoke and reissue the cert. If your hosting provider manages your server, you can ask them to disable RC4. If you run your own server, you’ll need to look up how to disable RC4 on IIS, Apache, NginX, etc. You can verify your site’s settings at Qualys’ SSL Server Test: Look for RC4 in the results and see if it’s labeled Yes or No.

If Jetpack doesn’t start indexing after you change your config, try turning off the Related Posts module and turning it back on. It only took a few minutes before recommendations started appearing on the site again.

There is one downside, which is that some older browsers (specifically. Internet Explorer on Windows XP) may not be able to connect. As always, it’s a trade-off.

Moved to a faster server, ALMOST moved to NginX

As of last week, this site is being served to you by a shiny new SSD-backed VPS at DreamHost. I was hoping it would be running NginX as well, but try as I might, I couldn’t get WordPress in a subdirectory to play nice with NginX. Speed Force worked fine, but it’s at the top level of a site. Ramblings and Re-Reading Les MisĂ©rables aren’t.

Fortunately, the new virtual servers are faster and cheaper (newer hardware, after all), and with the rest of my sites running NginX I end up with about the same overall memory footprint for two VPSes so that I could put this back on Apache. I suppose that saved me time converting the zillions of .htaccess rules I’ve amassed over the years. And with the faster systems, they’re able to handle more complex/simultaneous actions without timing out or spiking memory.

Pingback Problem: 162K WordPress Sites Tricked into DDoS

It’s always annoying when someone figures out a way to exploit intentional behavior, especially when it’s a key part of the design.

Sucuri reports on a denial-of-service attack that used thousands of legit WordPress sites to distribute the attack by sending fake pingbacks “from” the target site to all of the reflectors. Those blogs would all contact the targeted site to confirm the pingback and retrieve a title and summary…all at once, overwhelming it and taking it offline.

The quick-and-dirty solution is to remove XML-RPC functionality, but that also breaks certain plugins (like Jetpack) and the ability to connect to your blog using the WordPress mobile apps.

A little background on why Pingbacks work this way:

Waaaay back in the early days of blogging, most bloggers would interact by way of comments. If you wrote a blog post, and I was inspired to write a response, I would then go over to your site and post a comment letting you know about my own post. Two systems were proposed in 2002 to automate this process: Pingbacks and trackbacks.

  • Trackbacks sent a complete summary to the remote blog, including the title of your post, the link, and an excerpt (which you could manually craft, or let your software handle).
  • Pingbacks sent a notice — a “ping” — to the remote site with the URL of your post, and then the remote site would retrieve it and extract the title and a summary.

This was also around the time that blog comment spam and spammy blogs were getting to be a big problem. What would happen is a spamming site would send out trackbacks to as many sites as possible claiming that they’d responded to some post, thereby getting backlinks on a zillion blogs and increasing their page rank. Pingbacks had an advantage: Because you were calling back already, your server could check to see whether the other site really had linked to you. It took a long time, but eventually this escalated into spammy blogs creating a temporary post *with* real links to the pages they spammed, then replacing them with their spam pages after a short amount of time.

The problem now is: How do you block abuse of an as-designed behavior? That’s happened before: Back in the early days of the internet, it was considered polite to run your mail server as an open relay and rude to lock it down, but after spammers started massively abusing them, an open relay became a sign of a sysadmin who didn’t know what he was doing.

The comments on the Sucuri article suggest that Akismet, as a collaborative comment-spam filter, might be able to mitigate this type of attack. Wordfence’s collaborative security filter seems like another system well-positioned to detect it. But if that approach fails, pingbacks might just go the way of open relays.

Update March 18: Akismet has released a new version of the anti-spam plugin that mitigates this problem in two ways:

  1. Spam checks on pingbacks are now done before the verification request is sent, so that once an attack is identified, Akismet will prevent blogs from participating.
  2. An X-Pingback-Forwarded-For header is added to the verification request identifying where the pingback actually came from, making WordPress+Akismet a less attractive choice as a reflector by removing the anonymity.

Item #2, IMO, belongs in WordPress itself, not in a plugin, but I imagine this was a way to roll out the feature more quickly, at least to those sites using Akismet.

Update April 8: The X-Pingback-Forwarded-For header has been added to WordPress 3.8.2 and the upcoming 3.9.

First Stab at WordPress/MySQL Tuning

My job sent me to a class on scaling, optimizing and troubleshooting MySQL this week. I’ve been digging around a bit on some test databases at work, but of course as someone running a self-hosted WordPress blog, I had another MySQL server to practice on right here — one with real-world data and (admittedly low) load, but where I was only accountable to myself if I messed anything up.

Unfortunately, DreamHost’s MySQL VPS doesn’t give you much control over the server, and of course when you’re working with a third-party application, there’s only so much you can change the database without breaking compatibility. But I found some interesting surprises:

1: Everything was using the older MyISAM engine, because DreamHost is running an older version of MySQL that uses it as the default. Switching to the newer InnoDB (and back) is simple and safe enough that I figured it was worth a try.

2: There was a lot of junk left over from old plugins that I haven’t used in years. Continue reading