Explizite Unterschiede zwischen <Directory> und <DirectoryMatch> (und anderen <* Match> -Anweisungen)

8

Vorwort

Ich bin ein Neuling in Bezug auf Webserver. Ich richte einen Apache2-Server ein und stöbere gerade in der Dokumentation.

Ich bemerkte , dass die <Directory>, <Location>und <Files>Richtlinien haben jeweils eine entsprechende <*Match>Richtlinie: <DirectoryMatch>, <LocationMatch>und <FilesMatch>jeweils. Der Unterschied an der Oberfläche ist offensichtlich genug:

  • <*Match> Direktiven nehmen einen regulären Ausdruck als Argument
  • Nicht übereinstimmende Direktiven verwenden eine einfache Zeichenfolge oder einen Glob im Shell-Stil als Argument.

Seltsamerweise kann den Nicht-Match-Direktiven auch ein regulärer Ausdruck als Argument gegeben werden, wenn ein '~' vorangestellt ist. Daher sollten die folgenden zwei Zeilen identisch sein:

# From the Apache2 docs
<Directory ~ "^/www/[0-9]{3}"> ... </Directory>
<DirectoryMatch "^/www/[0-9]{3}"> ... </DirectoryMatch>

Fragen

Ich würde gerne wissen, ob es subtile oder wichtige Unterschiede gibt, die zu beachten sind, dass die coreDokumente von Apache nicht erwähnt werden. Der <DirectoryMatch>Abschnitt erwähnt einen subtilen Unterschied:

Kompatibilität

Vor 2.3.9 galt diese Direktive implizit für Unterverzeichnisse (wie <Directory>) und konnte nicht mit dem Zeilenende-Symbol ($) übereinstimmen. In Version 2.3.9 und höher sind nur Verzeichnisse, die dem Ausdruck entsprechen, von den beigefügten Anweisungen betroffen.

Darüber hinaus würde ich gerne wissen:

  • Gibt es weitere Unterschiede zwischen den Match- und Nicht-Match-Richtlinien?
  • Welche Direktive ist vorzuziehen, wenn ein regulärer Ausdruck erforderlich ist?
  • Sind andere Informationen Ihrer Meinung nach relevant?

Anmerkungen

  • <DirectoryMatch>und <Directory "~">sind auf der gleichen Zusammenführungsebene
  • Obwohl nicht explizit erwähnt, <Directory "~">können benannte Gruppen und Rückreferenzen verwendet werden, genau wie <DirectoryMatch>.
ZeroKnight
quelle

Antworten:

2

Der Unterschied liegt im zulässigen Parametertyp:

<Directory directory-path> ... </Directory>

vs.

<DirectoryMatch regex> ... </DirectoryMatch>

DirectoryMatchist eine Obermenge, was die Funktionen betrifft, da Sie jeden Pfad als regulären Ausdruck codieren können. Das Gegenteil ist nicht der Fall.

Directory ~ist wahrscheinlich eine späte Ergänzung. Basierend auf einem im Repository gefundenen Commit (Commit 07b82419b59d1bb7ba8860b86a2d381d5d1090bc im November 1996) wurde dieser Fall in Apache 1.2 hinzugefügt

DirectoryMatch wurde dann in Apache 1.3 (Commit a318749e61fda612e883a9ea594459a4517166b8 im Juli 1997) mit einer umfangreicheren Reihe von Funktionen hinzugefügt.

In der in diesem Commit aktualisierten Dokumentation heißt es eindeutig, dass Sie die Match-Version bevorzugen sollten, wenn Sie einen regulären Ausdruck verwenden:

    &lt;Directory ~ &quot;^/www/.*/[0-9]{3}&quot;&gt;
 </pre>

-would match directories in /www/ that consisted of three numbers.<p>
+would match directories in /www/ that consisted of three numbers. In
+Apache 1.3 and later, it is reccomended to use
+<a href="#directorymatch">&lt;DirectoryMatch&gt;</a> instead.<p>

(Diese Anweisung "Es wird empfohlen, DirectoryMatch zu verwenden" wurde später in einem Commit im August 1997 entfernt.)

DirectoryMatchist immer noch überlegen, da sie Directory ~nur nach "normalen" DirectoryAnweisungen behandelt werden und DirectoryMatchSie Daten erfassen können, die Sie anschließend verwenden können.

