WordPress unter IIS 7.5 mit URL Rewrite und 404-Handling

missing
Bildquelle: Pixabay, glasskid50 (modifiziert)

Es gibt Behelfslösungen, und es gibt solche, die sind glatt wie ein Droidenpopo, mitunter jedoch genauso schwer zu finden. So kam es mir zumindest bei der Suche nach einer WordPress konformen 404-Behandlung unter einem Hosting-Produkt mit URL Rewrite unter Windows 2008 Server vor.

iis not found

Man erkennt die Vefügbarkeit von URL Rewrite unter IIS (erst ab 7) ganz einfach daran, dass einem WordPress „echte“ Clean-URLs anbietet (nicht wie sonst über das Muster index.php/%postname%/). WordPress „weiß“ auf welchem Server es liegt, und bietet einem bei Änderung der Permalinkeinstellungen entweder den rewrite Code für die .htaccess an, oder den für die web.config, wie folgt

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
	<system.webServer>
		<rewrite>
			<rules>
				<rule name="wordpress" patternSyntax="Wildcard">
					<match url="*"/>
						<conditions>
							<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
							<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
						</conditions>
						<action type="Rewrite" url="index.php"/>
				</rule>
			</rules>
		</rewrite>
	</system.webServer>
</configuration>

Damit funktioniert bei mir lokal (IIS 7.5) bereits alles bestens. Der Aufruf einer nicht existenten Seite in einem WordPress wird durch den Aufruf des 404-Templates beantwortet. Doch dem war nicht so im Livebetrieb auf dem Webserver. Der riss die 404-Behandlung an sich, noch bevor WordPress auf is_404() checken und das entsprechende Template aktivieren konnte.

Den entscheidenden Hinweis gab die Funktion

function handle_404()

in wp-includes/class-wp.php, die mit den Zeilen

// Guess it's time to 404.
$wp_query->set_404();
status_header( 404 );
nocache_headers();

endet. Das Ausmarkieren des status_header ( 404 ) verhinderte die Behandlung durch den Webserver. Einen direkten Hook auf die Funktion gibt es nicht. Man kann sich jedoch in den status_header einhaken. Nachdem ich dort die Statusmeldung 404 zu einer 301 (redirect) erklärt hatte (Zeile mit Anmerkung // Modifikation), erfuhr der Webserver nichts mehr von „Seite nicht gefunden“, und das 404-Template wurde aufgerufen.

// verhindert, dass Server die 404-Meldung abfängt
// Originalfunktion in wp-includes/functions.php
add_filter('status_header', 'prevent_404');
function prevent_404($header) {
   if( $header == 404 ) $header = 301; // Modifikation
	$text = get_status_header_desc( $header );
	if ( empty( $text ) )
		return false;

	$protocol = $_SERVER["SERVER_PROTOCOL"];
	if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol )
		$protocol = 'HTTP/1.0';
	$status_header = "$protocol $header $text";
	if ( function_exists( 'apply_filters' ) )
		$status_header = apply_filters( 'status_header', $status_header, $header, $text, $protocol );

	return @header( $status_header, true, $header );
}

Das war die vorübergehende Behelfslösung.

Auf iis.net fand ich dann die Richtige. Dem Webserver wird mit nachfolgender kurzer Zeile gesagt, im Fehlerfall gar nichts zu tun, und die skriptseitige Lösung gewähren zu lassen.

httperror-Handling durch Webserver verhindern

<httpErrors existingResponse="PassThrough" />

web.config komplett

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
	<system.webServer>
		<rewrite>
			<rules>
				<rule name="wordpress" patternSyntax="Wildcard">
					<match url="*"/>
						<conditions>
							<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
							<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
						</conditions>
						<action type="Rewrite" url="index.php"/>
				</rule>
			</rules>
		</rewrite>
		
        <httpErrors existingResponse="PassThrough" />
	
	</system.webServer>
</configuration>

Quelle: HTTP Errors httpErrors

Bitte Kommentarfunktion nicht für Supportanfragen nutzen. Dem kann hier nicht entsprochen werden. Die Angabe einer E-Mail-Adresse und eines Namens ist nicht erforderlich. Einen (Spitz)-Namen zu nennen wäre aber doch nett.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Hinweis: Sowohl angegebener Name als auch E-Mail-Adresse (beides ist optional, dafür werden alle Kommentare vor Veröffentlichung geprüft) werden dauerhaft gespeichert. Du kannst jeder Zeit die Löschung Deiner Daten oder / und Kommentare einfordern, direkt über dieses Formular (wird nicht veröffentlicht, und im Anschluss gelöscht), und ich werde das umgehend erledigen. – Mit hinterlassenen Kommentaren hinterlegte IP-Adressen werden nach zwei Monaten automatisch gelöscht

publicly queryable