|
O objetivo desta aula é compreender
o funcionamento básico de um servidor Web, explorando suas
principais possibilidades de configuração.
Conceitos básicos
A World-Wide-Web é baseada em um relacionamento cliente/servidor,
no qual o cliente é um browser, que tem como característica
principal permitir a visualização de diversas mídias,
além do padrão básico HTML. O servidor WWW é
normalmente acessado através do protocolo HTTP, que permite o
tráfego das informações desejadas através
de uma conexão TCP.
Os recursos disponíveis na Internet são acessados através
de referências denominadas URLs - Universal Reference Locators. Uma
URL define completamente um serviço na Internet, e tem os seguintes
componentes:
protocolo: forma de comunicação usada para acessar o recurso.
Pode ser FTP, HTTP, LDAP, ...
servidor: nome da máquina que provê o serviço desejado.
domínio: complemento do nome do servidor, especificando em que rede
se encontra.
porta: porta a conectar no servidor. Pode ser omitida se for a porta default
para o serviço desejado.
caminho: localização do recurso dentro do servidor.
recurso: nome do recurso dentro do servidor.
Vejamos como são estruturadas as seguintes URLs de exemplo:
http://www.ppgia.pucpr.br:80/~maziero/index.html
ftp://ftp.ppgia.pucpr.br/pub/cnpq/lattes/ATENCAO.txt
| protocolo |
|
servidor |
domínio |
|
porta
|
caminho
|
|
recurso
|
| http |
:// |
www |
ppgia.pucpr.br
|
:
|
80
|
/~maziero
|
/
|
index.html
|
|
ftp
|
://
|
ftp
|
ppgia.pucpr.br
|
|
|
/pub/cnpq/lattes
|
/
|
ATENCAO.txt
|
O protocolo HTTP
O HTTP - HyperText Transport Protocol (versão 1.0 em
RFC1945 e versão 1.1 em RFC2616) - é um protocolo
textual bastante simples, transportado através de uma conexão TCP (default na
porta 80), que tem o
objetivo de enviar requisições a servidores, na forma de URLs "http://"
e obter respostas na forma de conteúdos especificados pelo padrão MIME. Um
exemplo típico de solicitação em HTTP é:
GET /teste.html HTTP/1.0
Host: 20.0.0.29:8081
Accept: text/html, text/plain, image/*, application/pdf, text/sgml, */*
Accept-Encoding: gzip, compress
Accept-Language: en
User-Agent: Lynx/2.8.5dev.7 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7
|
A resposta a essa solicitação poderia ser a seguinte:
HTTP/1.1 200 OK
Date: Tue, 01 Jun 2004 01:41:08 GMT
Server: Apache/2.0.40 (Red Hat Linux)
Last-Modified: Tue, 02 Apr 2002 19:49:45 GMT
ETag: "1c5e4-35-aba6c840"
Accept-Ranges: bytes
Content-Length: 53
Connection: close
Content-Type: text/html; charset=ISO-8859-1
<html>
<body>
<h1>Funcionou !</h1>
</body>
</html>
|
Os principais métodos (comandos) do protocolo HTTP são:
|
Método
|
Descrição |
| GET |
busca um objeto definido por uma URL do servidor |
| PUT |
indica que os dados no corpo da consulta devem ser
armazenados na URL especificada. |
| POST |
Cria um novo objeto ligado ao objeto especificado na URL.
Uma URL será alocada pelo servidor e retornada ao cliente.O conteúdo do novo
objeto é o corpo de dados da consulta. |
| HEAD |
Similar ao método GET, mas retorna somente o
cabeçalho da resposta do servidor |
| DELETE |
Requests that the server delete the information
corresponding to the given URL |
Os principais status de retorno de métodos HTTP são (veja a RFC 2616 para a
lista completa):
| Categoria |
descrição |
Código |
Descrição |
| 1** |
Informational |
100 |
Continue |
| |
|
101 |
Switching protocols |
| 2** |
Success |
200 |
Ok |
| |
|
201 |
Created |
| |
|
202 |
Accepted |
| |
|
203 |
Non-authoritive information |
| 3** |
Redirection |
226 |
IM used |
| |
|
300 |
Multiple choices |
| |
|
301 |
Moved permanently |
| |
|
302 |
Moved temporarily |
| 4** |
Client error |
400 |
Bad request |
| |
|
401 |
Unauthorized |
| |
|
402 |
Payment required |
| |
|
403 |
Forbidden |
| |
|
404 |
Not found |
|
|
415 |
Unsupported media type |
|
|
426 |
Upgrade Required |
| 5** |
Server error |
500 |
Internal server error |
|
|
501 |
Not implemented |
|
|
502 |
Bad gateway |
|
|
503 |
Service unavailable |
|
|
505 |
HTTP version not supported |
Os tipos MIME usados para identificar o tipo do conteúdo da resposta do servidor
seguem um padrão especificado nas RFCs 2045 a 2048. Alguns exemplos de tipos
MIME comuns são (veja uma lista mais extensa em /etc/mime.types):
|
Tipo MIME
|
Significado |
| text/plain |
arquivo de texto puro |
| text/html |
arquivo de texto em formato HTML |
| image/gif |
arquivo de imagem em formato GIF |
| image/jpeg |
arquivo de imagem em formato JPEG |
| application/pdf |
arquivo de aplicação em formato PDF |
| video/quicktime |
arquivo de vídeo em formato QuickTime |
Funcionamento básico do servidor
O servidor WWW que será usado nesta aula é o Apache,
certamente o mais utilizado atualmente no mundo inteiro. Existem diversos
outros servidores WWW para UNIX, gratuitos ou comerciais, mas nenhum tem
a base instalada do
Apache, e certamente poucos têm sua flexibilidade, desempenho e
segurança.
Ele é gratuito e está presente em quase todas as distribuições
de Linux.
O servidor Apache é executado na forma de um processo daemon
chamado "httpd", que geralmente é lançado durante o
processo de carga (boot) da máquina. O daemon mestre
cria uma série de daemons escravos (processos filhos)
para atender as requisições de páginas WWW, visando
aumentar o desempenho do sistema. Esses daemons são
executados sob a identidade de um usuário especial (normalmente
apache, httpd ou nobody), para evitar problemas de segurança.
Por essa razão, todos os arquivos acessíveis aos daemons
(páginas HTML, CGIs, imagens) devem estar com permissões
de acesso para terceiros (others).
Os principais diretórios usados pelo Apache (na distribuição
Linux RedHat) são:
- /etc/httpd/conf/httpd.conf : principal arquivo de configuração
- /etc/mime.types : tipos MIME e extensões de arquivos conhecidos
pelo servidor
- /var/log/httpd/ : arquivos de logs de acessos e erros
- /var/www/ : diretório principal das páginas locais
oferecidas pelo servidor
- /var/www/html/ : páginas default do servidor (index.html)
- /var/www/cgi-bin/ : programas executáveis no padrão
CGI
- /usr/lib/httpd/modules : módulos dinâmicos usados
pelo servidor (plugins)
- $HOME/public_html : páginas pessoais de cada usuário
A localização dos diretórios pode ser alterada editando-se
o arquivo de configuração.
Configuração básica
O principal arquivo de configuração do Apache é o /etc/httpd/conf/httpd.conf.
É um arquivo texto bastante extenso, mas muito documentado e de configuração
relativamente simples. Um dos pontos mais importantes desse arquivo é
a definição dos serviços acessíveis, que segue uma forma padrão. Eis
o exemplo de definição do diretório raiz das páginas locais:
DocumentRoot "/var/www/html"
<Directory "/var/www/html">
# Defines how this directory can be accessed by clients.
# This may also be "None", "All", or any combination of "Indexes",
# "Includes", "FollowSymLinks", "ExecCGI", or "MultiViews".
Options Indexes FollowSymLinks
# This controls which options the .htaccess files in directories can
# override. Can also be "All", or any combination of "Options", "FileInfo",
# "AuthConfig", and "Limit"
AllowOverride None
# Controls who can get stuff from this server.
Order allow,deny
Allow from all
</Directory>
|
Controle de acesso a páginas
O controle de acesso à páginas pelos clientes é feito com
base em diretórios. Além das definições presentes no arquivo de configuração
global (cláusulas order, allow e deny
dentro das definições dos
serviços), restrições de acesso podem ser definidas em arquivos separados, para cada diretório.
Para isso, deve-se criar um arquivo escondido (com nome .htaccess
por default) no diretório, contendo as definições de acessibilidade para
aquele diretório e seus sub-diretórios. Vejamos alguns exemplos:
Para controlar o acesso ao diretório baseado em hosts:
order deny,allow
deny from all
allow from .ppgia.pucpr.br
allow from 200.123.123.123
allow from 10.1
allow from 10.2.0.0/255.255.0.0
allow from 10.3.0.0/16
|
Para controlar o acesso baseado em usuários/senhas (o
arquivo de usuários/senhas deve ser criado através da aplicação htpasswd):
AuthUserFile /home/prof/maziero/passwords.txt
AuthName "Página dos usuários autorizados"
AuthType Basic
require valid-user
|
Informações mais detalhadas sobre controle de acesso no Apache podem ser
encontradas aqui.
Para ter mensagens de erro personalizadas:
ErrorDocument 404 /notfound.html
Para usar outra página default para um determinado diretório:
DirectoryIndex filename.html
Uma série de opções interessantes, incluindo o
redirecionamento automático de páginas, mirroring, etc, podem ser efetuadas
através do módulo Apache rewriting,
cuja explanação foge ao contexto deste curso.É importante ressaltar que o uso dos arquivos .htaccess
é regulado pela diretiva de configuração AllowOverride, definida para
cada diretório no arquivo de configuração principal.
Páginas WWW estáticas
As páginas WWW estáticas são documentos em formato HTML armazenados
no servidor, como esta página que você está lendo
agora. A estrutura básica de uma página HTML segue o formato
do exemplo a seguir:
<HTML>
<HEAD>
<TITLE>Este é o título desta página</TITLE>
</HEAD>
<BODY>
Este é o conteúdo da página, que pode ter diversas formatações
</BODY>
</HTML>
|
O Apache considera que um recurso designado no formato "/~usuário/caminho/recurso"
se localiza dentro do diretório pessoal ($HOME) do usuário
em questão, em um sub-diretório de informações
públicas. Por default esse diretório tem o nome "public_html",
e deve ficar dentro do diretório HOME do usuário.
As páginas estáticas podem conter imagens, sons, animações
e outros elementos. Todavia, como seu próprio nome diz, seu conteúdo
de informação é estático e sua atualização
depende de intervenção manual. Um sistema assim pode ser
considerado um sistema "two-tiers" de informação estática,
pois o servidor WWW funciona basicamente como um repositório de
informação.
A seguir veremos mecanismos que permitem gerar páginas com conteúdo
dinâmico, ou seja, que pode mudar automaticamente. Nesse caso,
o sistema passa a ser caracterizado com um sistema "three-tiers",
no qual o servidor WWW atua como um elemento intermediário
entre o cliente e o servidor de dados.
Programas CGI
O método mais antigo e simples para prover informação
dinâmica na WWW é o uso do mecanismo de programas CGI - Common
Gateway Interface. . A tecnologia CGI permite a construção
sob demanda de páginas WWW com conteúdo variável.
Ela se baseia na solicitação de execução de
um programa ou script no servidor, que irá gerar uma saída
compreensível para o browser no lado do cliente. Um programa CGI
é um arquivo instalado no servidor que, ao ser acessado por um cliente,
é executado e devolve ao cliente o resultado de sua execução.
A configuração default do servidor Apache somente permite a execução
de CGIs presentes no diretório
/var/www/cgi-bin. Essa configuração
deve ser alterada caso se deseje habilitar a execução
de CGIs em
outros diretórios, como por exemplo os diretórios $HOME
dos usuários. Todavia isso deve ser feito com
cuidado, para não criar brechas na segurança do sistema.
Um exemplo bastante simples de programa CGI (escrito em shell) está
aqui:
#!/bin/sh
echo "Content-type: text/plain"
echo ""
echo -n "Data neste servidor:"
date
|
Aqui temos outro exemplo mais elaborado, gerando como saída uma
página em HTML:
#!/bin/sh
echo "Content-type: text/html"
echo ""
echo "<HTML>"
echo "<HEAD>"
echo "<TITLE>Uma página simples em CGI shell</TITLE>"
echo "</HEAD>"
echo "<BODY>"
echo "As variáveis de ambiente estão acessíveis ao usuário:"
echo "<UL>"
echo "<LI>Bem-vindo, usuário em $REMOTE_ADDR</LI>"
echo "<LI>Você está usando o browser $HTTP_USER_AGENT</LI>"
echo "<LI>Este servidor executa em $SERVER_SOFTWARE</LI>"
echo "</UL>"
echo "Esta abordagem somente deve ser usada em páginas muito simples."
echo "</BODY>"
echo "</HTML>"
|
É possível a criação de CGIs simples com
scripts shell, ou mesmo com programas C/C++, mas essas
linguagens não se prestam à construção de
CGIs que devam retornar código HTML, pois a construção
do
mesmo via script shell ou programa C é penosa e pouco eficiente.
Para tal objetivo costumam ser usadas
linguagens apropriadas para tratamento de strings, como Perl ou Python.
Eis um exemplo de programa CGI em Perl. Ele gera uma tabela com informações
dos discos locais do servidor no instante da consulta:
#!/usr/bin/perl
# cabecalho HTTP
print "Content-type: text/html\n\n";
# inicio do documento HTML
print "<HTML>
<HEAD> <TITLE>Discos locais</TITLE> </HEAD>
<BODY>
<H1>Situação dos discos locais</H1>
";
# obtem a situação dos discos locais
@lista = `df` ;
# abertura de tabela
print "<TABLE COLS=5 BORDER=2>\n" ;
# gera entradas de tabela para as linhas
foreach $line ( @lista )
{
($fs, $bks, $used, $avail, $perc, $mount) = split ( /\s+/, $line) ;
print "<TR>
<TD>$fs</TD> <TD>$bks</TD> <TD>$used</TD> <TD>$avail</TD>
<TD>$perc</TD> <TD>$mount</TD></TR>\n";
}
# fechamento de tabela
print "</TABLE>\n";
# fim do documento HTML
print "</BODY></HTML>\n";
|
Resumindo, programas CGI são códigos executáveis lançados
pelo servidor WWW como processos separados, cujo resultado da execução
(saídas geradas em stdout) são enviadas de volta ao browser.
Páginas ativas
Outra forma de gerar conteúdo dinâmico na Web é através
do uso de páginas ativas. Neste caso, o documento HTML contém
tags especiais definindo instruções executáveis. Essas
instruções são executadas pelo servidor WWW
no momento da consulta, e o resultado é devolvido ao browser. Atualmente
as linguagens para páginas ativas em uso mais freqüentes são:
-
PHP: de domínio públio, executa em qualquer plataforma.
-
ASP: proprietária, executa sobre plataformas Windows NT.
-
JSP: baseada em Java, pode executar na maioria dos ambientes.
A discussão sobre as qualidades e defeitos dessas linguagens foge ao escopo
desta aula. Além das duas linguagens acima, existem outras possibilidades,
como Embedded Perl, Python, etc.
Um exemplo simples de página em PHP
seria o seguinte:
<HTML>
<BODY>
<?
echo "Ola usuario em $REMOTE_ADDR, tudo bem ?" ;
?>
</BODY>
</HTML>
|
O código indicado em azul é identificado por tags especiais
(<? e ?>) e executado pelo servidor ao carregar a página.
O resultado da execução, sem o código, é
retornado ao browser do cliente. Vejamos outro
exemplo mais complexo, no qual uma imagem é gerada dinamicamente:
<?
// Exemplo de criação de imagem
// aloca uma área de memória para uma imagem 100x100
$im = ImageCreate (100, 100);
// define cores para usar na imagem
$black = ImageColorAllocate ($im, 0, 0, 0) ;
$red = ImageColorAllocate ($im, 255, 0, 0) ;
$green = ImageColorAllocate ($im, 0, 255, 0) ;
$blue = ImageColorAllocate ($im, 0, 0, 255) ;
// Desenha alguns retangulos aleatorios na tela
srand ((double) microtime() * 1000000);
$x = rand (0,60) ;
$y = rand (0,60) ;
ImageRectangle ($im, $x, $y, $x+40, $y+40, $red);
$x = rand (0,60) ;
$y = rand (0,60) ;
ImageRectangle ($im, $x, $y, $x+40, $y+40, $green);
$x = rand (0,60) ;
$y = rand (0,60) ;
ImageRectangle ($im, $x, $y, $x+40, $y+40, $blue);
// cria um arquivo em disco com a imagem "teste.png"
ImagePng ($im, "exemplo.imagem.png");
// desaloca a memória utilizada para manipular a imagem
ImageDestroy ($im);
?>
<html>
<head>
<title>PHP Exemplos - Gráficos</title>
</head>
<body bgcolor = "#FFFFFF">
<img align="center" src="exemplo.imagem.png">
</body>
</html>
|
Ao invés de gerar imagens, o código PHP poderia buscar
informações em um servidor de bancos de dados. Dessa forma,
o código PHP pode ser considerado o "middle-tier" de um sistema
de informação, que mantém a lógica do negócio.
Um exemplo desse funcionamento pode ser observado no script PHP abaixo:
<HTML>
<BODY>
<?
// variáveis usadas na conexão ao DBMS
$host = "espec.ppgia.pucpr.br";
$user = "xxxxx";
$pwd = "xxxxx";
$base = "cadastro";
$table = "usuarios";
// estabelecer conexão com o DBMS
mysql_connect($host, $user, $pwd)
OR die ("Falhou no acesso ao DBMS");
// selecionar uma base de dados
mysql_select_db( "$base")
OR die( "Falhou na seleção da base");
// seleciona todos os usuários cadastrados
$query = "SELECT * FROM $table";
$result = mysql_query($query);
// quantas entradas temos no resultado ?
$number = mysql_numrows($result);
// gerar uma saida formatada
if ($number == 0) :
?>
<CENTER><P>Cadastro vazio !</CENTER>
<? else : ?>
<H3>Usuários cadastrados: <? echo $number ?></H3>
<table border=1>
<tr bgcolor="#AAAAAA">
<td>Nome</td> <td>Endereço</td> <td>Cidade</td> <td>Estado</td>
<td>E-mail</td> </tr>
<? for ($i=0; $i < $number; $i++):
$reg = mysql_fetch_array ($result) ;
?>
<tr>
<td> <? echo $reg["nome"] ?> </td> <td> <? echo $reg["ender"] ?> </td>
<td> <? echo $reg["cidade"] ?> </td> <td> <? echo $reg["estado"] ?> </td>
<td> <? echo $reg["email"] ?> </td>
</tr>
<? endfor;
?>
</table>
<? endif;
?>
</BODY>
</HTML>
|
Fontes: http://www.ppgia.pucpr.br/~maziero/ensino/svc/http/
|