Interface de gateway comum - Common Gateway Interface

Na computação , Common Gateway Interface ( CGI ) é uma especificação de interface que permite que os servidores da web executem um programa externo, normalmente para processar solicitações do usuário.

Esses programas geralmente são escritos em uma linguagem de script e são comumente chamados de scripts CGI , mas podem incluir programas compilados.

Um caso de uso típico ocorre quando um usuário da Web envia um formulário da Web em uma página da Web que usa CGI. Os dados do formulário são enviados ao servidor da Web em uma solicitação HTTP com um URL denotando um script CGI. O servidor Web então inicia o script CGI em um novo processo de computador , passando os dados do formulário para ele. A saída do script CGI, geralmente na forma de HTML , é retornada pelo script ao servidor da Web, e o servidor a retransmite ao navegador como sua resposta à solicitação do navegador.

Desenvolvido no início dos anos 1990, CGI foi o primeiro método comum disponível que permitia que uma página da Web fosse interativa. Embora ainda em uso, o CGI é relativamente ineficiente em comparação com as tecnologias mais recentes e foi amplamente substituído por elas.

História

O logotipo CGI oficial do anúncio de especificações

Em 1993, a equipe do National Center for Supercomputing Applications (NCSA) escreveu a especificação para chamar executáveis ​​de linha de comando na lista de discussão www-talk. Os outros desenvolvedores de servidor da Web o adotaram, e ele tem sido um padrão para servidores da Web desde então. Um grupo de trabalho presidido por Ken Coar começou em novembro de 1997 para definir mais formalmente a definição NCSA de CGI. Este trabalho resultou na RFC 3875, que especificava CGI Versão 1.1. Mencionados especificamente no RFC estão os seguintes contribuidores:

Historicamente, os scripts CGI costumavam ser escritos usando a linguagem C. RFC 3875 "The Common Gateway Interface (CGI)" define parcialmente CGI usando C, ao dizer que as variáveis ​​de ambiente "são acessadas pela rotina getenv () da biblioteca C ou ambiente variável".

O nome CGI vem dos primórdios da Web, quando os webmasters queriam conectar sistemas de informação legados, como bancos de dados, a seus servidores web. O programa CGI era executado pelo servidor que fornecia um "gateway" comum entre o servidor Web e o sistema de informações legado.

Objetivo da especificação CGI

Cada servidor da Web executa o software do servidor HTTP , que responde às solicitações dos navegadores da web . Geralmente, o servidor HTTP possui um diretório (pasta) , que é designado como uma coleção de documentos - arquivos que podem ser enviados para navegadores da Web conectados a este servidor. Por exemplo, se o servidor da Web tiver o nome de domínio example.come sua coleção de documentos estiver armazenada no /usr/local/apache/htdocs/sistema de arquivos local, o servidor da Web responderá a uma solicitação http://example.com/index.htmlenviando ao navegador o arquivo (pré-escrito) /usr/local/apache/htdocs/index.html.

Para páginas construídas dinamicamente, o software do servidor pode adiar solicitações para separar programas e retransmitir os resultados para o cliente solicitante (geralmente, um navegador da Web que exibe a página para o usuário final). Nos primeiros dias da Web, esses programas eram geralmente pequenos e escritos em uma linguagem de script; portanto, eles eram conhecidos como scripts .

Esses programas geralmente requerem que algumas informações adicionais sejam especificadas com a solicitação. Por exemplo, se a Wikipedia fosse implementada como um script, uma coisa que o script precisaria saber é se o usuário está logado e, se estiver, com qual nome. O conteúdo no topo de uma página da Wikipedia depende dessas informações.

O HTTP fornece meios para os navegadores passarem essas informações ao servidor da Web, por exemplo, como parte da URL. O software do servidor deve então passar essas informações para o script de alguma forma.

Por outro lado, ao retornar, o script deve fornecer todas as informações exigidas por HTTP para uma resposta à solicitação: o status HTTP da solicitação, o conteúdo do documento (se disponível), o tipo de documento (por exemplo, HTML, PDF ou texto simples) , etc.

