Por que o apache retorna uma resposta 404 para um arquivo que existe?

1

Eu tenho um servidor apache cujo principal objetivo é manipular solicitações de RPC. Todas essas solicitações atingiram um URL que começa com um prefixo fixo (por exemplo, /rpc ). Eu uso uma diretiva Location para definir o manipulador para esse URL (por exemplo, <Location /rpc>...</Location> ).

Agora gostaria que este servidor também exibisse arquivos estáticos. Eu coloquei um arquivo index.html em seu DocumentRoot , mas não consigo o apache para servi-lo para mim. Em vez disso, recebo 404 respostas. O log de acesso mostra isso:

127.0.0.1 - - [18/Aug/2010:11:41:52 -0400] "GET /index.html HTTP/1.1" 404 208

O log de erros mostra isso:

[...] [error] [client 127.0.0.1] File does not exist: /www/htdocs/index.html

Esta mensagem de erro é uma mentira imunda. Eu posso copiar e colar esse caminho e executar ls /www/htdocs/index.html e ver que o arquivo realmente existe.

Coisas que tentei até agora:

  • Verificou todas as permissões no caminho completo para o arquivo: todas as pastas são 755, todos os arquivos são 644
  • Propriedade confirmada: todos os diretórios e arquivos são de propriedade do mesmo usuário que o apache está executando como
  • Defina LogLevel debug (nenhuma nova mensagem apareceu nos registros)
  • Adicionado um bloco <Location /> com uma diretiva SetHandler default-handler
  • Adicionado um bloco <Location /index.html> com uma diretiva SetHandler default-handler
  • Moveram esses dois blocos Location acima e abaixo do bloco <Location /rpc>
  • Executou dtruss e não viu o apache emitir uma única stat() durante o processamento da solicitação

Estou ficando sem ideias. O que mais devo tentar?

(Estou usando o apache 2.2.12 no Mac OS X 10.5.8 e o apache 2.2.3 no CentOS 5.4.)

    
por John Siracusa 18.08.2010 / 18:27

1 resposta

3

A resposta acabou por depender de uma informação que não está presente na minha pergunta - mas a saída dtruss deveria ter sido uma grande dica!

Eu tenho uma diretiva PerlMapToStorageHandler Apache2::Const::OK na configuração do meu apache, conforme a sugestão na documentação mod_perl . Essa é uma configuração de todo o host e impede que o apache chame ap_directory_walk() e stat() ing um monte de arquivos toda vez que receber uma solicitação. Isso é desejável quando todos os seus URIs são "virtuais" (ou seja, não correspondem a arquivos reais no disco), mas isso também significa que você não pode servir arquivos estáticos!

Minha solução foi criar uma rotina PerlMapToStorageHandler personalizada que evite as chamadas stat() de todos os arquivos, exceto o que eu quero veicular:

package MyMapToStorageHandler;

use strict;  
use Apache2::RequestRec();
use Apache2::Const -compile => qw(DECLINED OK M_TRACE);

sub handler {
    my $r = shift;

    # Fall through to the default handling for TRACE requests and requests
    # for the index.html file.
    if ($r->method_number == Apache2::Const::M_TRACE || $r->uri eq '/index.html') {
        return Apache2::Const::DECLINED;
    }

    # Skip ap_directory_walk stat() calls by just returning OK
    return Apache2::Const::OK;
}

1;

Em seguida, no meu arquivo httpd.conf , substituí minha diretiva PerlMapToStorageHandler Apache2::Const::OK existente por:

PerlLoadModule MyMapToStorageHandler
...
PerlMapToStorageHandler MyMapToStorageHandler

Isso funcionou.

    
por 18.08.2010 / 18:27