That’s an old problem, and I have never looked deep enough explain it. But I have a plugin for that, written a long time ago. It still works, but keep the age of the code in mind when reading it. 🙂 I didn’t change much for this repost.
<?php
/*
Plugin Name: T5 Canonical Permalink
Plugin URI: http://toscho.de/2010/wordpress-plugin-canonical-permalink/
Description: Removes illegal numeric suffixes from the request URI.
Version: 0.3
Author: Thomas Scholz
Author URI: http://toscho.de
Created: 04.04.2010
*/
add_action('wp', 't5_canonical_request');
/**
* WordPress allows URIs with any numeric suffix, e.g.:
* /canonical-page-or-postname/12345/
* This functions performs a simple check and redirects
* to the canonical URI if neccessary.
*
* @return void
*/
function t5_canonical_request()
{
global $page, $post;
// post, page, attachment, preview
if ( ! is_singular() or is_preview() )
{
return;
}
$permalink = get_permalink();
// We don't have access to the number of sub pages here.
// So we have to hack.
$max_pages = substr_count(
$post->post_content, '<!--nextpage-->') + 1;
if ( 1 < $page and $page <= $max_pages )
{
/*
* Handle different permalink settings, eg:
* /%year%/%postname%.html or
* /%year%/%postname%/
*/
$rev_perma_struct = strrev(get_option('permalink_structure'));
if ( "https://wordpress.stackexchange.com/" != $rev_perma_struct[0] )
{
$permalink .= "/$page";
}
else
{
$permalink .= "$page/";
}
}
$host_uri = 'http'
. ( empty ( $_SERVER['HTTPS'] ) ? '' : 's' )
. '://' . $_SERVER['HTTP_HOST'];
$canonical_path = str_replace($host_uri, '', $permalink);
if ( ! empty ( $_GET ) )
{
global $wp;
// Array
$allowed = $wp->public_query_vars;
$out_arr = array();
foreach ( $_GET as $k => $v )
{
if ( in_array($k, $allowed ) )
{
$out_arr[] = $k . ( empty ( $v ) ? '' : "=$v" );
}
}
if ( ! empty ( $out_arr ) )
{
$canonical_path .= '?' . implode('&', $out_arr);
}
}
if ( $canonical_path == $_SERVER['REQUEST_URI'] )
{
return;
}
// Debug current result:
#print '<pre>' . var_export($canonical_path, TRUE) . '</pre>';
// Change it or return 'false' to stop the redirect.
$canonical_path = apply_filters(
't5_canonical_path',
$canonical_path
);
if ( FALSE != $canonical_path )
{
header('Location: ' . $permalink, true, 301);
die("<a href="https://wordpress.stackexchange.com/questions/70992/$permalink">$permalink</a>");
}
return;
}