Começando com CGI usando C
Introdução#
Normalmente, quando se trata de programação web muito se fala sobre linguagens como PHP, Java, Javascript e Python, mas também é possível desenvolver em C ou Perl, por exemplo.
Embora seja possível desenvolver páginas dinâmicas em praticamente qualquer linguagem, em algumas delas não são tão práticas para desenvolver tal dinamismo. Usar a linguagem C traz algumas vantagens e desvantagens.
Vantagens#
-
Desempenho: Linguagens compiladas são mais rápidas do que linguagens interpretadas (já que não precisam de uma máquina virtual).
-
Consumo de memória: Por ser compilada consome menos memória, mas além disso, sem usar alocações dinâmicas e conhecendo bem o fluxo de execução, é possível determinar a quantidade de memória que será usada pelo programa.
Desvantagens#
- Produtividade: Mais especificamente em C, como esta linguagem não foi pensada para o desenvolvimento de sistemas web, não possui algumas facilidades que trazem maior produtividade, como não ter o tipo String ou ter que interpretar strings para pegar os valores.
Nota
A desvantagem quanto a interpretação de valores como strings ficará mais clara no decorrer deste artigo.
Mas antes entender o que é e como funciona o CGI, é necessário aprender um pouco sobre como funciona a web (protocolo HTTP).
Sobre páginas na Internet#
O Hypertext Transfer Protocol (HTTP) é o protocolo pelo qual a internet funciona. De modo simplificado o cliente (usuário / navegador) faz requisição a uma página e o servidores responde devolvendo a página requisitada.
Para criar uma simples página estática basta criar um arquivo com extensão .html
(por exemplo minha_pagina.html
)
Nota
Caso queira aprender a criar páginas mais elaboradas o W3 Schools é altamente indicado, possui dicas sobre HTML, CSS e Javascript.
<html>
<head>
<meta charset="UTF-8">
<title>Minha página</title>
</head>
<body>
<h1>Olá mundo!</h1>
</body>
</html>
minha_pagina.html
no navegador
Um pouco mais sobre o protocolo HTTP#
Ao acessar (fazer requisição) uma página na internet, algumas informações do lado cliente são enviadas para o servidor, como por exemplo, qual o navegador, sistema operacional, idioma, página requisitada e tipo de requisição. Para ver as informações que estão sendo enviadas quando você acessa uma página, basta aperta a tecla F12 ou clicar com o botão direito do mouse e clicar em inspecionar elemento, em seguida acessar a aba Rede (network).
Observe que a mensagem é dividida em header (cabeçalho) e body (corpo) - isso será importante lá na frente.
Uma das formas para trazer dinamismo para uma página é utilizando formulários. Os formulários utilizam dois métodos para enviar os dados.
Método GET#
Ao enviar dados usando o método GET, os valores dos campos são adicionados à URL, ou seja, os dados ficam visíveis no campo de endereço da página. Este método geralmente é usado em filtro de pesquisas.
<html>
<head>
<meta charset="UTF-8">
<title>Usando o método GET</title>
</head>
<body>
<form action="" method="get">
<input type="text" name="minhaEntrada">
<input type="submit" value="Enviar">
</form>
</body>
</html>
Método POST#
Ao enviar dados usando o método POST, os valores dos campos são colocados no corpo da mensagem. Este método geralmente é usado para enviar dados sensíveis, já que não fica exposto que nem o método GET.
<html>
<head>
<meta charset="UTF-8">
<title>Usando o método POST</title>
</head>
<body>
<form action="" method="post">
<input type="text" name="minhaEntrada">
<input type="submit" value="Enviar">
</form>
</body>
</html>
Nota
Observe os dados não aparecem mais na URL, mas sim no Form Data, que fica no corpo da requisição.
Sobre CGI#
Common Gateway Interface (CGI) é um programa no lado servidor que envia ao cliente uma página HTML. É comumente usado para receber dados de formulários, mas pode ser usado para criar qualquer tipo de página dinâmica ou não.
Nota
Observe que o cliente se comunica com se servidor, em seguida o servidor repassa as informações enviadas pelo cliente para o programa. Por fim, após o programa processar ele retorna algo (pode ser uma página ou não), e o servidor pega o retorno do programa e repassa para o cliente.
Desenvolvendo com CGI#
Agora vamos criar nossa primeira página web usando a linguagem C, mas antes de lidar com o dinamismo, vamos criar uma página estática.
#include <stdio.h>
int main() {
printf( "Content-type: text/html\n\n" );
printf( "<html>\n" );
printf( "\t<head>\n" );
printf( "\t\t<meta charset=\"UTF-8\">\n" );
printf( "\t\t<title>Minha página</title>\n" );
printf( "\t</head>\n");
printf("\t<body>\n" );
printf( "\t\t<h1>Olá mundo!</h1>\n" );
printf( "\t</body>\n");
printf("</html>\n" );
return 0;
}
Observe que colocamos a informação do cabeçalho de que tipo de mensagem estamos enviando e em seguida o HTML da página. É importante que após o cabeçalho haja a quebra de linha com dois \n
. Podemos fazer um simples teste executando o programa.
Para transmitir informações do servidor ao programa, as informações são colocadas em variáveis de ambiente e o programa (a partir deste ponto irei me referir apenas por cgi). Algumas das variáveis de ambiente são:
Variável de ambiente | Descrição |
---|---|
CONTENT_TYPE | Tipo de mídia |
CONTENT_LENGTH | Tamanho do corpo da mensagem |
QUERY_STRING | Parâmetros que estão sendo enviados via URL |
REQUEST_METHOD | Tipo de método que está sendo requisitado |
Note que o que muda de um simples programa em C é que você irá receber dados de variáveis de ambiente ao invés de uma dado que foi digitado na linha de comando. Para pegar dados das variáveis de ambiente é necessário usar a função getenv
.
#include <stdio.h>
#include <stdlib.h>
int main() {
char *string = getenv( "QUERY_STRING" );
printf( "String que estava na variável de ambiente: %s\n", string );
return 0;
}
Para testar vamos ter de criar a variável de ambiente QUERY_STRING
.
$ set QUERY_STRING=criando variavel de ambiente no Windows
$ metodo_get.cgi
String que estava na variável de ambiente: criando variavel de ambiente no Windows
$ export QUERY_STRING="criando variavel de ambiente no Linux"
$ metodo_get.cgi
String que estava na variável de ambiente: criando variavel de ambiente no Linux
Note que você acabou de aprender como receber dados que são enviados pela URL, ou seja, acaba de aprender como receber dados que foram enviados usando o método GET.
Agora para receber dados que são enviados no corpo da mensagem, usaremos a variável de ambiente CONTENT_LENGTH
para saber o tamanho do corpo da mensagem e faremos uma simples leitura do stdin
(ou como comumente conhecido, leitura do teclado).
#include <stdio.h>
#include <stdlib.h>
int main() {
char *string = getenv( "CONTENT_LENGTH" );
int tamanho = atoi( string );
char vetor[tamanho + 1];
scanf( "%s", vetor );
printf( "String lida: %s\n", vetor );
return 0;
}
Note que você acabou de aprender como receber dados que foram enviados usando o método POST, pois o neste método coloca no CONTENT_LENGTH
contém o tamanho do corpo da mensagem e o corpo da mensagem é enviado pelo stdin. Só lembre de colocar os dois \n
antes de exibir devido ao fato já citado de servir para separar o cabeçalho do corpo da mensagem.
Agora, basta criar uma página com formulário, determinar o método de envio e a url de ação; e um CGI para lidar com os dados.
<html>
<head>
<meta charset="UTF-8">
<title>Meu formulário</title>
</head>
<body>
<h1>Olá mundo!</h1>
<h1>Esse é meu formulário</h1>
<form action="cgi-bin/programa.cgi" method="post">
<input type="text" name="minhaEntrada">
<input type="submit" value="Enviar">
</form>
</body>
</html>
#include <stdio.h>
#include <stdlib.h>
int main() {
char *string = getenv( "CONTENT_LENGTH" );
int tamanho = atoi( string );
char vetor[tamanho + 1];
fgets( vetor, tamanho + 1, stdin );
printf( "Content-type: text/html\n\n" );
printf( "<html>\n" );
printf( "\t<head>\n" );
printf( "\t\t<meta charset=\"UTF-8\">\n" );
printf( "\t\t<title>Lendo dados do formulário</title>\n" );
printf( "\t</head>\n" );
printf( "\t<body>\n" );
printf( "\t\t<h1>Olá mundo!</h1>\n" );
printf( "\t\t<h1>Estou lendo: %s</h1>\n", vetor );
printf( "\t</body>\n" );
printf( "</html>\n" );
printf( "\n\n" );
return 0;
}
Observe que não foi necessária a instalação de nenhuma ferramenta adicional para fazer nossos testes (usamos apenas um compilador C), mas para exibir o CGI no navegador é necessária a instalação de um servidor Web como Apache, não expliquei esse assunto por não ser o foco do artigo.
Caso queira ver um projeto usando CGI, tem um jogo da velha que criei um tempo atrás. E se quiser algo mais elaborado, como lidar com cookies e sessões veja as dúvidas frequentes.
Dúvidas frequentes#
Para que servem as duas quebras de linhas (\n\n
) no código?
São essas quebras de linhas que separam o cabeçalho do corpo da mensagem e são de uso obrigatório. Para mais detalhes acesse a referência 4.
Para que serve o charset?
Isso indica a codificação de caracteres. É indicado utilizar UTF-8 para que não haja nenhum problema.
O método GET é seguro?
“Não”, pensando em passar dados sensíveis, como por exemplo senha ou tipo de privilégio, não é recomendado usar esse método, já que qualquer pessoa pode ver (também pessoas mal intencionadas que estejam monitorando a rede) e alterar os dados.
O método POST é seguro?
“Não”, apesar de ser melhor que o GET, por não ficar tão escancarado, ainda não garante total segurança. Os dados só não estão mais visíveis, eles estão no corpo da mensagem. Para maior segurança, será necessário usar o protocolo HTTPS, mas para estudar CGI não recomendo se preocupar com HTTPS de imediato.
O que muda de um programa qualquer escrito em C para os que utilizam CGI?
A mudança é que você também irá receber dados por meio de variáveis de ambiente.
Ao usar o método GET no envio de um formulário alguns caracteres estão estranhos, por que isso acontece?
Como os dados são colocados na URL, esses dados são codificados (URL encoding). Isso não acontece quando se usa o método POST.
Como posso criar sessão?
Você pode criar um arquivo no servidor com as credenciais dos usuários (pode ser a identificação de do computador ou usuário) e as demais informações necessárias; e no lado cliente armazenar num cookie a credencial apenas, assim toda vez que o usuário acessar a página os cookies são enviados. Recomendo a leitura das referências 6 e 7.
Como testo o CGI no navegador?
Pra isso é necessário instalar um servidor web como o Apache e colocar os arquivos numa pasta específica. Assim você pode testar na sua própria máquina. Recomendo a leitura do artigo Habilitando CGI e .sh no Apache do Debian Jessie.