I found the answer by tracing through the wordpress code, wasn’t easy, this code is really a complete mess but hell, i made it through…
The solution comes in 3 different parts:
- Register your custom post type / Custom permalink structure
- Generate your custom rules / Overwrite existing rules
- Overide the redirect canonical filter to prevent redirection when you have a custom permalink structure with optional parts
Portion #1, custom post type/permalink registration
Use register_post_type() to register a custom post type or use add_permalink() to add a simple permalink, in my case i used a custom post type to store my webservice endpoints as pages and i use special rewrite rules to redirect the traffic there:
add_action('init', 'register_cpt_jsonwebservice');
function register_cpt_jsonwebservice() {
register_post_type( 'json', $args ); //See the definition of $args in the codex
}
Portion #2, Generate the special rewrite rules to redirect complex traffic to my pages handled by my custom post type
Using add_rewrite_tag, we can create the jsonid rewrite tag that will be read by the request parser, then reconfigure the permastruct to support an additional %jsonid% which is totally unorthodox, there are probably better ways to do that. The magic ends with a special rule that i add to the rewriter, this rule allows me to call pages with the url “/data///” and will redirect the traffic to the json custom type automaticaly.
add_action('generate_rewrite_rules', 'register_crr_jsonwebservice');
function register_crr_jsonwebservice($wp_rewrite) {
//Add the jsonid tag
add_rewrite_tag('%jsonid%', '([0-9a-zA-Z\-]+)', 'jsonid=');
//Reconfigure the json permastruct to add the json id, cannot be done normaly i think, i need to investigate register_post_type function
$wp_rewrite->extra_permastructs['json']['struct'] = '/json/%json%/%jsonid%/';
//Add the special data rules at the top
add_rewrite_rule('data/([^/]+)(/([a-zA-Z0-9\-]*))?$', 'index.php?post_type=json&name=$matches[1]&jsonid=$matches[3]', 'top');
}
Portion #3, prevent nasty canonical redirections
WordPress will always try to redirect the user to the page url that maps to the request. Thus, if /data/trips/ doesn’t correspond to /json/trips/ is configured for the custom post type, it will force a redirect to the right place, obviously crashing our party because ReST requires us not to redirect when POSTing, PUTing or DELETEing.
To this end, if you filter out on “redirect_canonical” you can intercept requests to redirect on your custom post type and thus prevent those nasty redirects crashing your ReST interface:
add_filter('redirect_canonical', array($this, 'register_crr_jsonwebservice_redirect_canonical'));
function register_crr_jsonwebservice_redirect_canonical($redirect_url)
{
if(strpos($redirect_url, '%jsonid%') !== false)
{
return '';
}
return $redirect_url;
}
Thats all folks…