Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 21 additions & 12 deletions src/Router/RewriteHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,13 @@ public function prevent_markdown_redirect($redirect_url, $requested_url) {
* @return void
*/
public function parse_markdown_url(\WP $wp): void {
$request_uri = $_SERVER['REQUEST_URI'] ?? '';
$request_uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : '';

// Extract path without query string
$path = parse_url($request_uri, PHP_URL_PATH);
$path = wp_parse_url($request_uri, PHP_URL_PATH);
if ($path === false || $path === null) {
return;
}

// Check if URL ends with .md (case-sensitive, lowercase only)
if (!preg_match('/^\/(.+)\.md$/', $path, $matches)) {
Expand Down Expand Up @@ -229,7 +232,7 @@ public function handle_markdown_request(): void {
}

// Get the request URI
$request_uri = $_SERVER['REQUEST_URI'] ?? '';
$request_uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : '';

// Enforce lowercase .md extension - let WP 404 if wrong case
if (!preg_match('/\.md$/', $request_uri) && preg_match('/\.md$/i', $request_uri)) {
Expand All @@ -238,8 +241,14 @@ public function handle_markdown_request(): void {

// Handle trailing slash redirect: /post-slug.md/ -> /post-slug.md
if (preg_match('/\.md\/$/', $request_uri)) {
$redirect_url = rtrim($request_uri, '/');
wp_redirect($redirect_url, 301);
$path = wp_parse_url($request_uri, PHP_URL_PATH);
$path = ($path !== false && $path !== null) ? rtrim($path, '/') : '';
$query = wp_parse_url($request_uri, PHP_URL_QUERY);
$redirect_url = home_url($path);
if (!empty($query)) {
$redirect_url .= '?' . $query;
}
wp_safe_redirect(esc_url_raw($redirect_url), 301);
exit;
}

Expand Down Expand Up @@ -324,7 +333,7 @@ public function handle_accept_negotiation(): void {
}

// Check Accept header for text/markdown
$accept = $_SERVER['HTTP_ACCEPT'] ?? '';
$accept = isset($_SERVER['HTTP_ACCEPT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_ACCEPT'])) : '';
if (strpos($accept, 'text/markdown') === false) {
return;
}
Expand All @@ -335,13 +344,13 @@ public function handle_accept_negotiation(): void {
return;
}

// Build markdown URL
$md_url = rtrim($canonical, '/') . '.md';

// 303 See Other redirect with Vary header for caching
status_header(303);
// Build markdown URL and redirect safely
$md_url = esc_url_raw(rtrim($canonical, '/') . '.md');
if ($md_url === '') {
return;
}
header('Vary: Accept');
header('Location: ' . $md_url);
wp_safe_redirect($md_url, 303);
exit;
}

Expand Down