Scripts CGI: quando você pode retornar um documento, em vez de uma resposta HTTP?

Scripts CGI: quando você pode retornar um documento, em vez de uma resposta HTTP?

O script 1 abaixo é bash e está em https://example.com/cgi-bin/test. Produz a saída 'Em construção' quando buscada. Ecos Statuse Content-typecabeçalhos e um pouco de HTML. Se eu tentar fazer eco de 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

phpvem em 2 sabores: as versões CLI e CGI. Se você apenas executar o Script 2 a partir da linha de comando, php test2.phpoapenasa 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, faz isso de maneira um pouco 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 precisam retornar pelo menos Content-typepara o Apache (mas podem retornar mais cabeçalhos, incluindo Status). Então a resposta é queambosos scripts funcionam porque o Script 1 retorna explicitamente Content-type, enquanto a versão CGI subjacente de phpfaz o mesmo.

O script bash pode retornar o documento HTML inteiro, desde que também retorne o arquivo Content-type.

Responder1

No CGI você precisa enviar o Content-Type. PHP gera isso para você. (verifique a saída através 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 content-type;

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');

Responder2

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 exige que o programa retornetodoscabeçalhos, incluindo cabeçalhos de status, antes do conteúdo real. No HTTP, os cabeçalhos e o corpo são separados por uma única linha - portanto, o formato onde você tem

Header
Header

Content

Após os cabeçalhos, você pode incluir um documento HTML completo - ou qualquer outro tipo de dado 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.

Responder3

Você precisa incluir uma resposta de cabeçalho CGI válida, não uma resposta HTTP, se estiver chamando 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.

Há 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:

HTTP/1.x 200 OK
Transfer-Encoding: chunked
Date: Tue, 06 Dec 2021 19:58:00 GMT
Server: My_Bash_Script
Connection: close
X-Powered-By: My_Bash_Script
Pragma: public
Expires: Tue, 06 Dec 2021 20:58:00 GMT
Cache-Control: max-age=3600, public
Last-Modified: Tue, 06 Dec 2021 20:58:00 GMT
Content-Encoding: gzip
Vary: Accept-Encoding, Cookie, User-Agent
Content-Type: text/html; charset=UTF-8
 
<!DOCTYPE html>
<head><title>Under construction</title>
<body><p>Under construction.</p></body>
</html>

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:

  • Uma solicitação é feita ao Apache em uma porta TCP. Isso inclui um cabeçalho de solicitação via HTTP.
  • O Apache executa quaisquer regras (por exemplo, mod_rewrite) e lida com quaisquer conexões/handshakes SSL necessários.
  • O Apache então detecta a extensão do arquivo como PHP e chama o script PHP através do interpretador PHP.
  • O código PHP é interpretado e transformado em uma string estática (espero :-) que é retornada ao Apache e contém o código HTML.
  • O Apache então adiciona as informações do cabeçalho à página HTML, juntamente com qualquer outro processamento de saída.
  • Isso é serializado e canalizado de volta pela conexão TCP para o cliente.

Outra boa maneira de explorar os cabeçalhos é usar as ferramentas de desenvolvedor do Firefox/Chrome (pressionar F12 no Firefox os abre). Vá para a guia Rede quando 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 monitore facilmente as conversas de tráfego para saber a diferença entre o que você está enviando e que está sendo mal compreendido e a aparência de uma conversa de página html estática normal servida pelo Apache.

PS (em 2022) Se você realmente estiver executando o Apache 2.2:

informação relacionada