Introdução a CGI com a RFC 3875

Esta é uma tradução livre, com alguns comentários sobre CGI do ponto de vista da RFC 3875. Espero que seja útil para alguém, assim como foi para mim.

[ Hits: 16.802 ]

Por: Perfil removido em 18/05/2012


RFC 3875 e Comentários de Tradução - II



Pedido do Corpo da Mensagem

Requisição de dados é acessado pelo script em um método definido em uma base por sistema. As opções mais comuns são a entrada padrão (STDIN), um descritor de arquivo ou um método para manipular arquivos.

Esta variável é fornecida se o valor de CONTENT_LENGTH, também for fornecido. O Servidor PODE sinalizar um EOF após o valor de CONTENT_LENGTH ser alcançado e o script NÃO DEVE ler além deste valor.

Métodos de Requisição

Um método de requisição, como fornecido por REQUEST_METHOD, será aplicado pelo script para escrever a resposta. O autor do script pode escolher o método que melhor se adequar a sua aplicação.

Se um script receber uma requisição por um método que não pode suportar, a requisição DEVE ser rejeitada com um erro.
  • Método GET - indica que o script deve produzir um documento baseado nos valores fornecidos nas meta-variáveis. Por convenção, GET é seguro e idempotente. Isso significa que além de produzir um documento como resposta, este script não fará mais nada.
  • Método POST - indica que o script irá produzir um documento baseado em uma ou mais variáveis presentes no corpo da requisição. O script DEVE checar o valor em CONTENT_LENGTH antes de ler o anexo e deve conferir o CONTENT_TYPE antes de processá-lo.

    * Nota de tradução: Idempotente quer dizer que múltiplas requisições ao mesmo recurso usando o método devem ter o mesmo resultado que teria uma requisição apenas.

    A título de curiosidade, idempotente é a propriedade de um número que, multiplicado por ele mesmo, tem ele mesmo como resultado (n x n = n), em termos de números reais, apenas 0 e 1 têm esta propriedade. Em termos de métodos de requisição HTTP, os métodos GET, HEAD, PUT e DELETE são idempotentes.

  • Método HEAD - Solicita ao script que faça o processamento suficiente para retornar campos de cabeçalho de resposta, sem fornecer uma mensagem-corpo. O script NÃO DEVE fornecer esta mensagem-corpo para este tipo de requisição. Se isso ocorrer o Servidor DEVE descartar esta mensagem-corpo.

Métodos Específicos do Protocolo

Um script PODE implementar qualquer método específico para um dado protocolo, como PUT e DELETE de HTTP/1.1; e DEVE checar o valor de SERVER_PROTOCOL para fazer isso. O Servidor PODE definir que alguns métodos não são apropriados ou permitidos para um script, e qualquer manipulação destes métodos irá retornar um erro ao cliente.

- O Script na Linha de Comando:

Alguns sistemas suportam um método para fornecer uma matriz (array) de cadeia de caracteres para um script CGI. Isso é usado somente nos casos de uma consulta HTTP indexada, o quê é identificado por requisições GET e HEAD com uma cadeia de consulta (URI) que não contém qualquer caractere codificado.

Nestes casos, o Servidor deve tratar a requisição como uma consulta e analisar segundo as regras:

search-string = search-word *( "+" search-word )
search-word = 1*schar
schar = unreserved | escaped | xreserved
xreserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "," | "$"


Resposta CGI

Manipulação de Resposta - O script DEVE sempre prover uma resposta não vazia, através de um método definido por sistema para enviar estes dados de volta ao Servidor. A saída padrão é sempre utiliza, a menos que definido de outro modo, como um descritor de arquivo.

O script DEVE checar a variável REQUEST_METHOD quando preparando sua resposta. O Servidor PODE implementar um Timeout para os dados serem recebidos pelo script, e se excedido este tempo, o Servidor PODE terminar a execução do script e seu processo.

Tipos de Respostas

A resposta consiste de um cabeçalho e um corpo, separados por uma linha em branco. O cabeçalho contém uma ou mais campos de cabeçalho. O corpo pode ser nulo (null).
generic-response = 1*header-field NL [ response-body ]

O script DEVE retornar uma resposta ou redirecionar o cliente para um local que possa elaborar uma resposta.
CGI-Response = document-response | local-redir-response | client-redir-response | client-redirdoc-response

O Documento Resposta

O script CGI pode retornar um documento para o usuário em um documento resposta, com um código opcional indicando o estado (status) da resposta.
document-response = Content-Type [ Status ] *other-field NL response-body

O script DEVE retornar um campo de cabeçalho do tipo Content-Type. Um cabeçalho de estado é opcional, é o estado 200 (OK) é assumido se esta omissão ocorrer.