Inicialmente, software de servidor diferente usaria maneiras diferentes de trocar essas informações com scripts. Como resultado, não era possível escrever scripts que funcionassem sem modificações para diferentes softwares de servidor, embora as informações trocadas fossem as mesmas. Portanto, decidiu-se especificar uma forma de troca dessas informações: CGI ( Common Gateway Interface , pois define uma forma comum de interface de software de servidor com scripts). Os programas geradores de páginas da Web chamados por software de servidor que operam de acordo com a especificação CGI são conhecidos como scripts CGI .

Essa especificação foi rapidamente adotada e ainda é suportada por todos os softwares de servidor conhecidos, como Apache , IIS e (com uma extensão) servidores baseados em node.js.

Um dos primeiros usos de scripts CGI era para processar formulários. No início do HTML, os formulários HTML normalmente tinham um atributo "ação" e um botão designado como botão "enviar". Quando o botão de envio é pressionado, o URI especificado no atributo "ação" é enviado ao servidor com os dados do formulário enviados como uma string de consulta . Se a "ação" especificar um script CGI, o script CGI será executado e produzirá uma página HTML.

Usando scripts CGI

Um servidor Web permite que seu proprietário configure quais URLs devem ser tratados por quais scripts CGI.

Isso geralmente é feito marcando um novo diretório dentro da coleção de documentos como contendo scripts CGI - seu nome geralmente é cgi-bin. Por exemplo, /usr/local/apache/htdocs/cgi-binpode ser designado como um diretório CGI no servidor web. Quando um navegador da Web solicita uma URL que aponta para um arquivo dentro do diretório CGI (por exemplo, http://example.com/cgi-bin/printenv.pl/with/additional/path?and=a&query=string), então, em vez de simplesmente enviar esse arquivo ( /usr/local/apache/htdocs/cgi-bin/printenv.pl) para o navegador da Web, o servidor HTTP executa o script especificado e passa a saída do script para o navegador da web. Ou seja, tudo o que o script envia para a saída padrão é passado para o cliente Web em vez de ser mostrado na tela em uma janela de terminal.

Conforme observado acima, a especificação CGI define como as informações adicionais passadas com a solicitação são passadas para o script. Por exemplo, se uma barra e nomes de diretório adicionais forem anexados à URL imediatamente após o nome do script (neste exemplo, /with/additional/path), esse caminho será armazenado na PATH_INFO variável de ambiente antes de o script ser chamado. Se os parâmetros forem enviados ao script por meio de uma solicitação HTTP GET (um ponto de interrogação anexado ao URL, seguido por pares param = valor; no exemplo, ?and=a&query=string), esses parâmetros serão armazenados na QUERY_STRINGvariável de ambiente antes de o script ser chamado. Se os parâmetros forem enviados ao script por meio de uma solicitação HTTP POST , eles serão passados ​​para a entrada padrão do script . O script pode então ler essas variáveis ​​de ambiente ou dados da entrada padrão e se adaptar à solicitação do navegador da web.

Exemplo

O seguinte programa Perl mostra todas as variáveis ​​de ambiente passadas pelo servidor Web:

#!/usr/bin/env perl

=head1 DESCRIPTION

printenv — a CGI program that just prints its environment

=cut
print "Content-Type: text/plain\n\n";

for my $var ( sort keys %ENV ) {
    printf "%s=\"%s\"\n", $var, $ENV{$var};
}

Se um navegador da Web emitir uma solicitação para as variáveis ​​de ambiente em http://example.com/cgi-bin/printenv.pl/foo/bar?var1=value1&var2=with%20percent%20encoding, um servidor da Web do Windows 7 de 64 bits executando o cygwin retornará as seguintes informações:

COMSPEC="C:\Windows\system32\cmd.exe"
DOCUMENT_ROOT="C:/Program Files (x86)/Apache Software Foundation/Apache2.4/htdocs"
GATEWAY_INTERFACE="CGI/1.1"
HOME="/home/SYSTEM"
HTTP_ACCEPT="text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
HTTP_ACCEPT_CHARSET="ISO-8859-1,utf-8;q=0.7,*;q=0.7"
HTTP_ACCEPT_ENCODING="gzip, deflate, br"
HTTP_ACCEPT_LANGUAGE="en-us,en;q=0.5"
HTTP_CONNECTION="keep-alive"
HTTP_HOST="example.com"
HTTP_USER_AGENT="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:67.0) Gecko/20100101 Firefox/67.0"
PATH="/home/SYSTEM/bin:/bin:/cygdrive/c/progra~2/php:/cygdrive/c/windows/system32:..."
PATHEXT=".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC"
PATH_INFO="/foo/bar"
PATH_TRANSLATED="C:\Program Files (x86)\Apache Software Foundation\Apache2.4\htdocs\foo\bar"
QUERY_STRING="var1=value1&var2=with%20percent%20encoding"
REMOTE_ADDR="127.0.0.1"
REMOTE_PORT="63555"
REQUEST_METHOD="GET"
REQUEST_URI="/cgi-bin/printenv.pl/foo/bar?var1=value1&var2=with%20percent%20encoding"
SCRIPT_FILENAME="C:/Program Files (x86)/Apache Software Foundation/Apache2.4/cgi-bin/printenv.pl"
SCRIPT_NAME="/cgi-bin/printenv.pl"
SERVER_ADDR="127.0.0.1"
SERVER_ADMIN="(server admin's email address)"
SERVER_NAME="127.0.0.1"
SERVER_PORT="80"
SERVER_PROTOCOL="HTTP/1.1"
SERVER_SIGNATURE=""
SERVER_SOFTWARE="Apache/2.4.39 (Win32) PHP/7.3.7"
SYSTEMROOT="C:\Windows"
TERM="cygwin"
WINDIR="C:\Windows"

Algumas, mas não todas, essas variáveis ​​são definidas pelo padrão CGI. Alguns, como PATH_INFO, QUERY_STRINGe os que começam com HTTP_, passam informações da solicitação HTTP.

Do ambiente, pode-se ver que o navegador da Web é o Firefox rodando em um PC com Windows 7 , o servidor da Web é o Apache rodando em um sistema que emula Unix , e o script CGI é nomeado cgi-bin/printenv.pl.

O programa pode então gerar qualquer conteúdo, gravá-lo na saída padrão e o servidor da Web irá transmiti-lo ao navegador.

A seguir estão as variáveis ​​de ambiente passadas para programas CGI:

  • Variáveis ​​específicas do servidor:
  • Solicite variáveis ​​específicas:
    • SERVER_PROTOCOL: HTTP / versão .
    • SERVER_PORT: Porta TCP (decimal).
    • REQUEST_METHOD: nome do método HTTP (veja acima).
    • PATH_INFO: sufixo do caminho, se anexado ao URL após o nome do programa e uma barra.
    • PATH_TRANSLATED: caminho completo correspondente conforme suposto pelo servidor, se PATH_INFOestiver presente.
    • SCRIPT_NAME: caminho relativo ao programa, como /cgi-bin/script.cgi.
    • QUERY_STRING: a parte do URL depois ? personagem. A string de consulta pode ser composta por * pares nome = valor separados por e comercial (como var1 = val1 & var2 = val2 ...) quando usada para enviar dados de formulário transferidos por meio do método GET, conforme definido pelo aplicativo HTML / x-www-form -urlencoded .
    • REMOTE_HOST: nome do host do cliente, não definido se o servidor não executou essa pesquisa.
    • REMOTE_ADDR: Endereço IP do cliente (ponto-decimal).
    • AUTH_TYPE: tipo de identificação, se aplicável.
    • REMOTE_USERusado para certos AUTH_TYPEs.
    • REMOTE_IDENT: veja o ident , apenas se o servidor realizar tal pesquisa.
    • CONTENT_TYPE: Tipo de mídia da Internet de dados de entrada se o método PUT ou POST for usado, conforme fornecido por meio do cabeçalho HTTP.
    • CONTENT_LENGTH: da mesma forma, o tamanho dos dados de entrada (decimal, em octetos ) se fornecido via cabeçalho HTTP.
    • Variáveis passaram por agente de utilizador ( HTTP_ACCEPT, HTTP_ACCEPT_LANGUAGE, HTTP_USER_AGENT, HTTP_COOKIEe possivelmente outros) conter os valores de correspondente cabeçalhos HTTP e, por conseguinte, têm o mesmo sentido.

O programa retorna o resultado ao servidor Web na forma de saída padrão, começando com um cabeçalho e uma linha em branco .

O cabeçalho é codificado da mesma forma que um cabeçalho HTTP e deve incluir o tipo MIME do documento retornado. Os cabeçalhos, complementados pelo servidor Web, geralmente são encaminhados com a resposta de volta ao usuário.

Aqui está um programa CGI simples escrito em Python 3 junto com o HTML que lida com um problema de adição simples.

add.html:

<!DOCTYPE html>
<html>
 <body>
  <form action="add.cgi" method="POST">
   <fieldset>
     <legend>Enter two numbers to add</legend>
     <label>First Number: <input type="number" name="num1"></label><br/>
     <label>Second Number: <input type="number" name="num2"></label><br/>
   </fieldset>
   <button>Add</button>
  </form>
 </body>
</html>

add.cgi:

#!/usr/bin/env python3

import cgi, cgitb
cgitb.enable()

input_data = cgi.FieldStorage()

print('Content-Type: text/html') # HTML is following
print('')                         # Leave a blank line
print('<h1>Addition Results</h1>')
try:
    num1 = int(input_data["num1"].value)
    num2 = int(input_data["num2"].value)
except:
    print('<output>Sorry, the script cannot turn your inputs into numbers (integers).</output>')
    raise SystemExit(1)
print('<output>{0} + {1} = {2}</output>'.format(num1, num2, num1 + num2))

Este programa Python 3 CGI obtém as entradas do HTML e adiciona os dois números juntos.

Desdobramento, desenvolvimento

Um servidor da Web que oferece suporte a CGI pode ser configurado para interpretar uma URL que serve como referência para um script CGI. Uma convenção comum é ter um cgi-bin/ diretório na base da árvore de diretórios e tratar todos os arquivos executáveis ​​dentro desse diretório (e nenhum outro, por segurança) como scripts CGI. Outra convenção popular é usar extensões de nome de arquivo ; por exemplo, se os scripts CGI recebem consistentemente a extensão .cgi, o servidor da Web pode ser configurado para interpretar todos esses arquivos como scripts CGI. Embora seja conveniente e exigido por muitos scripts predefinidos, ele abre o servidor para ataques se um usuário remoto puder carregar o código executável com a extensão adequada.

No caso de HTTP PUT ou POSTs , os dados enviados pelo usuário são fornecidos ao programa por meio da entrada padrão . O servidor da Web cria um subconjunto das variáveis ​​de ambiente passadas a ele e adiciona detalhes pertinentes ao ambiente HTTP.

Usos

CGI é freqüentemente usado para processar informações de entrada do usuário e produzir a saída apropriada. Um exemplo de programa CGI é aquele que implementa um wiki . Se o agente do usuário solicitar o nome de uma entrada, o servidor Web executa o programa CGI. O programa CGI recupera a origem da página dessa entrada (se houver), transforma-a em HTML e imprime o resultado. O servidor da Web recebe a saída do programa CGI e a transmite ao agente do usuário. Então, se o agente do usuário clicar no botão "Editar página", o programa CGI preencherá um HTML textareaou outro controle de edição com o conteúdo da página. Finalmente, se o agente do usuário clicar no botão "Publicar página", o programa CGI transforma o HTML atualizado na fonte da página dessa entrada e o salva.

Segurança

Os programas CGI são executados, por padrão, no contexto de segurança do servidor da web. Quando introduzidos pela primeira vez, vários scripts de exemplo foram fornecidos com as distribuições de referência dos servidores Web NCSA, Apache e CERN para mostrar como scripts de shell ou programas C poderiam ser codificados para fazer uso do novo CGI. Um exemplo de script foi um programa CGI chamado PHF, que implementou uma lista telefônica simples.

Em comum com uma série de outros scripts no momento, este script feito uso de uma função: escape_shell_cmd(). A função deveria limpar seu argumento, que veio da entrada do usuário e então passar a entrada para o shell Unix, para ser executado no contexto de segurança do servidor Web. O script não higienizava corretamente todas as entradas e permitia que novas linhas fossem passadas para o shell, o que efetivamente permitia a execução de vários comandos. Os resultados desses comandos foram exibidos no servidor web. Se o contexto de segurança do servidor Web permitir, comandos maliciosos podem ser executados por invasores.

Este foi o primeiro exemplo difundido de um novo tipo de ataque baseado na Web , em que dados não limpos de usuários da Web podem levar à execução de código em um servidor Web. Como o código de exemplo foi instalado por padrão, os ataques foram generalizados e levaram a uma série de alertas de segurança no início de 1996.

Alternativas

Para cada solicitação HTTP recebida, um servidor Web cria um novo processo CGI para tratá-lo e destrói o processo CGI após a solicitação HTTP ter sido tratada. Criar e destruir um processo pode consumir muito mais CPU e memória do que o trabalho real de gerar a saída do processo, especialmente quando o programa CGI ainda precisa ser interpretado por uma máquina virtual. Para um grande número de solicitações HTTP, a carga de trabalho resultante pode sobrecarregar rapidamente o servidor da web.

A sobrecarga envolvida na criação e destruição do processo CGI pode ser reduzida pelas seguintes técnicas:

  • Programas CGI pré-compilados para código de máquina , por exemplo, pré-compilados de programas C ou C ++ , em vez de programas CGI interpretados por uma máquina virtual, por exemplo , programas Perl , PHP ou Python .
  • Extensões de servidor da Web, como módulos Apache (por exemplo , mod_perl , mod_php , mod_python ), plug-ins NSAPI e plug-ins ISAPI que permitem processos de aplicativos de longa execução lidando com mais de uma solicitação e hospedados no servidor Web. A Web 2.0 permite transferir dados do cliente para o servidor sem o uso de formulários HTML e sem que o usuário perceba.
  • FastCGI , SCGI e AJP, que permitem que processos de aplicativos de longa duração tratem de mais de uma solicitação hospedada externamente no servidor da web. Cada processo de aplicativo escuta em um soquete; o servidor da Web lida com uma solicitação HTTP e a envia por meio de outro protocolo (FastCGI, SCGI ou AJP) para o soquete apenas para conteúdo dinâmico, enquanto o conteúdo estático geralmente é tratado diretamente pelo servidor da Web. Essa abordagem precisa de menos processos de aplicativo, portanto, consome menos memória do que a abordagem de extensão de servidor da Web. E, ao contrário de converter um programa de aplicativo em uma extensão de servidor da Web, os programas de aplicativo FastCGI, SCGI e AJP permanecem independentes do servidor da Web.
  • Jakarta EE executa aplicativos Jakarta Servlet em um contêiner da Web para servir conteúdo dinâmico e opcionalmente conteúdo estático que substitui a sobrecarga de criação e destruição de processos com a sobrecarga muito menor de criação e destruição de encadeamentos . Ele também expõe o programador à biblioteca que vem com o Java SE, na qual a versão do Jakarta EE em uso é baseada.

A configuração ideal para qualquer aplicativo da Web depende de detalhes específicos do aplicativo, quantidade de tráfego e complexidade da transação; esses trade-offs precisam ser analisados ​​para determinar a melhor implementação para uma determinada tarefa e orçamento de tempo. As estruturas da Web oferecem uma alternativa ao uso de scripts CGI para interagir com os agentes do usuário.

Veja também

Referências

links externos