Apache / ErrorDocument / LogFiles
Harry
- webserver
Holladiewaldfee,
wie schon öfters mal angeführt arbeite ich zur Zeit an einem CM-
System mit allerlei Schnickschnack. Ich würde ja gerne den Thread
verlinken, wo ich das schonmal alles erklärt habe, find ihn aber ums
Verrecken nicht mehr. Ist aber auch nicht so wichtig.
Als Server verwende ich Apache2.
Eines der Module in meinem Framework ist dafür zuständig, blöde URLs
wie z.B. bla.php?module=news&id=42&unwichtiges=zeug in "merkbare"
und "suchmaschinenverträgliche" umzuwandeln, also /news/42.
Da das ganze dynamisch gehen muß, möchte ich (auch aus
Portierungsgründen) nur ungerne mod_rewrite verwenden. Stattdessen
habe ich eine htaccess-Datei erstellt mit
ErrorDocument 404 /index.php?action=rewrite
Soll heißen: Immer wenn eine Seite nicht gefunden wird versucht das
rewrite-Modul die URL so umzuschreiben, daß was (aus Sicht des
Scriptes) sinnvolles rauskommt.
Beispiel:
Ein User fordert /news/43 an.
Apache stellt fest, daß das Verzeichnis nicht existiert und ruft
index.php?action=rewrite auf. Die PHP Seite isoliert den Querystring
aus $_SERVER['REDIRECT_QUERY_STRING'] und den ursprünglichen Pfad
aus $_SERVER['REDIRECT_URL'] und versucht, was sinnvolles draus zu
basteln. Anschliessend schaut sie in einer Datenbank nach, ob diesem
neuen String eine Seite zugeordnet ist.
Wenn nein wird eine Fehlermeldung ausgegeben und der Käse ist
gegessen.
Wenn ja schicke ich ein "HTTP/1.0 200 Ok" hinterher und gebe die
richtige Seite aus. Das Problem ist aber: Der Apache lässt sich
durch den zusätzlichen Header nicht beeindrucken und müllt mir
fröhlich mein LogFile zu.
Wie also bringe ich den Apachen dazu, wenn ein 200er-Header gesendet
wurde, keinen Eintrag ins LogFile zu schreiben?
Mir ist vollkommen klar, daß ich damit die Fehlerbehandlung des
Apachen mißbrauche und damit etwas anstelle, für das sie nie gedacht
war. Gibt es vielleicht noch einen anderen Weg (außer mod_rewrite),
auf dem ich das Geschilderte verwirklichen kann? Oder renne ich
dauernd mit dem Kopf an die Wand am Ende der Einbahnstraße?
Vielen Dank schonmal.
Ciao,
Harry
hi Harry ;-)
Als Server verwende ich Apache2.
Genauer bitte, und auch die Plattform angeben ...
Wenn nein wird eine Fehlermeldung ausgegeben und der Käse ist gegessen.
Wenn ja schicke ich ein "HTTP/1.0 200 Ok" hinterher und gebe die richtige Seite aus.
Das Problem ist aber: Der Apache lässt sich durch den zusätzlichen Header nicht beeindrucken und müllt mir fröhlich mein LogFile zu.
Glaub mir: so "fröhlich" ist er dabei gar nicht.
Wie also bringe ich den Apachen dazu, wenn ein 200er-Header gesendet
wurde, keinen Eintrag ins LogFile zu schreiben?
Indem du ihm sagst, was er überhaupt und wie ins log schreiben soll? Wie hast du denn bisher deine logfiles in der httpd.conf konfiguriert?
Mir ist vollkommen klar, daß ich damit die Fehlerbehandlung des Apachen mißbrauche
Tut mir leid, wenn ich dir diese Klarheit wieder zumüllen/vernebeln/eintrüben muß. Gerade Apache 2.0.x sieht ziemlich konsequent vor, daß du logfiles und Error-Meldungen selber konfigurieren solltest/kannst/darfst.
Grüße aus Berlin
Christoph S.
Holladiewaldfee,
Als Server verwende ich Apache2.
Genauer bitte, und auch die Plattform angeben ...
Man FreeBSD, mal Linux, mal WinXP ... ;-)
Apache 2.0.46.
Sollte wenn möglich aber auch mit 1.3.2x laufen.
Glaub mir: so "fröhlich" ist er dabei gar nicht.
Och .. ich dachte ich mach ihm eine Freude, wenn er auch mal was
sagen darf ;-)
Indem du ihm sagst, was er überhaupt und wie ins log schreiben
soll? Wie hast du denn bisher deine logfiles in der httpd.conf
konfiguriert?
Default. Prinzipell hat das ja auch nichts zu sagen, wenn, dann
sollte sich die Sache über eine htaccess-Datei regeln lassen, ganz
einfach aus dem Grund, daß nicht jeder, der das System nachher
einsetzt (ich selbst eingeschlossen) auf dem Server, auf dem er es
einsetzt, das Recht hat, in der httpd.conf rumzufummeln. Zu
einem "AllowOverride FileInfo" lassen sich die meisten Admins dann
ja grade noch überreden, aber zu "Änder mal bitte was am Log-
Verhalten des Apachen" dann eher weniger.
Mir ist vollkommen klar, daß ich damit die Fehlerbehandlung
des Apachen mißbrauche
Tut mir leid, wenn ich dir diese Klarheit wieder
zumüllen/vernebeln/eintrüben muß. Gerade Apache 2.0.x sieht
ziemlich konsequent vor, daß du logfiles und Error-Meldungen
selber konfigurieren solltest/kannst/darfst.
Schon klar (oder auch nicht).
Das Problem ist: Der Apache sieht einen 404er und lässt dann auf
Grund der ErrorDocument-Direktive meine PHP-Seite dran
rumfuhrwerken. Die aber akzeptiert entweder den Fehler oder eben
nicht. Wenn sie ihn nicht akzeptiert, weil sie es besser weiß,
schickt sie einen 200er-Header los.
Das Problem ist, daß der Apache in beiden Fällen einen Eintrag ins
LogFile macht. Wenn der 200er Header aber geschickt wurde soll er
eben das _nicht_ tun, da ja dann eigentlich kein Fehler vorlag.
Also (graphisch):
User Request: /news/42
Apache: 404
Apache: htaccess => ErrorDocument index.php
index.php: Umschreiben in module=news&id=42
index.php: Anfrage an DB: Existiert Seite, die
module=news&id=42 erwartet?
(1) Ja
index.php: 200 Ok
index.php: Angeforderte Seite abarbeiten
Apache: Eintrag LogFile: 404 NotFound /news/42 (*)
(2) Nein
index.php: Fehlerseite ausgeben
Apache: Eintrag LogFile: 404 NotFound /news/42
Der Fehler liegt bei (*): Eben diese Zeile soll _nicht_ ausgeführt
werden!
Ciao,
Harry
Wenn ich das richtig einschätze, dann schreibt der Apache den 404er schons ins Log-File, wenn die erste Anforderung kommt (also, wenn er auf index.php umleitet). Das kannst du wohl kaum beeinflussen, ausser, wenn du das Fehler-Logging ganz ausschaltest...
mfg
Michael
Holladiewaldfee,
Wenn ich das richtig einschätze, dann schreibt der Apache den
404er schons ins Log-File, wenn die erste Anforderung kommt (also,
wenn er auf index.php umleitet). Das kannst du wohl kaum
beeinflussen, ausser, wenn du das Fehler-Logging ganz ausschaltest...
Gnargh.
Gut, angenommen, ich schalte den Käse ganz aus.
Kann ich ihn dann dazu bewegen, doch noch einen Eintrag zu schreiben?
Die einzige Methode, die mir dabei einfällt, ist in einem tieferen
Verzeichnis die Fehlerbehandlung wieder zu aktivieren und dann dort
einen (ähnlichen) 404er zu provozieren.
Das ist aber nicht wirklich elegant, sondern eher eine
Notbehelfslösung.
Mit den Apache-Funktionen von PHP wird sich da wohl auch nix machen
lassen (http://de3.php.net/manual/de/ref.apache.php).
Also bliebe nur, ein anderes Konzept zu verwenden, d.h. Weg vom
404er, hin zu ... (bitte nicht mod_rewrite)
Leider bin ich nicht so der Apache-Konfigurations-Überflieger, so
daß ich nicht alle Möglichkeiten kenne, die es hier geben könnte.
Ciao,
Harry
jep.. denke auch, dass es anders gehen muss..
es gibt da (soweit ich mich erinnern mag) eine Funktion des Apache die so weit in der Verzeichnisstruktur zurückgeht, bis sie eine index.php (oder andere Start-Datei) findet...
aber wie die jetzt wieder heisst....
werde mal kurz suchen gehen...
Holladiewaldfee,
werde mal kurz suchen gehen...
Danke. Hat aber Zeit bis morgen ;-)
Oder übermorgen. Oder irgendwann anders :)
Hauptsache nicht "nie".
Ciao,
Harry
Hab das Teil nicht mehr gefunden....
aber hier im Forum wurde es vor rel. kurzer Zeit diskutiert.. hat also sicher Leute hier, die wissen wie es heisst...
http://httpd.apache.org/docs/mod/directives.html. index-Datei -> "DirectoryIndex"
Thx aber das ist nicht das was ich gesucht habe...
es geht darum, dass sich der Apache selbst "nach oben" kämpft bis er eine index-Datei findet
Hi Harry,
Gut, angenommen, ich schalte den Käse ganz aus.
und verzichtest auf sämtliche Warnmechanismen, die Dir sagen würden, daß Dein Webserver in Schwierigkeiten geraten ist? Das willst Du doch nicht ernsthaft tun.
Die einzige Methode, die mir dabei einfällt, ist in einem tieferen
Verzeichnis die Fehlerbehandlung wieder zu aktivieren und dann dort
einen (ähnlichen) 404er zu provozieren.
Die einzige Methode, die mir einfällt, ist, gar keinen 404er zu produzieren.
Also bliebe nur, ein anderes Konzept zu verwenden, d.h. Weg vom
404er, hin zu ... (bitte nicht mod_rewrite)
Und warum nicht? Das, was Du bisher machst, ist genauso Apache-proprietär.
Viele Grüße
Michael
Holladiewaldfee,
Hi Harry,
Gut, angenommen, ich schalte den Käse ganz aus.
und verzichtest auf sämtliche Warnmechanismen, die Dir sagen
würden, daß Dein Webserver in Schwierigkeiten geraten ist? Das
willst Du doch nicht ernsthaft tun.
Ja, stimmt, war'ne Schmarn-Idee. Ich hatte aber ja nie vor, das
komplette Error-Logging auszuschalten sondern nur die 404er für ein
bestimmtes Verzeichnis. Wäre dann doch ein echte 404er aufgetreten,
hätte das PHP-Script ja einen Log-Eintrag gemacht (ja, ich weiß, das
PHP-Script ist auch ein Schwachstelle).
Die einzige Methode, die mir einfällt, ist, gar keinen 404er zu
produzieren.
Würde ich ja gerne.
Ich weiß aber nicht wie. Ich könnte höchstens irgendein Script als
Directory-Handler einspannen. Allerdings wäre ich dann halt damit
geschlagen, jedesmal ein zusätzliches Unterverzeichnis angeben zu
müssen (also domain.de/cms.php/bla/wurscht/laber, zur Not auch
ohne ".php").
Also bliebe nur, ein anderes Konzept zu verwenden, d.h. Weg vom
404er, hin zu ... (bitte nicht mod_rewrite)Und warum nicht? Das, was Du bisher machst, ist genauso Apache-
proprietär.
Ja, aber viele Apachen haben halt kein mod_rewrite aktiviert. Und
selbst wenn, so wüsste ich nicht, wie ich mod_rewrite mit einer
Datenbank koppeln kann. Ich denke mal, ich müsste bei jeder Änderung
die komplette Datei neu schreiben. Außerdem stehen da dann mit der
Zeit ein echter Haufen Regeln drin, die abgearbeitet werden müssten,
da ich die Namen für die Weiterleitungen nur ungern an irgendwelche
Konventionen binden möchten (mal die für eine gültige URL abgesehen).
Ich bin wie schon gesagt nicht so der Apache-Konfigurations-
Überflieger. Und darunter fällt auch mod_rewrite ;-)
Ciao & Danke,
Harry
Hallo Harry,
Ja, aber viele Apachen haben halt kein mod_rewrite aktiviert. Und
selbst wenn, so wüsste ich nicht, wie ich mod_rewrite mit einer
Datenbank koppeln kann. Ich denke mal, ich müsste bei jeder Änderung
die komplette Datei neu schreiben.
Was für ein Käse verzapfst Du denn da?
Du kannst Problemlos
http://www.example.org/a/b/c/d/e/f/g/j
nach
http://www.example.org/index.php?path=a/b/c/d/e/f/g/j
umschreiben:
-----------------------------------------------------------
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI} !^index.php.*
RewriteRule ^(.*) index.php?path=$1 [L,QSA]
-----------------------------------------------------------
Damit erschlägst Du _jeden_ Pfad. Absolut _jeden_. Wenn der Besucher
http://www.example.org/alpha/beta/search?q=xyz
aufruft, dann wird daraus ganz ordentlich ein
http://www.example.org/index.php?path=alpha/beta/search&q=xyz
Probier es aus!
Viele Grüße,
Christian
Holladiewaldfee,
Was für ein Käse verzapfst Du denn da?
Käse.
http://www.example.org/a/b/c/d/e/f/g/j
nach
http://www.example.org/index.php?path=a/b/c/d/e/f/g/j
umschreiben:
Äh, ja, stimmt.
Denkfehler. Hargh. Ich muß ja nicht mod_rewrite selber an die Datenbank binden ... Ich sollte früher ins Bett gehn. Oder zumindest nicht mitten im Klausurstreß ein CMS schreiben wollen.
<insider>
[x] Dreht sich
</insider>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI} !^index.php.*
RewriteRule ^(.*) index.php?path=$1 [L,QSA]
Das ist schon klar, danke.
Mein Problem ist aber, wenn der Apache das Rewrite-Modul nicht geladen hat, ist der Ofen aus. Aber ich denke, da werde ich drüber hinwegsehen müssen, es geht wohl nicht ohne.
Damit erschlägst Du _jeden_ Pfad. Absolut _jeden_.
Das ist das Problem ;-)
Ich würde gerne dynamisch alle bereits bestehenden Dateien und Pfade ausnehmen.
Statisch könnte ich das ja (denke ich zumindest) mit !^index.php.* && !^img/.* && !^css/.* machen (vielleicht noch mit escape vor "/", probieren geht über studieren), aber dynamisch?
Naja, zur Not werde ich halt auf diese Dynamik verzichten, wenn's net anders geht.
Probier es aus!
Werd ich mal demnächst machen.
Nur noch 20 Seiten LinAlg, dann ist schluß für heute.
(He, es ist schönes Wetter, der Weiher, der Berg harrrrrrrr)
Ciao & Danke,
Harry
(dreht sich)
Hallo Harry,
Statisch könnte ich das ja (denke ich zumindest) mit !^index.php.* && !^img/.* && !^css/.* machen (vielleicht noch mit escape vor "/", probieren geht über studieren), aber dynamisch?
Warum nicht:
---------------------------------------------
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) index.php?path=$1 [L,QSA]
---------------------------------------------
Falls die Datei oder das Verzeichnis existiert, dann wird sie nicht von mod_rewrite angerührt, ansonsten wird index.php aufgerufen.
Du kannst zusätzlich noch ein
RewriteCond %{REQUEST_URI} ^/internal.*
RewriteRule ^(.*) - [F]
einbauen, damit alles unterhalb von internal/ nicht von außen zugänglich ist. Die Fehlermeldung kannst Du dann mit ErrorDocument festlegen.
Viele Grüße,
Christian
Holladiewaldfee,
Warum nicht [...]
Vielleicht sollte ich doch morgen statt Schweinsbraten mal die mod_rewrite-Doku mampfen.
Herzlichen Dank, Du hast mir echt geholfen!
Ciao,
Harry
Hallo Harry,
Vielleicht sollte ich doch morgen statt Schweinsbraten mal die
mod_rewrite-Doku mampfen.
*g*
Herzlichen Dank, Du hast mir echt geholfen!
Wobei mir auffällt, dass das /internal-Verbieten vor der anderen
Rewrite-Rule geschehen sollte, sonst kann man auf diese Weise zumindest die
Dateinamen herausfinden.
Viele Grüße,
Christian
hallo Waldfee,
Mal FreeBSD, mal Linux, mal WinXP ... ;-)
Apache 2.0.46.
Ja klar, warum frag ich auch nach :-( konnts mir ja denken.
Default. Prinzipell hat das ja auch nichts zu sagen
pah, Prinzipienreiter ...
wenn, dann sollte sich die Sache über eine htaccess-Datei regeln lassen
Richtig. Die Konfiguration für die Errormeldungen kannst du inne .htaccess schreiben, siehe http://httpd.apache.org/docs-2.0/mod/core.html#errordocument, das log-Format leider (noch) nicht.
Das Problem ist: Der Apache sieht einen 404er und lässt dann auf
Grund der ErrorDocument-Direktive meine PHP-Seite dran
rumfuhrwerken. Die aber akzeptiert entweder den Fehler oder eben
nicht. Wenn sie ihn nicht akzeptiert, weil sie es besser weiß,
schickt sie einen 200er-Header los.
So weit ist das meines Wissens tatsächlich "default".
Das Problem ist, daß der Apache in beiden Fällen einen Eintrag ins
LogFile macht.
Ähm, wirklich?
Wenn der 200er Header aber geschickt wurde soll er eben das _nicht_ tun, da ja dann eigentlich kein Fehler vorlag.
Tut er auch nicht, jedenfalls nicht "default" (und nicht bei mir). Die 200 gehört allenfalls in die access.log
Also (graphisch):
äks ...
User Request: /news/42
Apache: 404
Apache: htaccess => ErrorDocument index.php
index.php: Umschreiben in module=news&id=42
index.php: Anfrage an DB: Existiert Seite, die
module=news&id=42 erwartet?(1) Ja
index.php: 200 Ok
index.php: Angeforderte Seite abarbeiten
Apache: Eintrag LogFile: 404 NotFound /news/42 (*)
Da ist ein Denkfehler drin. Der Indianer hat ja bereits auf 404 reagiert. Daß du so gemein bist, da eine PHP-Seite zwischenzuspannen, ist ihm wurscht, und was die macht, ist ihm wohl auch wurscht. Wenn sie fertig ist, schreibt er einfach seinen Eintrag fertig, egal, was das PHP-Ding macht (ist ja möglicherweise ein neuer Prozeß).
Der Fehler liegt bei (*): Eben diese Zeile soll _nicht_ ausgeführt werden!
Jaja, ich habs kapiert, bloß dein Apache noch nicht. Es kann tatsächlich an den Einstellungen für die logfiles liegen, da müßte sich eine "Umleitung" zu einer Index-Seite (Standard-Dokument) irgendwo bei
LogFormat "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"" combined
einbauen lassen. Hab ich aber noch nie probiert. Schau mal nach, ob dein PHP-Script den "%(Referer)" oder den "%(Usewr-Agent)" (warum eigentlich den?) neu schreiben kann. Aber da fang ich auch an zu schwimmen.
Grüße aus Berlin
Christoph S.
N'Abend Harry,
Gibt es vielleicht noch einen anderen Weg (außer mod_rewrite),
auf dem ich das Geschilderte verwirklichen kann?
Die einfachste Methode wäre meiner Meinung nach, alle Zugriffe auf das Verzeichniss über ein Script laufen lassen, dass diese dann auswertet. Das müsste IMHO auch ohne mod_rewrite gehen.
Warum willst du eigentlich mod_rewrite nicht verwenden? Ich denke mal, bei anderen Servern gibt es ähnliche, wenn vielleicht auch nicht so effektive alternativen.
Oder renne ich dauernd mit dem Kopf an die Wand am Ende der Einbahnstraße?
Also das kann ich dir nicht sagen, dass must du schon selber wissen *SCNR*
Grüße Andres Freund (der übrigens auch am Entwickeln eines CMS ist. Allerdings nicht in PHP sondern in Perl)
Holladiewaldfee! ;)
Genau sowas versuche ich auch gerade zu basteln. :) Dabei wird zwar mod_rewrite verwendet aber nur um bei jeder Anfrage automatisch einen http-loader (.php) aufzurufen, also nicht für die eigentliche Umleitung. So ist man relativ flexibel.
Irgendwie gibt es da aber noch ein Problem mit der Rewrite-Regel, weil der Loader sich selbst aufruft und damit eine endlose Rekursion auslöst. Jedenfalls wenn ich im PHP-Skript mit header location weiterleite. Um die Rekursion zu umgehen, könnten Umgebungs-Var nützlich sein, die man entweder mit der Rewrite-Regel behandelt oder am Anfang des Loaders. Was auch klappen könnte, ist statt header location mit fsockopen als Client zu fungieren und die URL direkt zu laden, so dass mod_rewrite davon nix mitbekommt.
Dann gibt es noch Deine Möglichkeit mit den Error-Docs was aber das Log vollmüllt und sicher nicht im Sinne des Erfinders ist.
Ich meine kürzlich über Apache gelesen zu haben, dass wenn die in der URL angegebene Datei nicht gefunden wird, man einstellen kann, dass durch die übergeordneten Verzeichnisse gelaufen, bzw. gesucht wird. Demnach würde doch bei /loader.php/foo/bar trotzdem der loader aufgerufen werden, oder?
Viel Erfolg!
MfG
Danny