O Servidor PODE fazer qualquer modificação apropriada na saída do script para garantir que a resposta para o cliente esteja de acordo com o protocolo.

Resposta com Redirecionamento Local

O script CGI pode retornar uma URI, ou uma consulta, para um recurso local, baseado na localização do campo cabeçalho. Isso indica que o Servidor deve reprocestar a requisição usando os recursos de redirecionamento.
local-redir-response = local-Location NL

Neste caso, o script NÃO PODE retornar qualquer outro campo de cabeçalho ou o corpo da mensagem, e o Servidor DEVE gerar a resposta como ele a teria produzido se tiveste recebido a solicitação por um URL.
scheme "://" server-name ":" server-port local-pathquery

Resposta de Redirecionamento de Cliente

O script pode retornar uma URI absoluta em um campo de cabeçalho com a localização para indicar para o cliente que ele deve reprocestar a requisição usando uma URI específica.
client-redir-response = client-Location *extension-field NL

O script DEVE não prover qualquer outro campo de cabeçalho, exceto para os campos definidos em server-defined nas extensões CGI. Para uma requisição HTTP o Servidor DEVE gerar uma resposta 302.

Resposta de Redirecionamento de Cliente com Documento

O script CGI pode retornar um caminho absoluto em uma URI, para indicar ao cliente que deve reprocessar a requisição usando este caminho. O cabeçalho de estado DEVE ser suprimido e DEVE conter um estado 302, ou PODE conter um código de extensão, ou ainda um estado válido que para o cliente significa redirecionamento.

O Servidor DEVE fazer quaisquer modificações apropriadas na saída do script para garantir que a resposta combine com as regras do protocolo.

Campos de Cabeçalho de Resposta

Os campos de cabeçalho de resposta são próprios da CGI ou são extensões para serem interpretados por um Servidor, ou campos específicos de outro protocolo para serem incluídos na resposta devolvida ao cliente.

Pelo menos, um campo CGI deve ser fornecido; cada campo CGI não DEVE aparecer mais que uma vez na resposta. A sintaxe destes campos é:
  • header-field = CGI-field | other-field
  • CGI-field = Content-Type | Location | Status
  • other-field = protocol-field | extension-field
  • protocol-field = generic-field
  • extension-field = generic-field
  • generic-field = field-name ":" [ field-value ] NL
  • field-name = token
  • field-value = *( field-content | LWSP )
  • field-content = *( token | separator | quoted-string )

Os nomes destes campos são 'case insentitive'. O valor NULL para um campo equivale a dizer que o campo não está sendo enviado. Observe que cada campo de cabeçalho é uma resposta CGI que DEVE ser definida em uma única linha; CGI/1.1 não suporta continuação de linhas.

Espaços em branco são permitidos entre os separadores " : " e o valor do campo (mas não entre o nome do campo e ":"), e também entre tokens no valor do campo.

Content-Type

O campo Content-Type configura o tipo MIME contido no corpo da mensagem, se um corpo é retornado. Se o tipo fornecido falhar, o Servidor NÃO DEVE tentar determinar o tipo correto do conteúdo.

O valor deve ser enviado sem modificações para o cliente, exceto pelas mudanças no conjunto de caracteres definidas pelo parâmetro charset. O charset padrão assumido para tipos de texto é ISO-8859-1 se o protocolo for HTTP ou US-ASCII de outro modo.

Por isso é que o script DEVE incluir a informação sobre o charset desejado.

Localização

O campo de cabeçalho localização é usado para especificar para o Servidor que o script está retornando uma referência para um documento ao invés de um documento real.

Este retorno pode ser uma URI absoluta ou local (opcionalmente com uma cadeia de consulta), indicando que o Servidor deve buscar este documento e retorná-lo ao cliente como resposta.
  • Location = local-Location | client-Location
  • client-Location = "Location:" fragment-URI NL
  • local-Location = "Location:" local-pathquery NL
  • fragment-URI = absoluteURI [ "#" fragment ]
  • fragment = *uric
  • local-pathquery = abs-path [ "?" query-string ]
  • abs-path = "/" path-segments
  • path-segments = segment *( "/" segment )
  • segment = *pchar
  • pchar = unreserved | escaped | extra
  • extra = ":" | "@" | "&" | "=" | "+" | "$" | ","

A sintaxe de uma URI absoluta é definida na RFC 2396 e 2732. Uma URI absoluta válida sempre inicia com o nome do esquema seguido por " : '' Os nomes dos esquemas sempre se iniciam por uma letra, seguido por alfanuméricos e os sinais ("+", "-" or ".").

Uma URI local e uma consulta tem um caminho absoluto, e não um caminho relativo ou nulo, e sempre se iniciam por uma barra " / ".

Estado

