Umleitung bei 404
Martin Hein
- webserver
Hallo Forum,
ich möchte gerne ein eigenes ErrorDocument auf meinem Apache 2 ausprobieren aber ich kriegs nicht hin. Kann mir jemand nen
Tipp geben, warum das folgende nicht geht ?
<VirtualHost *:80>
ServerName sebam.mobile.net
DocumentRoot C:/Dokume~1/me/sebam.de
DirectoryIndex index.php
ErrorDocument 404 C:/Dokume~1/me/sebam.de/notfound.html
</VirtualHost>
Der VHost lässt sich ansprechen, aber die Definition des ErrorDocuments an der Selle hat keinerlei Auswirkung.
Kann jemand sehen, was da falsch ist ?
Danke und
beste gruesse,
martin
Moin!
ErrorDocument 404 C:/Dokume~1/me/sebam.de/notfound.html
Der VHost lässt sich ansprechen, aber die Definition des ErrorDocuments an der Selle hat keinerlei Auswirkung.
Kann jemand sehen, was da falsch ist ?
Du gibst einen Dateinamen an, das ist falsch. Du mußt den URL-Pfadnamen (beginnend bei /, ohne Domain) der Seite angeben.
- Sven Rautenberg
Moin Sven,
Ich hätte vielleicht dazu schreiben sollen, dass ich das ganze unter
Windows teste. Ich war davon ausgegangen, dass die Angbabe mit
"/datei.htm", wie bei "DocumentRoot" einfach nur eine absolute
Pfadangabe ist:
DocumentRoot C:/folder
... funktioniert. Und es deshalb dementsprechend:
ErrorDocument 404 C:/folder/mymissing.htm
... lauten muss. Ich habe folgendes ausprobiert:
<VirtualHost *:80>
ServerName sebam.mobile.net
DocumentRoot C:folder
ErrorDocument /error/mymissing.htm
DirectoryIndex index.php
</VirtualHost>
Das führte dazu, dass sich der Apache nicht mehr starten liess,
obwohl die Datei dort existierte ;(
Mit der absoluten Pfad:
C:/folder/mymissing.htm
läuft der Apache wieder, aber das Dokument wird nicht angezeigt.
Ich habe noch eine Ahnung:
Weiter oben steht etas ist der httpd.conf, dass offenbar für die
Anzeige des ErrorDocuments zuständig ist. Ich kann mir vorstellen,
dass das dafür sorgt, dass die Angabe im <VirtualHost *:80> gar
nicht greift und ich dort etwas ändern muss.
Der Auszug:
-----------
<IfModule mod_negotiation.c>
<IfModule mod_include.c>
Alias /error/ "C:/Programme/xampp/apache/error/"
<Directory "C:/Programme/xampp/apache/error">
AllowOverride None
Options IncludesNoExec
AddOutputFilter Includes html
AddHandler type-map var
Order allow,deny
Allow from all
LanguagePriority en cs de es fr it ja ko nl pl pt-br ro sv tr
ForceLanguagePriority Prefer Fallback
</Directory>
ErrorDocument 400 /error/HTTP_BAD_REQUEST.html.var
ErrorDocument 401 /error/HTTP_UNAUTHORIZED.html.var
ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var
ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var
ErrorDocument 405 /error/HTTP_METHOD_NOT_ALLOWED.html.var
ErrorDocument 408 /error/HTTP_REQUEST_TIME_OUT.html.var
ErrorDocument 410 /error/HTTP_GONE.html.var
ErrorDocument 411 /error/HTTP_LENGTH_REQUIRED.html.var
ErrorDocument 412 /error/HTTP_PRECONDITION_FAILED.html.var
ErrorDocument 413 /error/HTTP_REQUEST_ENTITY_TOO_LARGE.html.var
ErrorDocument 414 /error/HTTP_REQUEST_URI_TOO_LARGE.html.var
ErrorDocument 415 /error/HTTP_UNSUPPORTED_MEDIA_TYPE.html.var
ErrorDocument 500 /error/HTTP_INTERNAL_SERVER_ERROR.html.var
ErrorDocument 501 /error/HTTP_NOT_IMPLEMENTED.html.var
ErrorDocument 502 /error/HTTP_BAD_GATEWAY.html.var
ErrorDocument 503 /error/HTTP_SERVICE_UNAVAILABLE.html.var
ErrorDocument 506 /error/HTTP_VARIANT_ALSO_VARIES.html.var
</IfModule>
</IfModule>
Kann das sein ?
beste gruesse,
martin
Moin!
Ich hätte vielleicht dazu schreiben sollen, dass ich das ganze unter
Windows teste.
Nein. Kein anderes Betriebssystem verwendet Laufwerksbuchstaben in Pfadnamen.
Ich war davon ausgegangen, dass die Angbabe mit
"/datei.htm", wie bei "DocumentRoot" einfach nur eine absolute
Pfadangabe ist:DocumentRoot C:/folder
... funktioniert. Und es deshalb dementsprechend:ErrorDocument 404 C:/folder/mymissing.htm
... lauten muss.
Das ist eben falsch. Das ErrorDocument ist laut Doku definiert als:
ErrorDocument Fehlercode Dokument
Dokument ist hierbei eben eine lokale Ressource. Die Apache-Doku dazu gibts auch auf Deutsch: http://httpd.apache.org/docs/2.0/mod/core.html#errordocument
Ich habe folgendes ausprobiert:
<VirtualHost *:80>
ServerName sebam.mobile.net
DocumentRoot C:folder
ErrorDocument /error/mymissing.htm
DirectoryIndex index.php
</VirtualHost>Das führte dazu, dass sich der Apache nicht mehr starten liess,
obwohl die Datei dort existierte ;(
Da steht kein Fehlercode vor dem Dokument.
Mit der absoluten Pfad:
C:/folder/mymissing.htm
läuft der Apache wieder, aber das Dokument wird nicht angezeigt.
Wie in der Doku nachzulesen, ist das Dokument relativ zum DOCUMENT_ROOT - oder eine externe URL, auf die umgeleitet wird (was man nicht will, weil dadurch der 404-Status nicht ausgegeben werden kann, da die Umleitung den temporären Redirect mit Status 302 erfordert).
Weiter oben steht etas ist der httpd.conf, dass offenbar für die
Anzeige des ErrorDocuments zuständig ist. Ich kann mir vorstellen,
dass das dafür sorgt, dass die Angabe im <VirtualHost *:80> gar
nicht greift und ich dort etwas ändern muss.
Nein, das ErrorDocument kann in verschiedenen Ebenen geändert werden, global, lokal oder auch per .htaccess im jeweiligen Verzeichnis.
Aber dein Auszug zeigt dir, wie die Direktive zu schreiben ist:
ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var
Wenn es also auf deinem VHost ein Dokument http://vhost-domain/error/HTTP_NOT_FOUND.html.var gibt (wobei das .var für Content Negotiation zuständig ist - das ist ein ganz anderes Thema und soll nicht weiter verwirren), dann wird dieses für Fehlermeldungen mit Status 404 benutzt.
Vergleiche die URLs, rufe dein Fehlerdokument mal unter seiner URL ab. Wenn da nichts kommt, hast du die falsche URL im ErrorDocument angegeben.
- Sven Rautenberg
Hallo Sven,
völlig korrekt. Vielen Dank für deine Geduld !
Mit Angabe einer Url (http://vhost-domain/notfound.php) funktioniert's tadellos. Jetzt versuche ich das ganze
mal in die htaccess zu verschieben ... aber das dürfte
dann ja kein Problem sein.
Jetzt hätte ich auf der notfound.php noch gerne gewusst,
welche Seite nicht gefunden wurde. Das Array "$_SERVER[]"
gibt keine Auskunft darüber. Wäre auf unlogisch gewesen,
ich hab's trotzdem mal ganz naiv anzeigen lassen. Bei
Rewrite-Rules steht einem ja etwas in der Art ->
"%{Referer}i" zur Verfügung. Das müsste doch theroretisch
gehen. Nur die Syntax ist mit noch nicht klar.
beste gruesse,
martin
Moin!
Mit Angabe einer Url (http://vhost-domain/notfound.php) funktioniert's tadellos.
Nein, funktioniert es nicht. Mit URL wird ein Redirect ausgelöst. Das willst du nicht.
Jetzt hätte ich auf der notfound.php noch gerne gewusst,
welche Seite nicht gefunden wurde. Das Array "$_SERVER[]"
gibt keine Auskunft darüber.
Ohne Redirect würde es das tun, als REQUEST_URI. Allein deswegen willst du keinen Redirect.
- Sven Rautenberg
Moin Sven,
Nein, funktioniert es nicht. Mit URL wird ein Redirect ausgelöst. Das willst du nicht.
ok ok, ich hatte mich kurz gefreut, etwas erreicht zu haben,
was aussah, als würde es mein Problem lösen ;)
Ohne Redirect würde es das tun, als REQUEST_URI. Allein deswegen willst du keinen Redirect.
Verstanden, ich komme um die Angabe beginnend mit "/" nicht drum herum ... habs immernoch nicht hinbekommen, weil ich mit dem "/"
nicht warm werde ;(
1. Versuch:
-----------
<VirtualHost *:80>
ServerName sub.domain.net
DocumentRoot Z:/htdocs/domain.net
DirectoryIndex index.php
ErrorDocument 404 /_content/notfound.php
</VirtualHost>
Das ErrorDocument liegt unter:
Z:/htdocs/domain.net/_content/notfound.php
Ich habe "/" als DocumentRoot angenommen
Das ErrorDocument ist dort vorhanden, aber:
"Die Seite kann nicht angezeigt werden."
2. Versuch:
-----------
<VirtualHost *:80>
ServerName sub.domain.net
DocumentRoot Z:/htdocs/domain.net
DirectoryIndex index.php
ErrorDocument 404 /error/mymissing.html
</VirtualHost>
Das ErrorDocument liegt unter:
D:/Programme/xampp/apache/error/mymissing.html
Ich habe "/" als ServerRoot ("D:/Programme/xampp/apache")
angenommen. Das ErrorDocument ist dort vorhanden, aber:
"Die Seite kann nicht angezeigt werden."
Irgendwas mache ich immernoch falsch.
Tausend Dank für einen Tipp und
beste gruesse,
martin
Versuch 1 funktioniert doch ... immer schön Apache neu starten.
tausend Dank für Deine kompetente Hilfe und
beste gruesse,
martin
Hi,
das ganze nimmt nun sehr vertrakt Züge an, die ich nicht mehr
nachvollziehen kann.
Das ErrorDocument (z.Zt. noch in der httpd.conf definiert) sollte
mehr als nur eine selbstgestaltete Fehlerseite sein. Es sollte
vielmehr versuchen den Fehler beheben. Und zwar folgendermassen:
In einer .htaccess, dierkt unter "/" definiert stehen knapp
400 Rewriterules nach dem Muster:
RewriteRule ^Impressum/$ /_content/?site_id=138&%{QUERY_STRING}
Diese RewriteRules werden von einem selbstgebastelten CMS
geschrieben, sobald eine neue Seite in der Struktur veröffentlicht
wird, indem ich eine "writehtaccess.inc.php" includiere. Damit
hat der Server einiges zu tun, aber es passiert nicht so oft.
Mit meinem ErrorDocument wollte ich den Fehler abfangen, dass
diese .htaccess nicht aktuell ist, indem ich eben auch dort
diese "writehtaccess.inc.php" includiere, um so die htaccess
auf den neuesten Stand zu bringen, falls ein Dokument nicht
gefunden wird.
Genau das tut es auch. Allerdings viel zu häufig ;(
Das Phänomen ist, dass die "notfound.php" aufgerufen wird,
obwohl es eine RewriteRule gibt, in der steht, wo sich die angeforderte Seite befindet. Während die "notfound.php"
noch abgearbeitet wird, scheint es so als würde die RewriteRule
gefunden und angewendet.
kann so etwas sein ?
beste gruesse,
martin
Moin!
In einer .htaccess, dierkt unter "/" definiert stehen knapp
400 Rewriterules nach dem Muster:RewriteRule ^Impressum/$ /_content/?site_id=138&%{QUERY_STRING}
Das ist ganz schlecht.
Meine Empfehlung: Rewrite ALLE Requests auf die zentrale PHP-Seite, und prüfe erst DORT die abgerufene Seite (steht in $_SERVER('REQUEST_URI') drin). Wird ja wohl irgendwo in der Datenbank abgelegt sein, welcher Inhalt zu welcher URL gehört.
Abhängig vom Resultat der DB-Suche sendest du beim Abruf einer nichtexistenten Seiten den Status 404 (mit header()) oder eben die existierende Seite.
- Sven Rautenberg
Moin,
In einer .htaccess, dierkt unter "/" definiert stehen knapp
400 Rewriterules nach dem Muster:RewriteRule ^Impressum/$ /_content/?site_id=138&%{QUERY_STRING}
Das ist ganz schlecht.
ich hab wieder leichte Verständnisschwierigkeiten. Deshalb erklär
ich mal, wie das ganze bisher funktioniert:
-----------------------------------------------------------------
Der Aufruf der url "/_content/?site_id=138" über einen Link
innerhalb der Seite geht an diese zentrale Seite, die mit
einem DB-QUERY aus "site_id=138" den Pfad "/Impressum/"
ermittelt und dahin per header() weiterleitet. Beim Aufruf
der URL greift die RewriteRule:
^Impressum/$ /_content/?site_id=138&%{QUERY_STRING}
... die dann ihrerseits dafür sorgt, dass der Inhalt der
ursprünglich angeforderten URL "/_content/?site_id=138"
angezeigt wird.
-----------------------------------------------------------------
... das hört sich für mich in etwa an, wie das, was du empfielst.
beste gruesse,
martin
Moin!
ich hab wieder leichte Verständnisschwierigkeiten. Deshalb erklär
ich mal, wie das ganze bisher funktioniert:
Der Aufruf der url "/_content/?site_id=138" über einen Link
innerhalb der Seite geht an diese zentrale Seite, die mit
einem DB-QUERY aus "site_id=138" den Pfad "/Impressum/"
ermittelt und dahin per header() weiterleitet. Beim Aufruf
der URL greift die RewriteRule:^Impressum/$ /_content/?site_id=138&%{QUERY_STRING}
... die dann ihrerseits dafür sorgt, dass der Inhalt der
ursprünglich angeforderten URL "/_content/?site_id=138"
angezeigt wird.... das hört sich für mich in etwa an, wie das, was du empfielst.
Nein, es ist genau das Umgekehrte von dem, was ich empfehle, aber genauso umgesetzt.
Ein Request auf die zentrale Datei (mutmaßlich steht hinter "/_content/" eine index.php) mit ID wird vom Skript weitergeleitet auf eine "schöne URL".
Dieser Teil ist ja ok, wenn es früher mal die ID-URLs gab, und Suchmaschinen die evtl. noch indiziert haben oder sie von anderswo her so verlinkt sind.
Aber dass dann vierhundert Rewrite-Rules wieder dafür sorgen, dass jede schöne URL zurück zu ihrer ID kommt - das ist eben komplett überflüssig.
Wenn dein Skript weiß, welche URL zur ID gehört, dann weiß es umgekehrt auch, welche ID zu einer gegebenen URL gehört.
Also reicht es aus, einfach "alle" Seiten (vielleicht nur die, die auf ".html" enden) mit einer einzigen Regel auf die zentrale index.php zu rewriten, und das Skript guckt dann nach, welche URL abgerufen wurde, welche ID dazu gehört, und gibt dann die passenden Inhalte aus. Wobei die ID dann ziemlich bedeutungslos wird, weil die ja für die Ausgabe vermutlich nicht gebraucht wird, und für den Suchprozess auch keine Bedeutung hat.
- Sven Rautenberg
Moin Sven,
Ok, ich hab Deinen, den umgekehrten Ansatz, vorhin nochmal
durchdacht und glaube, ihn verstanden zu haben:
------------------------------------------------------------
Eine RewriteRule sorgt dafür, dass jede "schöne URL" z.B.:
"http://sub.domain.net/Unsere_Leistungen/Leistungen_von_A-Z/"
auf:
"http://sub.domain.net/_content/index.php"
... zeigt, die dann aus der REQUEST_URI per Script die site_id,
ermittelt, die ich für die Darstellung der Contents benötige.
-------------------------------------------------------------
Der Vorteil ist natürlich zum Einen, dass man sich 400 RewriteRules spart (Stellt sich mir die Frage, ob das problematisch ist ?), zum anderen, dass keine Umleitung per header("location:") stattfinden muss.
Meine Lösung ist fogendermassen entstanden:
------------------------------------------------------------
Ich habe eine Anwedung gebaut, mit einem selbstgeschusterten CMS
basierend auf tinyMCE gebaut. Der Content eben dieser 400 Seiten
steckt als XHTML in einer MySQL-DB. Der Content ist durch den
Kunden eingepflegt worden, bevor die Anwendung drum herum fertig war. Alle Links lauten "./?site_id=<irgendwas zwischen 1 und 400>
Ich habe dann mod_rewrite, mit dem ich bis dahin noch nicht gearbeitet hatte und von dem ich nicht wusste, ob es zur Verfügung steht, "draufgesetzt".
------------------------------------------------------------
Der Vorteil dabei ist, dass die Anwendung ohne mod_rewrite
funktioniert.
ich könnte meine Lösung nach Deiner Empfehlung umstricken:
------------------------------------------------------------
1)
Ich könnte die 400 RewriteRules eliminieren, indem ich sie auf
eine beschränke, die grundsätzlich auf en zentrales Dokument
("/_content/index.php") zeigt, dort ein Script einsezen, dass
aus der REQUEST_URI die zugehörige site_id, die benötigt wird
aus der Datenbank holt.
-> Da stellt sich die Frage, was den Server mehr beansprucht.
Das Script abzuarbeiten, oder 400 Rules zu "lesen".
Den Content könnte ich ausserdem mit einem ähnlichen Script dahingehend parsen, dass die Links direkt "schöne URLs" sind,
statt mit dem gleichen Script die URL für die per header("location:") zu ermitteln.
-> da stellt sich die Frage, ob das Script für das parsen oder
für die Ermittlung der URL für die Umleitung mehr Action für
den Server bedeutet. Die Umleitung würde man sich aber sparen.
Ich könnte das CMS dahingehend umbauen, dass schon dort die
richtigen "schönen URLs" eingesetzt werden. Das würde die
Anwendung abhängig von mod_rewrite machen, aber das parsen
aus Schritt 2 würde wegfallen.
Ergo:
-----
Wenn ich bereit bin, mal unabhängig vom Aufand des Umbaus, mich abhängig von "mod_rewrite" zu machen, könnte ich auf 400 Rewrite
Rules verzichten und gegen ein Script ersetzen. Weiterhin könnte
ich anstelle meines Scripts, dass mir beim Aufruf einer "unschönen"
URL die "schöne" ermittelt und dann dahin umleitet, ein Script
schreiben, dass diese Umleitung spart indem es den gesamten Content
parsed, also für jeden unschönen Link den schönen ermittelt und ersetzt. Der dritte Schritt, der den zweiten spart funktioniert
nicht, weil sich die Links auf eine Seite ändern, sobald sich
z.B. der Titel ändert.
Ich danke Dir für Deine Empfehlung aber ich kann mir nicht
vorstellen, dass sie für meine Anwendung unter all diesen
Aspekten noch richtig ist (ausser die 400 Rules sind
wirklich problematisch)... und ich bin vor Allem gespannt
auf Deine Meinung.
Eine gute Nacht und
beste gruesse,
martin
Moin!
Der Vorteil ist natürlich zum Einen, dass man sich 400 RewriteRules spart (Stellt sich mir die Frage, ob das problematisch ist ?), zum anderen, dass keine Umleitung per header("location:") stattfinden muss.
Das sind zwei sehr wichtige Vorteile.
Das Einsparen des sinnlosen Redirects spart direkt Zeit beim Aufrufen neuer Seiten.
Außerdem spart es kräftig Server-Ressourcen, denn so ein Redirect erfordert ja trotzdem einen Apache-Prozess, der ihn erzeugt. Bei Websites mit vielen Zugriffen kann allein das zum Problem werden.
Das Einsparen von Zeilen in .htaccess ist ebenfalls eine sehr gute Idee. Zum einen muß die gesamte Datei für JEDEN Request, auch für alle Bilder und sonstige Ressourcen, vom Server geparst werden. Zum anderen müssen alle 400 regulären Ausdrücke auf jede angeforderte URL angewandt werden. Auch das kostet Zeit, die man sich mit eindeutig besserer Planung sparen kann.
Der Vorteil dabei ist, dass die Anwendung ohne mod_rewrite
funktioniert.
Du klammerst dich an diesen winzigen Vorteil, als würde sonst die Welt untergehen. Toll, die Anwendung funktioniert ohne mod_rewrite! Du übersiehst dabei:
Die Anwendung funktioniert nicht ohne PHP, nicht ohne MySQL, und nicht ohne Webserver.
Kein mod_rewrite zu haben dürfte bei der Dichte von Apache-Webservern, die man im PHP/MySQL-Umfeld antrifft, keinerlei Relevanz haben.
Ich danke Dir für Deine Empfehlung aber ich kann mir nicht
vorstellen, dass sie für meine Anwendung unter all diesen
Aspekten noch richtig ist (ausser die 400 Rules sind
wirklich problematisch)... und ich bin vor Allem gespannt
auf Deine Meinung.
Meine Meinung ist, dass du derzeit unnötig Server-Ressourcen und User-Zeit verbrätst und dich damit entschuldigst, dass du dich nicht von einer Komponente abhängig machen willst, die auf 100% der relevanten Webserverangebote vorhanden ist, dabei aber übersiehst, dass du sowieso von Komponenten abhängig bist, die zwingend vorhanden sein müssen.
Methode 3 ist die saubere Vorgehensweise. URLs sollen sich über die Lebensdauer eines Dokuments sowieso nicht ändern, eine Verknüpfung von Titel und URL wäre also aus diesem Aspekt ohnehin unzulässig. Abgesehen von dem enormen Overhead, den das beständige Pflegen der Rewrite-Rules erfordert.
- Sven Rautenberg
Moin,
eines vorab:
------------
Wenn es so klingt, als klammere ich mich an den Vorteil,
von mod_rewrite unabhängig zu sein, ist ein falscher Eidruck entstanden.
Ich bin grundsätzlich sehr dankbar für Deinen Vorschlag,
muss nur abwägen, in wie weit er für mich in der jetzigen
Situation umsetzbar und welche Vorteile diese Umsetzung
dann noch hat. Ich streite dabei bestimmt keine etwaige
Fehlplanung meinerseits ab ...
... aber mir ist noch eine Alternative eingefallen, mit der
sich das ganze relativ einfach lösen liesse und die m.E. die
meisten Server-Recourcen sparen würde:
-----------------------------------------------------------------
Wenn die URLs nach folgendem Muster gestaltet wären:
statt:
"/Impressum/" -> "/Impressum/?site_id=138
und statt:
^Impressum/$ /_content/?site_id=138&%{QUERY_STRING}
->^.+/$ /_content/?%{QUERY_STRING}
(ich weiss nicht genau, wie der reguläre Ausdruck in dem Fall
genau aussehen müsste, aber er soll heissen "alles an die selbe
Adresse)
das hiesse:
a) es ist keine Umleitung per header() nötig.
b) es wird kein Script gebraucht, dass die
Zuordnung site_id/url ermittelt.
c) die Rewrite-Rule ist eine einzige.
c) die Links würden immer passen auch wenn sie sich ändern.
------------------------------------------------------------------
Einziger Nachteil:
------------------
Die URL ist nicht ganz so schön ;) Es wäre zu überlegen, ob
man aus "/Impressum/?site_id=138" "/Impressum/138.htm" macht.
Aber ob das soviel schöner ist ?
Was sagst Du dazu ?
beste gruesse,
martin
Hi,
Es wäre zu überlegen, ob
man aus "/Impressum/?site_id=138" "/Impressum/138.htm" macht.
Aber ob das soviel schöner ist ?
nö, ist es nicht. Warum nicht einfach /?Impressum ?
Das ist einprägsam, leicht zu tippen und erfordert auch kein mod_rewrite.
Deinem Script ja wie schon bemerkt jede URL zu jeder ID bekannt und bei entsprechender Datenhaltung kann die Anforderung sehr schnell umgesetzt werden.
Übrigens kann eine solche Lösung auch ohne Datenbank auskommen und noch effizienter sein: wenn nämlich die Daten in gleichlautende Dateien gespeichert werden.
freundliche Grüße
Ingo