O script 1 abaixo é bash e está em https://example.com/cgi-bin/test
. Ele produz a saída 'Em construção' quando buscado. Ele ecoa Status
e Content-type
cabeçalhos e alguns HTML. Se eu tentar ecoar um documento HTML inteiro, o Apache apenas reclamará de um cabeçalho inválido.
O script 2 abaixo é php e está em https://example.com/cgi-bin/test2.php
. Ao contrário do script bash, este retorna um documento HTML.
Como é que o script 2 pode enviar um documento HTML inteiro, mas o script 1 não?
Roteiro 1
#!/bin/bash
cat <<'EOF'
Status: 200 OK
Content-type: text/html
<p>Under construction.</p>
EOF
Roteiro 2
<?php
print <<<EOF
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
...etc
</head>
<body>
...etc
</body>
</html>
EOF;
?>
EDITAR
php
vem em 2 sabores: as versões CLI e CGI. Se você acabou de executar o Script 2 a partir da linha de comando, php test2.php
a única saída produzida por php
é exatamente o que você vê: o documento HTML. php-cgi
é a versão CGI (instalar no Ubuntu/Deb como apt install php-cgi
). O Apache (efetivamente) executa a versão CGI (na vida real, ele faz isso de maneira ligeiramente diferente, mas com os mesmos resultados):
$ php-cgi test2.php
Content-type: text/html; charset=UTF-8
<!DOCTYPE html>
...rest of doc
Os scripts CGI devem retornar pelo menos Content-type
para o Apache (mas podem retornar mais cabeçalhos, incluindo Status
). Portanto, a resposta é que ambos os scripts funcionam porque o Script 1 retorna explicitamente Content-type
, enquanto a versão CGI oculta php
faz o mesmo.
O script bash pode retornar todo o documento HTML, desde que também retorne o arquivo Content-type
.
PHP e CGI são duas coisas diferentes neste contexto.
CGI é uma interface entre um programa - neste caso, um script bash - e o servidor web. Esta interface especifica a comunicação entre o servidor web e o programa.
Este padrão requer que o programa retorne todos os cabeçalhos, incluindo cabeçalhos de status, antes do conteúdo real. Em HTTP, os cabeçalhos e o corpo são separados por uma única linha - portanto, o formato em que você
Após os cabeçalhos, você pode incluir um documento HTML completo - ou qualquer outro tipo de dados que corresponda aos cabeçalhos enviados.
O PHP faz algumas suposições para você e, a menos que você as substitua, ele define o tipo de conteúdo, o código de status e assim por diante automaticamente.
No CGI você precisa enviar o Content-Type. O PHP o gera para você. (verifique a saída por meio de um navegador, você a verá mesmo que não a veja em seu código.
Eu tenho um CGI que fiz em C, e você realmente precisa do tipo de conteúdo;
No meu caso por exemplo;
printf("Tipo de conteúdo: text/html;charset=us-ascii\n\n");
Se você precisar alterar o cabeçalho no php, deverá chamar o cabeçalho no início do seu script.
ou seja;
header('Tipo de conteúdo: aplicativo/json');
Você precisa incluir uma resposta de cabeçalho CGI válida, não uma resposta HTTP, se chamar um script via CGI por meio do Apache. Acho que, em essência (detalhe abaixo), você precisa remover "Status: 200 OK" do seu arquivo e pode funcionar.
Existe um bom artigo do próprio Apache ( https://httpd.apache.org/docs/2.2/howto/cgi.html ) que mostra o mínimo para obter uma resposta válida.
Um exemplo de cabeçalho recebido pelo cliente pode ser o seguinte:
Mas seu CGI só precisa enviar de "Content-Type: text/html; charset=UTF-8" para baixo.
Um artigo bastante bom pode ser encontrado aqui explicando os cabeçalhos: https://code.tutsplus.com/tutorials/http-headers-for-dummies--net-8039
Com relação a um arquivo PHP servido via Apache, existem várias camadas de comunicação:
Outra boa maneira de explorar os cabeçalhos é usar o Firefox / Chrome Developer Tools (pressionar F12 no Firefox os abre). Vá para a guia Rede assim que as Ferramentas do desenvolvedor estiverem abertas e recarregue a página (Ctrl + R no Windows/Linux). Existe uma opção "Raw" onde você pode ver os dados exatos que foram enviados e recebidos.
Finalmente, se você encontrar um site, ou mesmo que seu CGI esteja sendo servido por http em vez de https, você pode instalar o Wireshark ( https://www.wireshark.org ) e monitorar facilmente as conversas de tráfego para aprender o diferencial entre o que você estão enviando que está sendo mal interpretado e como é uma conversação de página html estática normal servida pelo Apache.
PS (em 2022,) Se você realmente estiver executando o Apache 2.2: