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.