O campo estado de um cabeçalho contém código formado por um inteiro de três dígitos (xxx) que indica o sucesso ou não da tentativa de manipular a requisição pelo Servidor.
  • Status = "Status:" status-code SP reason-phrase NL
  • status-code = "200" | "302" | "400" | "501" | extension-code
  • extension-code = 3digit
  • reason-phrase = *TEXT

- O código de estado 200 'OK' indica o sucesso, sendo o valor assumido em caso de omissão para uma resposta documento.

- O estado 302 'Found' indica que um campo de cabeçalho localização e um corpo foram encontrados.

- O código '400' representa uma requisição inválida - 'Bad Request' - como um formato de requisição desconhecido ou faltando CONTENT_TYPE.

- O código '501' é retorndo quando um método requerido não é implementado ou não suportado pelo Servidor.

Outros códigos são encontrados na especificação HTTP ou junto a IANA. O script DEVE checar o valor de SERVER_PROTOCOL antes de usar códigos de erro HTTP/1.1.

Campos de Cabeçalho Específicos do Protocolo

O script PODE retornar qualquer outro campo de cabeçalho relacionado com as definições da mensagem e definidos pelo protocolo (HTTP/1.0 ou 1.1). Cabe ao Servidor traduzir a mensagem CGI de acordo com a sintaxe do protocolo.

Por exemplo, uma sequência para nova linha (no Unix definido como US-ASCII LF) é diferente da sequência para HTTP (US-ASCII CR seguido de LF).

O script NÃO DEVE retornar quaisquer campos de cabeçalho relacionados com a comunicação para o lado cliente da comunicação que possa afetar a capacidade do Servidor em enviar respostas. O Servidor PODE remover quaisquer cabeçalhos retornardos ao cliente. O Servidor DEVE resolver conflitos entre cabeçalhos retornardo pelo script e outros enviados por ele.

Especificações Para Sistemas UNIX e Compatíveis

Meta-Variáveis - são passadas para o script de modo idêntico as variáveis de ambiente. São acestadas pela rotina getenv().

A linha de comando - Acestada através de argc e argv como argumentos de main().

O diretório de trabalho de um script é o diretório onde ele reside.

O charset US-ASCII, excluíndo NUL, é usado para definir as meta-variáveis, campos de cabeçalhos e valores de CHAR; o texto é codificado em ISO-8859-1. PATH_TRANSLATED pode conter quaisquer valores, exceto NUL. A sequencia de nova linha (NL) é definida por um LF; Servidores também devem aceitar CR + LF como NL.

Implementação

- Recomendações para Servidores:

Embora o Servidor e o script CGI necessariamente não sejam consistentes em relação a manipulação dos caminhos URLs (URLs do cliente e dados de PATH_INFO), o desenvolvedor pode desejar impor consistência.

1. Definir quaisquer restrições sobre permissões de caminhos segmentados, em particular os segmentos não terminais nulos.

2. Definir o comportamento de " . " e " .. " em segmentos de caminhos, ou seja, se são proibidos ou tratados como segmentos comuns ou ainda interpretados de acordo com a especificação sobre URL relativa.

3. Definir qualquer limite da implementação, incluindo os limites do caminho ou o comprimento das cadeias (string) de busca, e o limite sobre o volume de campos e cabeçalhos que um Servidor irá analisar (parse).

- Recomendações para Scripts:

Se o script não tem a intenção de procestar dados através de PATH_INFO, então deve rejeitar a requisição através de 404 - Not Found if PATH_INFO is not NULL.

Se a saída para um formulário está sendo procestada, checar se o tipo CONTENT_TYPE é: "application/x-www-form-urlencoded"

Ou: "multipart/form-data"

Se o conteúdo de CONTENT_TYPE é em branco, o script pode rejeitar a requisição com um erro 415 - 'Unsupported Media Type'.

Quando estiver analisando PATH_INFO, PATH_TRANSLATED ou SCRIPT_NAME, o script deve ser cuidadoso ao evitar seguimentos (" // ") em especial (" . " e " .. ") que devem ser removidos antes de serem utilizado com uma chamada de sistema (system calls) ou devem ser rejeitados com um erro 404 - Not Found.

Quando retornando campos de cabeçalho, o script deve tentar enviar os cabeçalhos tão breve quanto possível, e deve enviá-los antes de qualquer cabeçalho da HTTP. Isso reduz o custo de memória no Servidor.

Desenvolvedores devem estar cientes que REMOTE_ADDR e REMOTE_HOST nem sempre vão identificar o verdadeiro cliente. O cliente pode ser um proxy, um gateway ou outro agente intermediário agindo em nome de um cliente real.

Considerações de Segurança

- Métodos de Segurança:

A especificação HTTP possui uma seção que discute itens de segurança e sua leitura é recomendada. Apesar da convenção dizer que GET e HEAD devem ser métodos seguros e idempotentes isso pode não ser sempre verdade. A leitura da RFC 2616 é recomendada.

- Informações Sensíveis em Campos de Cabeçalhos:

Alguns campos de cabeçalho HTTP podem eventualmente carregar informações sensíveis como uma senha, ou algo que não deve ser passado diretamente para o script.

No caso da autenticação básica, o cliente enviará um cabeçalho de autenticação contendo seu nome de login e sua senha.

O Servidor valida esta informação e por isso não deve passar a senha através de HTTP_AUTHORIZATION, sem cuidadosa análise. Isso vale também para HTTP_PROXY_AUTHORIZATION.

- Privacidade dos Dados:

Dados confidenciais em uma requisição devem ser colocados em um corpo de mensagem, como parte de uma requisição POST, e não colocados na URL ou cabeçalhos de mensagem. Em alguns sistemas, o ambiente usado para passar meta-variáveis torna estes dados visíveis aos outros processos e clientes.

Além do problema que estes dados estão expostos em Servidores, proxies e intermediários que gravam permanentemente a URL tornando-a visível para terceiros.

- Um modelo de segurança:

Para uma conexão cliente utilizando TLS, o modelo de segurança é aplicado entre o cliente e o Servidor e não entre o cliente e o script. Assim, é responsabilidade do Servidor manipular sessões TLS e a autenticação do cliente.

- Interferência do Script com o Servidor:

CGI invoca o script como um processo-filho utilizando o mesmo usuário e grupo do processo Servidor. Em nenhuma hipótese o processo-filho (script) pode interferir no processo-pai (Servidor), suas configurações, documentos ou arquivos de Log.

- Comprimento de Dados e Considerações sobre Buffers:

Esta especificação não coloca limites no comprimento do corpo da mensagem presente no script. O script não deve assumir que serão alocados buffers estáticos de qualquer tamanho para conter toda a submissão de uma só vez.

Usar buffers estáticos pode causar 'stack-smashing' ou 'stack-overflow', abrindo vulnerabilidades no sistema operacional. O script pode enfileirar grandes submissões para disco ou outra mídia que lida com buffers, e sem seguida enviar rápidas sucessões destas submissões o que resultará em negação de serviço.

Se CONTENT_LENGTH for maior que os recursos considerados no dimensionamento do Servidor, uma mensagem de erro adequada. Normalmente, 503 'Service Unavailable' (HTTP/1.0 and HTTP/1.1), 413 'Request Entity Too Large'(HTTP/1.1), e 414 'Request-URI Too Large' (HTTP/1.1).

- Procestamento Sem Estado (stateless):

É da natureza da Web a ausência de estado. Cada execução do script e os recursos que são consumidos para isso são independentes. O script nunca deve fazer quaisquer presunções sobre o contexto do agente do usuário.

O script SEMPRE deve possuir o máximo de validações possíveis em sua lógica para examinar os dados obtidos do cliente, antes de permitir que estes dados sejam utilizados para quaisquer propósitos.

- Caminhos Relativos:

O Servidor deve ser cuidadoso com o uso de " .. " em segmentos de uma URL. Estes caminhos relativos devem ser removidos ou resolvidos antes que a URL seja dividida (split) em 'script-path' e 'extra-path'.

Alternativamente, quando 'extra-path' é utilizado para encontrar PATH_TRANSLATED devem ser tomados cuidados para evitar que a resolução do caminho proporcione caminhos traduzidos fora da hierarquia desejada.

Página anterior     Próxima página

Páginas do artigo
   1. Introdução
   2. RFC 3875 e Comentários de Tradução - I
   3. RFC 3875 e Comentários de Tradução - II
   4. Acknowledgements
Outros artigos deste autor

ArchLinux, uma distro de expressão aqui no VOL

Linux prestes a ganhar novos adeptos

Compilando Kernel no CentOS 6.0

Passos essenciais para configurar sua impressora no Linux

Ubuntu - configurando dois monitores numa mesma placa de vídeo

Leitura recomendada

Programando uma Intranet com Apache, MySQL e Perl (parte 1)

Catalyst Framework Perl - Parte III

Executando os principais frameworks Perl no cPanel com CGI

Catalyst Framework Perl (parte 1)

Twittando com o Perl (parte 1)

  
Comentários
[1] Comentário enviado por surfinhu em 27/05/2012 - 13:57h

Sensacional a explicação dada. Parabéns, amigo, pela paciência e boa vontade para compartilhar o seu conhecimento!
Meus sinceros agradecimentos.

[2] Comentário enviado por tonyrecife em 27/05/2012 - 19:28h

Olá,
Gostaria de um passa-a-passo que como fazer meu PC rodar shell scripts pelo Browser.
Obrigado


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts