Diferenças explícitas entre <Directory> e <DirectoryMatch> (e outras diretivas <* Match>)

8

Prefácio

Sou um neófito em relação aos servidores da web. Estou configurando um servidor Apache2 e atualmente examinando a documentação.

Notei que o <Directory>, <Location>e <Files>directivas cada um tem um correspondente <*Match>directiva: <DirectoryMatch>, <LocationMatch>e <FilesMatch>respectivamente. A diferença na superfície é aparente o suficiente:

  • <*Match> diretivas usam uma expressão regular como argumento
  • As diretivas não correspondentes consideram uma cadeia simples ou um estilo de shell como argumento.

Curiosamente, as diretivas que não são de correspondência também podem receber uma expressão regular como argumento se forem precedidas por um '~'. Assim, as duas linhas a seguir devem ser idênticas:

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

Questões

O que eu gostaria de saber é se há ou não diferenças sutis ou importantes que os coredocumentos do Apache não mencionam. A <DirectoryMatch>seção menciona uma diferença sutil:

Compatibilidade

Antes da 2.3.9 , esta diretiva aplicava-se implicitamente aos subdiretórios (como <Directory>) e não podia corresponder ao símbolo de fim de linha ($). No 2.3.9 e posterior , apenas os diretórios que correspondem à expressão são afetados pelas diretivas incluídas.

Além disso, gostaria de saber:

  • Existem outras diferenças entre as diretivas de correspondência e não de correspondência?
  • Qual diretiva é mais preferível quando uma expressão regular é necessária?
  • Alguma outra informação que considere pertinente?

Notas

  • <DirectoryMatch>e <Directory "~">estão no mesmo nível de mesclagem
  • Embora não mencionado explicitamente, <Directory "~">pode usar grupos nomeados e referências anteriores, assim como <DirectoryMatch>.
ZeroKnight
fonte

Respostas:

2

A diferença está no tipo de parâmetro permitido:

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

vs

<DirectoryMatch regex> ... </DirectoryMatch>

DirectoryMatché um superconjunto, com recursos, pois você será capaz de codificar qualquer caminho como um regex. O oposto não é verdadeiro.

Directory ~provavelmente é uma adição tardia. Com base em uma confirmação encontrada no repositório (confirmação 07b82419b59d1bb7ba8860b86a2d381d5d1090bc em novembro de 1996), este caso foi adicionado no Apache 1.2

DirectoryMatch foi adicionado ao Apache 1.3 (commit a318749e61fda612e883a9ea594459a4517166b8 em julho de 1997) com um conjunto mais rico de recursos.

E a documentação atualizada nesse commit disse claramente que você deveria favorecer a versão correspondente ao usar uma regex:

    &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>

(esta instrução "é recomendável usar o DirectoryMatch" foi removida posteriormente em um commit em agosto de 1997)

DirectoryMatchainda é superior porque Directory ~é tratado apenas após Directoryinstruções "normais" e DirectoryMatchpermite capturar dados que você pode usar posteriormente.

Quando você está usando uma regex, eu preferiria a Matchvariante, pois fica mais claro que você está usando uma expressão regular e não um caso específico da variante que não corresponde. Além das pequenas diferenças acima, isso não faria uma diferença enorme.

ATUALIZAÇÃO, na verdade, provavelmente não há alterações no resultado, pois o código faz o mesmo:

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";
        }
    }

Exatamente a mesma ligação r = ap_pregcomp(cmd->pool, cmd->path, AP_REG_EXTENDED|USE_ICASE);em ambos os casos.

Patrick Mevzek
fonte
2
"O DirectoryMatch é um superconjunto" - embora o OP esteja comparando especificamente <Directory ~e <DirectoryMatch, não <Directory. Até o Apache 2.3.9, <Directory ~era indiscutivelmente o superconjunto, porque suportava a $âncora regex, enquanto <DirectoryMatchque não. (Isso também pode ter sido por isso a recomendação de uso DirectoryMatchfoi removido nos docs anteriores?)
MrWhite
2
" DirectoryMatchainda é superior porque Directory ~é tratado apenas após Directoryinstruções " normais " e DirectoryMatchpermite capturar dados que você pode usar posteriormente." - mas, como observado pelo PO, essas diretivas são as mesmas em ambos os aspectos.
MrWhite
11
Concordo que DirectoryMatché mais fácil de ler e, portanto, preferível (acima Directory ~). Embora os documentos não declarem explicitamente isso, DirectoryMatché usado em todos os exemplos recentes (por exemplo, na página Seções de configuração ) e Directory ~nunca recebe uma menção. Os documentos, no entanto, afirmam explicitamente que os nomes semelhantes LocationMatche FilesMatchsão preferíveis à ~versão correspondente dessas diretivas.
MrWhite
@MrWhite DirectoryMatchnão suportava a $âncora antes do Apache 2.3.9? Os commits que encontrei estão relacionados ao Apache 1.2 / 1.3, até agora.
Patrick Mevzek 22/03
11
Sim, conforme declarado pelo OP (dos documentos 2.4 ), enquanto os primeiros exemplos <Directory ~inclusive incluíam a âncora de fim de cadeia. Sim, vejo que esses commits são de 1.2 / 1.3 - boa escavação! :) Também está indicado nos documentos do Apache 1.3 quando DirectoryMatchfoi introduzido. Também houve alterações no Apache 1.3 (de 1.2) com relação à forma como os contêineres regex (por exemplo, <Directory ~e os que acabamos de apresentar <DirectoryMatch) foram mesclados.
MrWhite
1

Existem outras diferenças entre as diretivas de correspondência e não de correspondência?

Não é estritamente uma diferença entre as duas versões de regex ( <Directory ~e <DirectoryMatch), mas algumas diretivas, como AllowOverridee AllowOverrideList, são permitidas apenas em um <Directory>contêiner simples (sem regex) . Então, isso exclui ambos <Directory ~e <DirectoryMatch.

Referência:
https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride

Apenas disponível em <Directory>seções
AllowOverride é válido apenas em <Directory>seções especificadas sem expressões regulares, não em <Location>, <DirectoryMatch>ou <Files>seções.

Sr. White
fonte