Wenn Sie Matcheinen regulären Ausdruck verwenden, würde ich die Variante bevorzugen, da dadurch klarer wird, dass Sie einen regulären Ausdruck verwenden und keinen speziellen Fall der nicht übereinstimmenden Variante. Abgesehen von den oben genannten kleinen Unterschieden würde es jedoch keinen großen Unterschied machen.

UPDATE in der Tat wahrscheinlich keine Änderungen im Ergebnis, da der Code das gleiche tut:

static const char *dirsection(cmd_parms *cmd, void *mconfig, const char *arg)
{

...

    if (!strcmp(cmd->path, "~")) {
        cmd->path = ap_getword_conf(cmd->pool, &arg);
        if (!cmd->path)
            return "<Directory ~ > block must specify a path";
        r = ap_pregcomp(cmd->pool, cmd->path, AP_REG_EXTENDED|USE_ICASE);
        if (!r) {
            return "Regex could not be compiled";
        }
    }
    else if (thiscmd->cmd_data) { /* <DirectoryMatch> */
        r = ap_pregcomp(cmd->pool, cmd->path, AP_REG_EXTENDED|USE_ICASE);
        if (!r) {
            return "Regex could not be compiled";
        }
    }

Also genau der gleiche Anruf r = ap_pregcomp(cmd->pool, cmd->path, AP_REG_EXTENDED|USE_ICASE);in beiden Fällen.

Patrick Mevzek
quelle
2
"DirectoryMatch ist eine Obermenge" - obwohl das OP speziell vergleicht <Directory ~und <DirectoryMatchnicht <Directory. Bis Apache 2.3.9 <Directory ~war wohl die Obermenge, weil es den $Regex-Anker unterstützte, während <DirectoryMatchdies nicht der Fall war . (Dies könnte auch der Grund gewesen sein, warum die Empfehlung zur Verwendung DirectoryMatchin den früheren Dokumenten entfernt wurde?)
MrWhite
2
" DirectoryMatchist immer noch überlegen, da sie Directory ~nur nach" normalen " DirectoryAnweisungen behandelt werden und DirectoryMatchSie Daten erfassen können, die Sie anschließend verwenden können." - aber wie vom OP festgestellt, sind diese Richtlinien in beiden Punkten gleich.
MrWhite
1
Ich bin damit einverstanden, dass dies DirectoryMatchleichter zu lesen und daher vorzuziehen ist (gegenüber Directory ~). Die Dokumente geben dies zwar nicht explizit an, DirectoryMatchwerden jedoch in allen aktuellen Beispielen verwendet (z. B. auf der Seite " Konfigurationsabschnitte ") und werden Directory ~nie erwähnt. In den Dokumenten wird jedoch ausdrücklich angegeben, dass die ähnlich benannten LocationMatchund FilesMatchder entsprechenden ~Version dieser Anweisungen vorzuziehen sind .
MrWhite
@ MrWhite DirectoryMatchhat den $Anker vor Apache 2.3.9 nicht unterstützt ? Die Commits, die ich gefunden habe, beziehen sich bisher auf Apache 1.2 / 1.3.
Patrick Mevzek
1
Ja, wie vom OP angegeben (aus den 2.4-Dokumenten ), während frühe Beispiele <Directory ~sogar den End-of-String-Anker enthielten. Ja, ich sehe, dass diese Commits von 1.2 / 1.3 stammen - gutes Graben! :) Es ist auch in den Apache 1.3-Dokumenten angegeben, als DirectoryMatches eingeführt wurde. Es gab auch Änderungen in Apache 1.3 (von 1.2) hinsichtlich der Zusammenführung der Regex-Container (dh <Directory ~der gerade eingeführten <DirectoryMatch).
MrWhite
1

Gibt es weitere Unterschiede zwischen den Match- und Nicht-Match-Richtlinien?

Kein strikter Unterschied zwischen den beiden Regex-Versionen ( <Directory ~und <DirectoryMatch), aber einige Direktiven wie AllowOverrideund AllowOverrideListsind nur in einem einfachen <Directory>Container (ohne Regex) zulässig . Das schließt also sowohl <Directory ~und aus <DirectoryMatch.

Referenz:
https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride

Nur in verfügbaren <Directory>Abschnitte
AllowOverride gilt nur in <Directory>Abschnitten ohne reguläre Ausdrücke angegeben, nicht in <Location>, <DirectoryMatch>oder <Files>Abschnitte.

Herr weiß
quelle