Skip to content

2. Noções básicas

Neste capítulo, apresentamos os conceitos básicos da programação web. O seu objetivo principal é introduzir os princípios-chave da programação web, que são independentes da tecnologia específica utilizada para os implementar. Inclui inúmeros exemplos que o encorajamos a testar, a fim de «absorver» gradualmente a filosofia do desenvolvimento web. As ferramentas gratuitas necessárias para os testar estão listadas no final do documento, no apêndice intitulado «Ferramentas Web».

2.1. Componentes de uma aplicação Web

Servidor

Image

Máquina do cliente15

Número
Função
Exemplos comuns
1
SO do servidor
Linux, Windows
2
Servidor Web
Apache (Linux, Windows)
IIS (NT), PWS (Win9x), Cassini (Windows + plataforma .NET)
3
Scripts do lado do servidor. Podem ser executados por módulos do servidor ou por programas externos ao servidor (CGI).
PERL (Apache, IIS, PWS)
VBSCRIPT (IIS, PWS)
JAVASCRIPT (IIS, PWS)
PHP (Apache, IIS, PWS)
JAVA (Apache, IIS, PWS)
C#, VB.NET (IIS)
4
Base de dados - Pode estar na mesma máquina que o programa que a utiliza ou noutra máquina através da Internet.
Oracle (Linux, Windows)
MySQL (Linux, Windows)
Postgres (Linux, Windows)
Access (Windows)
SQL Server (Windows)
5
SO do cliente
Linux, Windows
6
Navegador Web
Netscape, Internet Explorer, Mozilla, Opera
7
Scripts do lado do cliente executados no navegador. Estes scripts não têm acesso aos discos do computador do cliente.
VBScript (IE)
JavaScript (IE, Netscape)
PerlScript (IE)
Applets Java

2.2. As trocas de dados numa aplicação web com um formulário

Image

ServidorMáquina do cliente

Número
Função
1
O navegador solicita um URL pela primeira vez (http://machine/url). Não são passados parâmetros.
2
O servidor web envia a página web para essa URL. Pode ser estática ou gerada dinamicamente por um script do lado do servidor (SA) que pode ter utilizado conteúdo de bases de dados (SB, SC). Aqui, o script irá detetar que a URL foi solicitada sem quaisquer parâmetros e irá gerar a página web inicial.
O navegador recebe a página e exibe-a (CA). Os scripts do lado do navegador (CB) podem ter modificado a página inicial enviada pelo servidor. Em seguida, através de interações entre o utilizador (CD) e os scripts (CB), a página web será modificada. Em particular, os formulários serão preenchidos.
3
O utilizador submete os dados do formulário, que são então enviados para o servidor web. O navegador recarrega a URL original ou uma diferente, conforme apropriado, e envia simultaneamente os valores do formulário para o servidor. Pode utilizar dois métodos para isso: GET e POST. Ao receber o pedido do cliente, o servidor executa o script (SA) associado à URL solicitada, que irá detetar os parâmetros e processá-los.
4
O servidor entrega a página web gerada pelo programa (SA, SB, SC). Este passo é idêntico ao anterior, o Passo 2. A comunicação prossegue agora de acordo com os Passos 2 e 3.

2.3. Notações

No que se segue, assumiremos que foram instaladas várias ferramentas e adotaremos as seguintes notações:

notação
significado
<apache>
raiz da árvore de diretórios do servidor Apache
<apache-DocumentRoot>
Diretório raiz das páginas web servidas pelo Apache. As páginas web devem estar localizadas neste diretório raiz. Assim, o URL http://localhost/page1.htm corresponde ao ficheiro <apache-DocumentRoot>\page1.htm.
<apache-cgi-bin>
Raiz da árvore de diretórios associada ao alias cgi-bin, onde podem ser colocados scripts CGI para o Apache. Assim, a URL http://localhost/cgi-bin/test1.pl corresponde ao ficheiro <apache-cgi-bin>\test1.pl.
<IIS-DocumentRoot>
O diretório raiz para páginas web servidas pelo IIS, PWS ou Cassini. As páginas web devem estar localizadas neste diretório raiz. Assim, a URL http://localhost/page1.htm corresponde ao ficheiro <IIS-DocumentRoot>\page1.htm.
<perl>
Raiz da árvore de diretórios da linguagem Perl. O executável perl.exe está normalmente localizado em <perl>\bin.
<php>
Raiz da árvore de diretórios do PHP. O executável php.exe está normalmente localizado em <php>.
<java>
Raiz da árvore de diretórios Java. Os executáveis relacionados com Java estão localizados em <java>\bin.
<tomcat>
Raiz do servidor Tomcat. Podem ser encontrados exemplos de servlets em <tomcat>\webapps\examples\servlets e exemplos de páginas JSP em <tomcat>\webapps\examples\jsp

Para cada uma destas ferramentas, consulte o apêndice, que fornece orientações de instalação.

2.4. Páginas Web estáticas, páginas Web dinâmicas

Uma página estática é representada por um ficheiro HTML. Uma página dinâmica, por outro lado, é gerada «em tempo real» pelo servidor Web. Nesta secção, apresentamos vários testes utilizando diferentes servidores Web e linguagens de programação para demonstrar a universalidade do conceito da Web. Iremos utilizar dois servidores Web: o Apache e o IIS. Embora o IIS seja um produto comercial, está disponível em duas versões mais limitadas, mas gratuitas:

  • PWS para máquinas Win9x
  • Cassini para máquinas com Windows 2000 e XP

A pasta <IIS-DocumentRoot> é normalmente a pasta [unidade:\inetpub\wwwroot], em que [unidade] é a unidade (C, D, ...) onde o IIS foi instalado. O mesmo se aplica ao PWS. No caso do Cassini, a pasta <IIS-DocumentRoot> depende da forma como o servidor foi iniciado. O apêndice mostra que o servidor Cassini pode ser iniciado numa janela do DOS (ou através de um atalho) da seguinte forma:

dos>webserver /port:N /path:"P" /vpath:"/V"

A aplicação [WebServer], também conhecida como servidor web Cassini, aceita três parâmetros:

  • /port: número da porta do serviço web. Pode ser qualquer número. O valor predefinido é 80
  • /path: caminho físico para uma pasta no disco
  • /vpath: pasta virtual associada à pasta física anterior. Note que a sintaxe não é /path=path, mas sim /vpath:path, ao contrário do que indica o painel de ajuda acima.

Se o Cassini for iniciado da seguinte forma:

dos>webserver /port:N /path:"P" /vpath:"/"

então a pasta P é a raiz da árvore de diretórios web do servidor Cassini. Esta é, portanto, a pasta designada por <IIS-DocumentRoot>. Assim, no exemplo seguinte:

dos12>webserver /path:"d:\data\devel\webmatrix" /vpath:"/"

o servidor Cassini será executado na porta 80, e a raiz do seu diretório <IIS-DocumentRoot> é a pasta [d:\data\devel\webmatrix]. As páginas web a serem testadas devem estar localizadas sob esta raiz.

A partir daqui, cada aplicação web será representada por um único ficheiro que pode ser criado utilizando qualquer editor de texto. Não é necessário qualquer IDE.

2.4.1. Página HTML estática (HyperText Markup Language)

Considere o seguinte código HTML:

<html>
  <head>
    <title>essai 1 : une page statique</title>
   </head>
   <body>
     <center>
     <h1>Une page statique...</h1>
   </body>
</html>

que produz a seguinte página web:

Os testes

Image

Teste1

  • Inicie o servidor Apache
  • Coloque o script test1.html em <apache-DocumentRoot>
  • Aceda ao URL http://localhost/essai1.html num navegador
  • Pare o servidor Apache

Teste 2

  • Inicie o servidor IIS/PWS/Cassini
  • Coloque o script test1.html em <IIS-DocumentRoot>
  • Aceda ao URL http://localhost/essai1.html num navegador

2.4.2. Uma página ASP (Active Server Pages)

O script test2.asp:

<html>
  <head>
    <title>essai 1 : une page asp</title>
   </head>
   <body>
     <center>
     <h1>Une page asp générée dynamiquement par le serveur PWS</h1>
     <h2>Il est <% =time %></h2>
     <br>
     A chaque fois que vous rafraîchissez la page, l'heure change.
   </body>
</html>

produz a seguinte página web:

Image

O teste

  • Inicie o servidor IIS/PWS
  • Coloque o script essai2.asp em <IIS-DocumentRoot>
  • Solicite o URL http://localhost/essai2.asp utilizando um navegador

2.4.3. Um script P o ERL (Practical Extracting and Reporting Language)

O script essai3.pl:

#!d:\perl\bin\perl.exe

($secondes,$minutes,$heure)=localtime(time);

print <<HTML
Content-type: text/html

<html>
  <head>
    <title>essai 1 : un script Perl</title>
   </head>
   <body>
     <center>
     <h1>Une page générée dynamiquement par un script Perl</h1>
     <h2>Il est $heure:$minutes:$secondes</h2>
     <br>
     A chaque fois que vous rafraîchissez la page, l'heure change.
   </body>
</html>

HTML
;

A primeira linha é o caminho para o executável perl.exe. Poderá ser necessário ajustá-lo, se for o caso. Uma vez executado por um servidor web, o script produz a seguinte página:

Image

O

  • Servidor web: Apache
  • Para referência, consulte o ficheiro de configuração srm.conf ou httpd.conf (dependendo da sua versão do Apache) em <apache>\confs e procure a linha que menciona cgi-bin para determinar o diretório <apache-cgi-bin> onde deve colocar o essai3.pl.
  • Coloque o script essai3.pl em <apache-cgi-bin>
  • Solicite o URL http://localhost/cgi-bin/essai3.pl

Note que a página Perl demora mais tempo a carregar do que a página ASP. Isto deve-se ao facto de o script Perl ser executado por um interpretador Perl que tem de ser carregado antes de poder executar o script. Este não permanece na memória de forma permanente.

2.4.4. Um script PHP

O script essai4.php

<html>
  <head>
    <title>essai 4 : une page php</title>
   </head>
   <body>
     <center>
     <h1>Une page PHP générée dynamiquement</h1>
     <h2>
<?
          $maintenant=time();
          echo date("j/m/y, h:i:s",$maintenant);
?>
     </h2>
     <br>
     A chaque fois que vous rafraîchissez la page, l'heure change.
   </body>
</html>

O script anterior gera a seguinte página web:

Image

Testes

Teste1

  • Verifique o ficheiro de configuração srm.conf ou o httpd.conf do Apache em <Apache>\confs
  • Para referência, verifique as linhas de configuração do PHP
  • Inicie o servidor Apache
  • Coloque o ficheiro essai4.php em <apache-DocumentRoot>
  • Aceda ao URL http://localhost/essai4.php

Teste2

  • Inicie o servidor IIS/PWS
  • Para referência, verifique a configuração do PWS relativa ao PHP
  • Coloque o ficheiro essai4.php em <IIS-DocumentRoot>\php
  • Solicitar o URL http://localhost/essai4.php

2.4.5. Um script JSP

O script heure.jsp

<%  //programme Java affichant l'heure %>

<%@ page import="java.util.*" %>

<% 
    // code JAVA pour calculer l'heure
  Calendar calendrier=Calendar.getInstance();
  int heures=calendrier.get(Calendar.HOUR_OF_DAY);
  int minutes=calendrier.get(Calendar.MINUTE);
  int secondes=calendrier.get(Calendar.SECOND);
  // heures, minutes, secondes sont des variables globales
  // qui pourront être utilisées dans le code HTML
%>

<% // code HTML %>
<html>
  <head>
     <title>Page JSP affichant l'heure</title>
  </head>
  <body>
     <center>
     <h1>Une page JSP générée dynamiquement</h1>
     <h2>Il est <%=heures%>:<%=minutes%>:<%=secondes%></h2>
     <br>
     <h3>A chaque fois que vous rechargez la page, l'heure change</h3>
  </body>
</html>

Uma vez executado pelo servidor web, este script produz a seguinte página:

Image

Os testes

  • Coloque o script heure.jsp em <tomcat>\jakarta-tomcat\webapps\examples\jsp (Tomcat 3.x) ou em <tomcat>\webapps\examples\jsp (Tomcat 4.x)
  • Inicie o servidor Tomcat
  • Aceda ao URL http://localhost:8080/examples/jsp/heure.jsp

2.4.6. Uma página ASP.NET

O script heure1.aspx:

<html>
<head>
    <title>Démo asp.net </title>
</head>
<body>
    Il est <% =Date.Now.ToString("hh:mm:ss") %>
</body>
</html>

Uma vez executado pelo servidor web, este script gera a seguinte página:

Image

Este teste requer um computador Windows no qual a plataforma .NET tenha sido instalada (ver apêndice).

  • Coloque o script heure1.aspx em <IIS-DocumentRoot>
  • Inicie o servidor IIS/CASSINI
  • Solicite o URL http://localhost/heure1.aspx

2.4.7. Conclusão

Os exemplos anteriores demonstraram que:

  • uma página HTML pode ser gerada dinamicamente por um programa. Este é o objetivo da programação web.
  • as linguagens e os servidores web utilizados podem variar. Atualmente, observam-se as seguintes tendências principais:
    • as combinações Apache/PHP (Windows, Linux) e IIS/PHP (Windows)
    • a tecnologia ASP.NET em plataformas Windows, que combina o servidor IIS com uma linguagem .NET (C#, VB.NET, etc.)
    • a tecnologia Java Servlet e páginas JSP a funcionar em vários servidores (Tomcat, Apache, IIS) e em várias plataformas (Windows, Linux).

2.5. Scripts do lado do navegador

Uma página HTML pode conter scripts que serão executados pelo navegador. Existem muitas linguagens de script do lado do navegador. Aqui estão algumas:

Linguagem
Navegadores suportados
VBScript
IE
JavaScript
IE, Netscape
PerlScript
IE
Java
IE, Netscape

Vejamos alguns exemplos.

2.5.1. Uma página web com um script VBScript, no lado do navegador

A página vbs1.html

<html>
  <head>
    <title>essai : une page web avec un script vb</title>
    <script language="vbscript">
      function reagir
        alert "Vous avez cliqué sur le bouton OK"
      end function
    </script>
   </head>

   <body>
<center>
     <h1>Une page Web avec un script VB</h1>
     <table>
       <tr>
         <td>Cliquez sur le bouton</td>
         <td><input type="button" value="OK" name="cmdOK" onclick="reagir"></td>
       </tr>
      </table>
   </body>
</html>

A página HTML acima contém não só código HTML, mas também um programa destinado a ser executado pelo navegador que carrega esta página. O código é o seguinte:

    <script language="vbscript">
      function reagir
        alert "Vous avez cliqué sur le bouton OK"
      end function
    </script>

As tags <script></script> são utilizadas para delimitar scripts dentro de uma página HTML. Estes scripts podem ser escritos em várias linguagens, e o atributo language da tag <script> especifica a linguagem utilizada. Neste caso, é VBScript. Não entraremos em detalhes sobre esta linguagem. O script acima define uma função chamada react que exibe uma mensagem. Quando é que esta função é chamada? A seguinte linha de código HTML diz-nos:

         <input type="button" value="OK" name="cmdOK" onclick="reagir">

O atributo onclick especifica o nome da função a ser chamada quando o utilizador clica no botão OK. Assim que o navegador carregar esta página e o utilizador clicar no botão OK, aparecerá a seguinte página:

Image

Testes

Apenas o Internet Explorer é capaz de executar scripts VBScript. O Netscape requer complementos para o fazer. Podemos realizar os seguintes testes:

  • Servidor Apache
  • Script vbs1.html em <apache-DocumentRoot>
  • Solicitar o URL http://localhost/vbs1.html utilizando o Internet Explorer

  • Servidor IIS/PWS

  • Script vbs1.html em <pws-DocumentRoot>
  • Solicite a URL http://localhost/vbs1.html utilizando o Internet Explorer

Uma página web com um script JavaScript, no lado do navegador

La page : js1.html

<html>
  <head>
    <title>essai 4 : une page web avec un script Javascript</title>
    <script language="javascript">
      function reagir(){
        alert ("Vous avez cliqué sur le bouton OK");
      }
    </script>
   </head>

   <body>
     <center>
     <h1>Une page Web avec un script Javascript</h1>
     <table>
       <tr>
         <td>Cliquez sur le bouton</td>
         <td><input type="button" value="OK" name="cmdOK" onclick="reagir()"></td>
       </tr>
    </table>
   </body>
</html>

Esta página é idêntica à anterior, exceto que substituímos o VBScript pelo JavaScript. O JavaScript tem a vantagem de ser suportado tanto pelo Internet Explorer como pelo Netscape. A execução deste código produz os mesmos resultados:

Image

Os testes

  • Servidor Apache
  • Script js1.html em <apache-DocumentRoot>
  • Solicite o URL http://localhost/js1.html utilizando o Internet Explorer ou o Netscape

  • Servidor IIS/PWS

  • Script js1.html em <pws-DocumentRoot>
  • Solicite a URL http://localhost/js1.html utilizando o Internet Explorer ou o Netscape

2.6. Comunicação cliente-servidor

Voltemos ao nosso diagrama inicial que ilustra os componentes de uma aplicação web:

Image

Máquina do servidor

Aqui, estamos a concentrar-nos nas trocas entre a máquina cliente e a máquina servidor. Estas ocorrem através de uma rede, e vale a pena rever a estrutura geral das trocas entre duas máquinas remotas.

2.6.1. O Modelo OSI

O modelo de rede aberta conhecido como OSI (Modelo de Referência de Interconexão de Sistemas Abertos), definido pela ISO (Organização Internacional de Normalização), descreve uma rede ideal na qual a comunicação entre máquinas pode ser representada por um modelo de sete camadas:

Image

Cada camada recebe serviços da camada abaixo dela e fornece os seus próprios serviços à camada acima dela. Suponha que duas aplicações localizadas em máquinas diferentes, A e B, queiram comunicar: fazem-no na camada de Aplicação. Não precisam de conhecer todos os detalhes de como a rede funciona: cada aplicação passa a informação que deseja transmitir para a camada abaixo dela: a camada de Apresentação. A aplicação, portanto, só precisa de conhecer as regras para interagir com a camada de Apresentação. Uma vez que a informação está na camada de Apresentação, é passada de acordo com outras regras para a camada de Sessão, e assim por diante, até que a informação chegue ao meio físico e seja fisicamente transmitida para a máquina de destino. Aí, ela passará pelo processo inverso do que passou na máquina de envio.

Em cada camada, o processo emissor responsável pelo envio da informação envia-a a um processo recetor na outra máquina pertencente à mesma camada que ele próprio. Faz-o de acordo com certas regras conhecidas como protocolo da camada. Temos, portanto, o seguinte diagrama de comunicação final:

Image

As funções das diferentes camadas são as seguintes:

Física
Assegura a transmissão de bits através de um meio físico. Esta camada inclui equipamentos terminais de processamento de dados (DPTE), tais como terminais ou computadores, bem como equipamentos de terminação de circuitos de dados (DCTE), tais como moduladores/demoduladores, multiplexadores e concentradores. Os pontos-chave a este nível são:
. a escolha da codificação da informação (analógica ou digital)
. a escolha do modo de transmissão (síncrono ou assíncrono).
Camada de Ligação de Dados
Oculta as características físicas da Camada Física. Deteta e corrige erros de transmissão.
Rede
Gere o caminho que a informação enviada pela rede deve seguir. Isto denomina-se encaminhamento: determinar a rota que a informação deve seguir para chegar ao seu destino.
Transporte
Permite a comunicação entre duas aplicações, enquanto as camadas anteriores apenas permitiam a comunicação entre máquinas. Um serviço prestado por esta camada pode ser a multiplexação: a camada de transporte pode utilizar uma única ligação de rede (de máquina para máquina) para transmitir dados pertencentes a várias aplicações.
Sessão
Esta camada fornece serviços que permitem a uma aplicação abrir e manter uma sessão de trabalho numa máquina remota.
Apresentação
O seu objetivo é padronizar a representação dos dados entre diferentes máquinas. Assim, os dados provenientes da máquina A serão «formatados» pela camada de apresentação da máquina A de acordo com um formato padrão antes de serem enviados pela rede. Ao chegarem à camada de apresentação da máquina de destino B, que os reconhecerá graças ao seu formato padrão, serão reformatados de modo a que a aplicação na máquina B os possa reconhecer.
Aplicação
Neste nível, encontramos aplicações que estão geralmente próximas do utilizador, tais como o e-mail ou a transferência de ficheiros.

2.6.2. O Modelo TCP/IP

O modelo OSI é um modelo ideal. O conjunto de protocolos TCP/IP aproxima-se dele da seguinte forma:

Image

  • a interface de rede (a placa de rede do computador) desempenha as funções das camadas 1 e 2 do modelo OSI
  • a camada IP (Protocolo de Internet) desempenha as funções da camada 3 (rede)
  • a camada TCP (Protocolo de Controlo de Transmissão) ou UDP (Protocolo de Datagrama do Utilizador) desempenha as funções da camada 4 (transporte). O protocolo TCP garante que os pacotes de dados trocados entre máquinas cheguem ao seu destino. Se isso não acontecer, reenvia os pacotes perdidos. O protocolo UDP não desempenha esta tarefa, pelo que cabe ao programador da aplicação fazê-lo. É por isso que, na Internet — que não é uma rede 100% fiável —, o protocolo TCP é o mais utilizado. A isto chama-se uma rede TCP-IP.
  • A camada de Aplicação abrange as funções das camadas 5 a 7 do modelo OSI.

As aplicações web residem na camada de Aplicação e, por isso, dependem dos protocolos TCP/IP. As camadas de Aplicação das máquinas cliente e servidor trocam mensagens, que são depois transferidas para as camadas 1 a 4 do modelo para serem encaminhadas para o seu destino. Para comunicarem entre si, as camadas de Aplicação de ambas as máquinas têm de «falar» a mesma língua ou protocolo. O protocolo utilizado pelas aplicações web denomina-se HTTP (HyperText Transfer Protocol). Trata-se de um protocolo baseado em texto, o que significa que as máquinas trocam linhas de texto através da rede para comunicarem. Estas trocas são padronizadas, o que significa que o cliente dispõe de um conjunto de mensagens para indicar ao servidor exatamente o que pretende, e o servidor também dispõe de um conjunto de mensagens para fornecer a sua resposta ao cliente. Esta troca de mensagens assume a seguinte forma:

Image

Cliente --> Servidor

Quando o cliente faz um pedido ao servidor web, envia

  1. linhas de texto no formato HTTP para indicar o que pretende
  1. uma linha vazia
  2. opcionalmente, um documento

Servidor --> Cliente

Quando o servidor responde ao cliente, envia

  1. linhas de texto no formato HTTP para indicar o que está a enviar
  2. uma linha vazia
  3. opcionalmente um documento

As comunicações seguem, portanto, o mesmo formato em ambas as direções. Em ambos os casos, pode ser enviado um documento, embora seja raro um cliente enviar um documento para o servidor. Mas o protocolo HTTP permite isso. É isso que permite, por exemplo, que os assinantes de um ISP carreguem vários documentos para o seu site pessoal hospedado por esse ISP. Os documentos trocados podem ser de qualquer tipo. Considere um navegador a solicitar uma página web contendo imagens:

  1. o navegador liga-se ao servidor web e solicita a página que deseja. Os recursos solicitados são identificados de forma única por URLs (Uniform Resource Locators). O navegador envia apenas cabeçalhos HTTP e nenhum documento.
  2. O servidor responde. Primeiro, envia cabeçalhos HTTP indicando que tipo de resposta está a enviar. Esta pode ser um erro, caso a página solicitada não exista. Se a página existir, o servidor indicará nos cabeçalhos HTTP da sua resposta que irá enviar um documento HTML (HyperText Markup Language) a seguir a eles. Este documento é uma sequência de linhas de texto em formato HTML. O texto HTML contém tags (marcadores) que fornecem ao navegador instruções sobre como apresentar o texto.
  3. O cliente sabe, a partir dos cabeçalhos HTTP do servidor, que irá receber um documento HTML. Ele irá analisar este documento e poderá perceber que este contém referências a imagens. Estas imagens não estão incluídas no documento HTML. Por isso, faz um novo pedido ao mesmo servidor web para solicitar a primeira imagem de que necessita. Este pedido é idêntico ao feito no passo 1, exceto que o recurso solicitado é diferente. O servidor processará esta solicitação enviando a imagem solicitada ao cliente. Desta vez, na sua resposta, os cabeçalhos HTTP especificarão que o documento enviado é uma imagem e não um documento HTML.
  4. O cliente recupera a imagem enviada. Os passos 3 e 4 serão repetidos até que o cliente (normalmente um navegador) tenha todos os documentos necessários para apresentar a página na íntegra.

2.6.3. O Protocolo HTTP

Vamos explorar o protocolo HTTP através de exemplos. O que é que um navegador e um servidor web trocam entre si?

2.6.3.1. A resposta de um servidor HTTP

Aqui, vamos explorar como um servidor web responde aos pedidos dos seus clientes. O serviço web ou serviço HTTP é um serviço TCP/IP que normalmente opera na porta 80. Pode operar numa porta diferente. Nesse caso, o navegador do cliente teria de especificar essa porta no URL que solicita. Um URL segue geralmente este formato:

protocole://machine[:port]/chemin/infos

onde

protocolo
http para o serviço Web. Um navegador também pode atuar como cliente para FTP, news, Telnet e outros serviços.
máquina
nome da máquina que hospeda o serviço web
porta
Porta do serviço web. Se for 80, o número da porta pode ser omitido. Este é o caso mais comum
caminho
caminho para o recurso solicitado
info
informações adicionais enviadas ao servidor para especificar o pedido do cliente

O que faz um navegador quando um utilizador solicita o carregamento de um URL?

  1. Estabelece uma ligação TCP/IP com a máquina e a porta especificadas na parte máquina[:porta] da URL. Estabelecer uma ligação TCP/IP significa criar um «canal» de comunicação entre duas máquinas. Assim que este canal for estabelecido, toda a informação trocada entre as duas máquinas passará por ele. A criação deste canal TCP/IP ainda não envolve o protocolo HTTP da Web.
  2. Assim que a ligação TCP/IP é estabelecida, o cliente envia o seu pedido ao servidor Web, enviando linhas de texto (comandos) no formato HTTP. Envia a parte path/info da URL para o servidor
  3. O servidor responderá da mesma forma e através da mesma ligação
  4. Uma das duas partes decidirá encerrar a ligação. Isto depende do protocolo HTTP utilizado. Com o HTTP 1.0, o servidor encerra a ligação após cada uma das suas respostas. Isto obriga um cliente que precise de efetuar múltiplas solicitações para recuperar os vários documentos que compõem uma página web a abrir uma nova ligação para cada solicitação, o que acarreta um custo. Com o protocolo HTTP/1.1, o cliente pode indicar ao servidor para manter a ligação aberta até que lhe diga para a fechar. Pode, portanto, recuperar todos os documentos de uma página web utilizando uma única ligação e fechar a ligação por si próprio assim que o último documento tiver sido obtido. O servidor irá detetar este encerramento e fechar a ligação também.

Para examinar as trocas entre um cliente e um servidor web, utilizaremos uma ferramenta chamada curl. O Curl é uma aplicação DOS que permite atuar como cliente para serviços de Internet que suportam vários protocolos (HTTP, FTP, TELNET, GOPHER, etc.). O curl está disponível no URL http://curl.haxx.se/. Aqui, baixaremos preferencialmente a versão para Windows win32-nossl, já que a versão win32-ssl requer DLLs adicionais não incluídas no pacote do curl. Este pacote contém um conjunto de ficheiros que apenas precisam de ser extraídos para uma pasta a que doravante chamaremos <curl>. Esta pasta contém um ficheiro executável chamado [curl.exe]. Este será o nosso cliente para consultar servidores web. Abra uma janela do Prompt de Comando e navegue até à pasta <curl>:

dos>dir curl.exe
22/03/2004  13:29              299 008 curl.exe

E:\curl2>curl
curl: try 'curl --help' for more information
dos>curl --help | more
Usage: curl [options...] <url>
Options: (H) means HTTP/HTTPS only, (F) means FTP only
 -a/--append        Append to target file when uploading (F)
 -A/--user-agent <string> User-Agent to send to server (H)
    --anyauth       Tell curl to choose authentication method (H)
 -b/--cookie <name=string/file> Cookie string or file to read cookies from (H)
    --basic         Enable HTTP Basic Authentication (H)
 -B/--use-ascii     Use ASCII/text transfer
 -c/--cookie-jar <file> Write cookies to this file after operation (H)
 ....

Vamos utilizar esta aplicação para consultar um servidor web e examinar as trocas entre o cliente e o servidor. Estaremos na seguinte situação:

Image

O servidor web pode ser qualquer servidor. Aqui, o nosso objetivo é descobrir as trocas que ocorrerão entre o cliente web curl e o servidor web. Anteriormente, criámos a seguinte página HTML estática:

<html>
  <head>
    <title>essai 1 : une page statique</title>
   </head>
   <body>
     <center>
     <h1>Une page statique...</h1>
   </body>
</html>

que visualizamos num navegador:

Image

Podemos ver que o URL solicitado é: http://localhost/aspnet/chap1/statique1.html. O servidor web é, portanto, o localhost (=máquina local) na porta 80. Se visualizarmos o código-fonte HTML desta página web (Ver/Código-fonte), vemos o texto HTML que foi originalmente criado:

Image

Agora vamos usar o nosso cliente CURL para solicitar a mesma URL:

dos>curl http://localhost/aspnet/chap1/statique1.html
<html>
  <head>
    <title>essai 1 : une page statique</title>
   </head>
   <body>
     <center>
     <h1>Une page statique...</h1>
   </body>
</html>

Podemos ver que o servidor web enviou um conjunto de linhas de texto representando o código HTML da página solicitada. Mencionámos anteriormente que a resposta de um servidor web assume a forma:

Image

No entanto, aqui não vimos os cabeçalhos HTTP. Isto deve-se ao facto de o [curl] não os apresentar por predefinição. A opção --include permite-lhe apresentá-los:

E:\curl2>curl --include http://localhost/aspnet/chap1/statique1.html
HTTP/1.1 200 OK
Server: Microsoft ASP.NET Web Matrix Server/0.6.0.0
Date: Mon, 22 Mar 2004 16:51:00 GMT
X-AspNet-Version: 1.1.4322
Cache-Control: public
ETag: "1C4102CEE8C6400:1C4102CFBBE2250"
Content-Type: text/html
Content-Length: 161
Connection: Close

<html>
  <head>
    <title>essai 1 : une page statique</title>
   </head>
   <body>
     <center>
     <h1>Une page statique...</h1>
   </body>
</html>

O servidor enviou, de facto, uma série de cabeçalhos HTTP seguidos de uma linha em branco:

HTTP/1.1 200 OK
Server: Microsoft ASP.NET Web Matrix Server/0.6.0.0
Date: Mon, 22 Mar 2004 16:51:00 GMT
X-AspNet-Version: 1.1.4322
Cache-Control: public
ETag: "1C4102CEE8C6400:1C4102CFBBE2250"
Content-Type: text/html
Content-Length: 161
Connection: Close
HTTP/1.1 200 OK
o servidor indica
  • que suporta a versão 1.1 do HTTP
  • que possui o recurso solicitado (código 200, mensagem OK)
Servidor: 
o servidor identifica-se. Neste caso, trata-se de um servidor Cassini
Data: ...
a data/hora da resposta
X-ASPNet-Version: ...
cabeçalho específico do servidor Cassini
Cache-Control: public
fornece ao cliente informações sobre se a resposta enviada pode ser armazenada em cache. O atributo [public] indica ao cliente que pode armazenar a página em cache. Um atributo [no-cache] teria indicado ao cliente para não armazenar a página em cache.
ETag:
...
Content-type: text/html
O servidor indica que irá enviar texto no formato HTML.
Content-Length: 161
O número de bytes no documento que será enviado após os cabeçalhos HTTP. Este número corresponde, na verdade, ao tamanho em bytes do ficheiro essai1.html:
dos>dir test1.html

08/07/2002  10:00                  161 test1.html
Connection: close
o servidor indica que irá fechar a ligação assim que o documento for enviado

O cliente recebe estes cabeçalhos HTTP e sabe agora que irá receber 161 bytes que representam um documento HTML. O servidor envia estes 161 bytes imediatamente após a linha em branco que sinalizou o fim dos cabeçalhos HTTP:

<html>
  <head>
    <title>essai 1 : une page statique</title>
   </head>
   <body>
     <center>
     <h1>Une page statique...</h1>
   </body>
</html>

Aqui vemos o ficheiro HTML tal como foi originalmente construído. Se o nosso cliente fosse um navegador, após receber estas linhas de texto, interpretá-las-ia para apresentar a seguinte página ao utilizador:

Image

Vamos usar o nosso cliente [curl] novamente para solicitar o mesmo recurso, mas desta vez pedindo apenas os cabeçalhos de resposta:

dos>curl --head http://localhost/aspnet/chap1/statique1.html
HTTP/1.1 200 OK
Server: Microsoft ASP.NET Web Matrix Server/0.6.0.0
Date: Tue, 23 Mar 2004 07:11:54 GMT
Cache-Control: public
ETag: "1C410A504D60680:1C410A58621AD3E"
Content-Type: text/html
Content-Length: 161
Connection: Close

Obtemos o mesmo resultado de antes sem o documento HTML. Agora, vamos solicitar uma imagem utilizando tanto um navegador como o cliente TCP genérico. Primeiro, utilizando um navegador:

Image

O ficheiro univ01.gif tem 4052 bytes:

dos>dir univ01.gif
23/03/2004  08:14             4 052 univ01.gif

Agora vamos usar o cliente [curl]:

dos>curl --head http://localhost/aspnet/chap1/univ01.gif
HTTP/1.1 200 OK
Server: Microsoft ASP.NET Web Matrix Server/0.6.0.0
Date: Tue, 23 Mar 2004 07:18:44 GMT
Cache-Control: public
ETag: "1C410A6795D7500:1C410A6868B1476"
Content-Type: image/gif
Content-Length: 4052
Connection: Close

Observe os seguintes pontos no ciclo de solicitação-resposta acima:

--head
  • Solicitamos apenas os cabeçalhos HTTP do recurso. Isto porque uma imagem é um ficheiro binário, não um ficheiro de texto, e exibi-la no ecrã como texto não produz nada legível.
Content-Length: 4052
  • Este é o tamanho do ficheiro univ01.gif
Content-Type: image/gif
  • O servidor informa ao cliente que enviará um documento do tipo image/gif, ou seja, uma imagem no formato GIF. Se a imagem estivesse no formato JPEG, o tipo de documento seria image/jpeg. Os tipos de documento são padronizados e são chamados de tipos MIME (Multi-purpose Mail Internet Extension).

2.6.3.2. Um pedido de um cliente HTTP

Agora, vamos fazer a seguinte pergunta: se quisermos escrever um programa que «comunique» com um servidor web, que comandos deve este enviar ao servidor web para obter um determinado recurso? Nos exemplos anteriores, vimos o que o cliente recebeu, mas não o que o cliente enviou. Vamos usar a opção [--verbose] do curl para ver também o que o cliente envia ao servidor. Comecemos por solicitar a página estática:

dos>curl --verbose http://localhost/aspnet/chap1/statique1.html
* About to connect() to localhost:80
* Connected to portable1_tahe (127.0.0.1) port 80
> GET /aspnet/chap1/statique1.html HTTP/1.1
User-Agent: curl/7.10.8 (win32) libcurl/7.10.8 OpenSSL/0.9.7a zlib/1.1.4
Host: localhost
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*

< HTTP/1.1 200 OK
< Server: Microsoft ASP.NET Web Matrix Server/0.6.0.0
< Date: Tue, 23 Mar 2004 07:37:06 GMT
< Cache-Control: public
< ETag: "1C410A504D60680:1C410A58621AD3E"
< Content-Type: text/html
< Content-Length: 161
< Connection: Close
<html>
  <head>
    <title>essai 1 : une page statique</title>
   </head>
   <body>
     <center>
     <h1>Une page statique...</h1>
   </body>
</html>
* Closing connection #0

Primeiro, o cliente [curl] estabelece uma ligação TCP/IP à porta 80 na máquina localhost (=127.0.0.1)

* About to connect() to localhost:80
* Connected to portable1_tahe (127.0.0.1) port 80

Assim que a ligação é estabelecida, envia o seu pedido HTTP. Trata-se de uma sequência de linhas de texto que termina com uma linha em branco:

GET /aspnet/chap1/statique1.html HTTP/1.1
User-Agent: curl/7.10.8 (win32) libcurl/7.10.8 OpenSSL/0.9.7a zlib/1.1.4
Host: localhost
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*

A solicitação HTTP de um cliente web tem duas funções:

  • especificar o recurso pretendido. Esta é a função da primeira linha, GET
  • fornecer informações sobre o cliente que faz a solicitação, para que o servidor possa, potencialmente, adaptar a sua resposta a este tipo específico de cliente.

O significado das linhas enviadas acima pelo cliente [curl] é o seguinte:

GET recurso protocolo
para solicitar um determinado recurso utilizando uma versão específica do protocolo HTTP. O servidor envia uma resposta no formato HTTP, seguida de uma linha em branco e, em seguida, do recurso solicitado
User-Agent
para indicar quem é o cliente
host:máquina:porta
para especificar (protocolo HTTP 1.1) a máquina e a porta do servidor web consultado
Pargma
aqui para especificar que o cliente não suporta cache.
Aceitar
Tipos MIME que especificam os tipos de ficheiros que o cliente consegue processar

Vamos tentar a operação novamente com a opção --head do [curl]:

dos>curl --verbose --head --output reponse.txt http://localhost/aspnet/chap1/statique1.html
* About to connect() to localhost:80
* Connected to portable1_tahe (127.0.0.1) port 80
> HEAD /aspnet/chap1/statique1.html HTTP/1.1
User-Agent: curl/7.10.8 (win32) libcurl/7.10.8 OpenSSL/0.9.7a zlib/1.1.4
Host: localhost
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*

< HTTP/1.1 200 OK
< Server: Microsoft ASP.NET Web Matrix Server/0.6.0.0
< Date: Tue, 23 Mar 2004 07:54:22 GMT
< Cache-Control: public
< ETag: "1C410A504D60680:1C410A58621AD3E"
< Content-Type: text/html
< Content-Length: 161
< Connection: Close

Vamos concentrar-nos apenas nos cabeçalhos HTTP enviados pelo cliente:

HEAD /aspnet/chap1/statique1.html HTTP/1.1
User-Agent: curl/7.10.8 (win32) libcurl/7.10.8 OpenSSL/0.9.7a zlib/1.1.4
Host: localhost
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*

Apenas o comando que solicita o recurso mudou. Em vez de um comando GET, temos agora um comando HEAD. Este comando solicita que a resposta do servidor se limite aos cabeçalhos HTTP e que não envie o recurso solicitado. A captura de ecrã acima não mostra os cabeçalhos HTTP recebidos. Estes foram guardados num ficheiro utilizando a opção [--output response.txt] do comando [curl]:

dos>more reponse.txt
HTTP/1.1 200 OK
Server: Microsoft ASP.NET Web Matrix Server/0.6.0.0
Date: Tue, 23 Mar 2004 07:54:22 GMT
Cache-Control: public
ETag: "1C410A504D60680:1C410A58621AD3E"
Content-Type: text/html
Content-Length: 161
Connection: Close

2.6.4. Conclusão

Analisámos a estrutura do pedido de um cliente web e a resposta do servidor web a esse pedido, utilizando alguns exemplos. A comunicação ocorre através do protocolo HTTP, um conjunto de comandos baseados em texto trocados entre as duas partes. O pedido do cliente e a resposta do servidor partilham a seguinte estrutura:

Image

No caso de uma solicitação do cliente (frequentemente chamada de consulta), a seção [Document] geralmente está ausente. No entanto, é possível que um cliente envie um documento ao servidor. Isso é feito utilizando um comando chamado PUT. Os dois comandos comuns para solicitar um recurso são GET e POST. O último será discutido um pouco mais adiante. O comando HEAD é utilizado para solicitar apenas os cabeçalhos HTTP. Os comandos GET e POST são os mais utilizados por clientes web baseados em navegadores.

Em resposta a um pedido do cliente, o servidor envia uma resposta com a mesma estrutura. O recurso solicitado é transmitido na secção [Document], a menos que o comando do cliente tenha sido HEAD, caso em que apenas os cabeçalhos HTTP são enviados.

2.7. HTML

Um navegador web pode apresentar vários documentos, sendo o mais comum o documento HTML (HyperText Markup Language). Trata-se de texto formatado utilizando tags do tipo <tag>texto</tag>. Assim, o texto <B>importante</B> apresentará o texto «importante» em negrito. Existem tags autónomas, como a tag , que apresenta uma linha horizontal. Não iremos rever todas as tags que podem ser encontradas no texto HTML. Existem muitos programas de software WYSIWYG que permitem criar uma página web sem escrever uma única linha de código HTML. Estas ferramentas geram automaticamente o código HTML para um layout criado utilizando o rato e controlos predefinidos. Pode, assim, inserir (utilizando o rato) uma tabela na página e, em seguida, visualizar o código HTML gerado pelo software para descobrir as tags a utilizar na definição de uma tabela numa página web. É tão simples quanto isso. Além disso, o conhecimento de HTML é essencial, uma vez que as aplicações web dinâmicas têm de gerar elas próprias o código HTML para enviar aos clientes web. Este código é gerado programaticamente e, naturalmente, tem de saber o que gerar para que o cliente receba a página web que deseja.

Em suma, não precisa de conhecer toda a linguagem HTML para começar a programar para a Web. No entanto, este conhecimento é necessário e pode ser adquirido utilizando construtores de páginas Web WYSIWYG, como o Word, o FrontPage, o DreamWeaver e dezenas de outros. Outra forma de descobrir as complexidades do HTML é navegar na Web e visualizar o código-fonte de páginas que apresentam elementos interessantes que ainda não tenha encontrado.

2.7.1. Um exemplo

Considere o exemplo seguinte, criado com o FrontPage Express, uma ferramenta gratuita incluída no Internet Explorer. O código gerado pelo FrontPage foi aqui simplificado. Este exemplo apresenta alguns elementos comumente encontrados num documento web, tais como:

  • uma tabela
  • uma imagem
  • um link

Image

Um documento HTML tem geralmente a seguinte forma:

<html>
    <head>
        <title>Un titre</title>
        ...
    </head>
    <body attributs>
        ...
    </body>
</html>

Todo o documento está entre as tags <html>...</html>. É composto por duas partes:

  1. <head>...</head>: Esta é a parte não exibível do documento. Fornece informações ao navegador que irá exibir o documento. Contém frequentemente a tag <title>...</title>, que define o texto que aparecerá na barra de título do navegador. Pode também conter outras tags, incluindo aquelas que definem as palavras-chave do documento, que são depois utilizadas pelos motores de busca. Esta secção pode ainda conter scripts, geralmente escritos em JavaScript ou VBScript, que serão executados pelo navegador.
  2. <body attributes>...</body>: Esta é a secção que será exibida pelo navegador. As tags HTML contidas nesta secção indicam ao navegador o layout visual «desejado» para o documento. Cada navegador interpreta estas tags à sua maneira. Como resultado, dois navegadores podem exibir o mesmo documento web de forma diferente. Este é geralmente um dos desafios enfrentados pelos web designers.

O código HTML para o nosso documento de exemplo é o seguinte:

<html>

  <head>
      <title>balises</title>
  </head>

  <body background="/images/standard.jpg">
      <center>
        <h1>Les balises HTML</h1>
        <hr>
      </center>

    <table border="1">
      <tr>
        <td>cellule(1,1)</td>
        <td valign="middle" align="center" width="150">cellule(1,2)</td>
        <td>cellule(1,3)</td>
      </tr>
      <tr>
        <td>cellule(2,1)</td>
        <td>cellule(2,2)</td>
        <td>cellule(2,3</td>
      </tr>
    </table>

    <table border="0">
      <tr>
        <td>Une image</td>
        <td><img border="0" src="/images/univ01.gif" width="80" height="95"></td>
      </tr>
      <tr>
        <td>le site de l'ISTIA</td>
        <td><a href="http://istia.univ-angers.fr">ici</a></td>
      </tr>
    </table>
  </body>
</html>

Apenas os pontos de interesse para nós foram destacados no código:

HTML
Etiquetas HTML e exemplos
título do documento
<title>tags</title>
O texto aparecerá na barra de título do navegador quando o documento for exibido
barra horizontal
<horizontal> : exibe uma linha horizontal
tabela
<atributos da tabela>....</table> : para definir a tabela
<tr atributos>... : para definir uma linha
<td atributos>... : para definir uma célula
exemplos:
<table border="1">... : o atributo border define a espessura da borda da tabela
<td valign="middle" align="center" width="150">célula(1,2) : define uma célula cujo conteúdo será célula(1,2). Este conteúdo será centralizado verticalmente (valign="middle") e horizontalmente (align="center"). A célula terá uma largura de 150 píxeis (width="150")
imagem
<img border="0" src="/images/univ01.gif" width="80" height="95"> : define uma imagem sem borda (border="0"), 95 píxeis de altura (height="95"), 80 píxeis de largura (width="80") e cujo ficheiro de origem é /images/univ01.gif no servidor web (src="/images/univ01.gif"). Esta ligação está localizada num documento web acessível através do URL http://localhost:81/html/balises.htm. Portanto, o navegador irá solicitar a URL http://localhost:81/images/univ01.gif para recuperar a imagem aqui referenciada.
link
<a href="http://istia.univ-angers.fr">aqui: faz com que o texto «aqui» funcione como um link para a URL http://istia.univ-angers.fr.
fundo da página
<body background="/images/standard.jpg">: indica que a imagem a ser utilizada como fundo da página está localizada no URL /images/standard.jpg no servidor web. No contexto do nosso exemplo, o navegador irá solicitar o URL http://localhost:81/images/standard.jpg para recuperar esta imagem de fundo.

Podemos ver neste exemplo simples que, para construir todo o documento, o navegador deve fazer três pedidos ao servidor:

  1. http://localhost:81/html/balises.htm para recuperar o código-fonte HTML do documento
  2. http://localhost:81/images/univ01.gif para recuperar a imagem univ01.gif
  3. http://localhost:81/images/standard.jpg para recuperar a imagem de fundo standard.jpg

O exemplo seguinte mostra um formulário web também criado com o FrontPage.

Image

O código HTML gerado pelo FrontPage e ligeiramente limpo é o seguinte:

<html>

  <head>
      <title>balises</title>
    <script language="JavaScript">
        function effacer(){
          alert("Vous avez cliqué sur le bouton Effacer");
      }//effacer
        </script>
  </head>

  <body background="/images/standard.jpg">
    <form method="POST" >
      <table border="0">
        <tr>
          <td>Etes-vous marié(e)</td>
          <td>
              <input type="radio" value="Oui" name="R1">Oui
              <input type="radio" name="R1" value="non" checked>Non
          </td>
        </tr>
        <tr>
          <td>Cases à cocher</td>
          <td>
              <input type="checkbox" name="C1" value="un">1
              <input type="checkbox" name="C2" value="deux" checked>2
              <input type="checkbox" name="C3" value="trois">3
          </td>
        </tr>
        <tr>
          <td>Champ de saisie</td>
          <td>
              <input type="text" name="txtSaisie" size="20" value="qqs mots">
          </td>
        </tr>
        <tr>
          <td>Mot de passe</td>
          <td>
              <input type="password" name="txtMdp" size="20" value="unMotDePasse">
          </td>
        </tr>
        <tr>
          <td>Boîte de saisie</td>
          <td>
               <textarea rows="2" name="areaSaisie" cols="20">
ligne1
ligne2
ligne3
</textarea>
          </td>
        </tr>
        <tr>
          <td>combo</td>
          <td>
              <select size="1" name="cmbValeurs">
                <option>choix1</option>
                <option selected>choix2</option>
                <option>choix3</option>
              </select>
          </td>
        </tr>
        <tr>
          <td>liste à choix simple</td>
          <td>
              <select size="3" name="lst1">
                <option selected>liste1</option>
                <option>liste2</option>
                <option>liste3</option>
                <option>liste4</option>
                <option>liste5</option>
              </select>
          </td>
        </tr>
        <tr>
          <td>liste à choix multiple</td>
          <td>
              <select size="3" name="lst2" multiple>
                <option>liste1</option>
                <option>liste2</option>
                <option selected>liste3</option>
                <option>liste4</option>
                <option>liste5</option>
              </select>
          </td>
        </tr>
        <tr>
          <td>bouton</td>
          <td>
              <input type="button" value="Effacer" name="cmdEffacer" onclick="effacer()">
          </td>
        </tr>
        <tr>
          <td>envoyer</td>
          <td>
              <input type="submit" value="Envoyer" name="cmdRenvoyer">
          </td>
        </tr>
        <tr>
          <td>rétablir</td>
          <td>
              <input type="reset" value="Rétablir" name="cmdRétablir">
          </td>
        </tr>
      </table>
      <input type="hidden" name="secret" value="uneValeur">
    </form>
  </body>
</html>

O mapeamento entre elementos visuais e tags HTML é o seguinte:

Controlo visual
Tag HTML
form
<form method="POST" >
campo de entrada
<input type="text" name="txtInput" size="20" value="algumas palavras">
campo de entrada oculto
<input type="password" name="txtPassword" size="20" value="aPassword">
campo de entrada multilinha
<textarea rows="2" name="inputArea" cols="20">
linha1
linha2
linha3
</textarea>
botões de opção
<input type="radio" value="Sim" name="R1">Sim
<input type="radio" name="R1" value="No" checked>Não
caixas de seleção
<input type="checkbox" name="C1" value="one">1
<input type="checkbox" name="C2" value="dois" checked>2
<input type="checkbox" name="C3" value="três">3
Lista suspensa
<select size="1" name="cmbValues">
<option>opção1</option>
<option selected>opção2</option>
<option>opção3</option>
</select>
lista de seleção única
<select size="3" name="lst1">
<option selected>lista1</option>
<option>lista2</option>
<option>lista3</option>
<option>lista4</option>
<option>lista5</option>
</select>
lista de seleção múltipla
<select size="3" name="lst2" multiple>
<option>lista1</option>
<option>lista2</option>
<option selected>lista3</option>
<option>lista4</option>
<option>lista5</option>
</select>
botão de envio
<input type="submit" value="Enviar" name="cmdSubmit">
botão de reiniciar
<input type="reset" value="Redefinir" name="cmdReset">
botão
<input type="button" value="Limpar" name="cmdClear" onclick="clear()">

Vamos rever estes diferentes controlos.

2.7.1.1. O formulário

formulário
<form method="POST" >
Etiqueta HTML
<form name="..." method="..." action="...">...</form>
atributos
name="exampleform": nome do formulário
method="..." : método utilizado pelo navegador para enviar os valores recolhidos no formulário para o servidor web
action="..." : URL para a qual os valores recolhidos no formulário serão enviados.
Um formulário web é delimitado pelas tags <form>...</form>. O formulário pode ter um nome (name="xx"). Isto aplica-se a todos os controlos presentes num formulário. Este nome é útil se o documento web contiver scripts que precisem de referenciar elementos do formulário. O objetivo de um formulário é recolher informações introduzidas pelo utilizador através do teclado ou do rato e enviá-las para o URL de um servidor web. Qual deles? Aquele referenciado no atributo action="URL". Se este atributo estiver em falta, as informações serão enviadas para o URL do documento no qual o formulário se encontra. Este seria o caso no exemplo acima. Até agora, sempre vimos o cliente web como «solicitando» informações de um servidor web, nunca «fornecendo» informações a ele. Como é que um cliente web fornece informações (os dados contidos no formulário) a um servidor web? Voltaremos a este assunto em detalhe um pouco mais tarde. Pode utilizar dois métodos diferentes chamados POST e GET. O atributo method="método" da tag <form>, onde método é definido como GET ou POST, indica ao navegador qual o método a utilizar para enviar as informações recolhidas no formulário para a URL especificada pelo atributo action="URL". Quando o atributo método não é especificado, o método GET é utilizado por predefinição.

2.7.1.2. Campo de entrada

Image

Image

campo de entrada
<input type="text" name="txtInput" size="20" value="algumas palavras">
<input type="password" name="txtMdp" size="20" value="aPassword">
Etiqueta HTML
<input type="..." name="..." size=".." value="..">
A tag input existe para vários controlos. É o atributo type que distingue estes diferentes controlos uns dos outros.
atributos
type="text": especifica que este é um campo de entrada de texto
type="password": os caracteres no campo de entrada são substituídos por asteriscos (*). Esta é a única diferença em relação a um campo de entrada normal. Este tipo de controlo é adequado para introduzir palavras-passe.
size="20": número de caracteres visíveis no campo — não impede a introdução de mais caracteres
name="txtInput": nome do controlo
value="algumas palavras": texto que será exibido no campo de entrada.

2.7.1.3. Campo de entrada multilinha

Image

campo de entrada multilinha
<textarea rows="2" name="areaSaisie" cols="20">
linha1
linha2
linha3
</textarea>
tag HTML
<textarea ...>texto</textarea>
exibe um campo de entrada de texto multilinha com texto inicial no interior
atributos
rows="2": número de linhas
cols="'20": número de colunas
name="areaSaisie": nome do controlo

2.7.1.4. Botões de opção

Image

botões de opção
<input type="radio" value="Yes" name="R1">Sim
<input type="radio" name="R1" value="no" checked>Não
Etiqueta HTML
<input type="radio" attribute2="value2" ....>texto
Exibe um botão de opção com texto ao lado.
atributos
name="radio": nome do controlo. Os botões de opção com o mesmo nome formam um grupo de botões mutuamente exclusivos: apenas um deles pode ser selecionado.
value="valor": valor atribuído ao botão de opção. Não confunda este valor com o texto exibido ao lado do botão de opção. O texto serve apenas para fins de exibição.
checked: se esta palavra-chave estiver presente, o botão de opção está marcado; caso contrário, não está.

2.7.1.5. Caixas de seleção

caixas de seleção
<input type="checkbox" name="C1" value="one">1
<input type="checkbox" name="C2" value="two" checked>2
<input type="checkbox" name="C3" value="three">3

Image

Etiqueta HTML
<input type="checkbox" attribute2="value2" ....>texto
exibe uma caixa de seleção com texto ao lado.
atributos
name="C1": nome do controlo. As caixas de seleção podem ou não ter o mesmo nome. As caixas de seleção com o mesmo nome formam um grupo de caixas de seleção associadas.
value="valor": valor atribuído à caixa de seleção. Não confunda este valor com o texto exibido ao lado do botão de opção. O texto serve apenas para fins de exibição.
marcado: se esta palavra-chave estiver presente, o botão de opção fica marcado; caso contrário, não fica.

2.7.1.6. Lista suspensa (combo)

Combo
<select size="1" name="cmbValues">
<option>opção1</option>
<option selected>opção2</option>
<option>opção3</option>
</select>

Image

Etiqueta HTML
<select size=".." name="..">
<option [selected]>...</option>
...
</select>
exibe o texto entre as tags <option>...</option> numa lista
atributos
name="cmbValues": nome do controlo.
size="1": número de itens visíveis da lista. size="1" torna a lista equivalente a uma caixa combinada.
selected: se este atributo estiver presente para um item da lista, esse item aparece selecionado na lista. No nosso exemplo acima, o item da lista "choice2" aparece como o item selecionado na caixa combinada quando é exibido pela primeira vez.

2.7.1.7. Lista de seleção única

lista de seleção única
<select size="3" name="lst1">
<option selected>list1</option>
<option>list2</option>
<option>lista3</option>
<option>lista4</option>
<option>lista5</option>
</select>

Image

Etiqueta HTML
<select size=".." name="..">
<option [selected]>...</option>
...
</select>
exibe o texto entre as tags <option>...</option> numa lista
atributos
os mesmos que para a lista suspensa que exibe apenas um item. Este controlo difere da lista suspensa anterior apenas no seu atributo size>1.

2.7.1.8. Lista de seleção múltipla

lista de seleção única
<select size="3" name="lst2" multiple>
<option selected>list1</option>
<option>list2</option>
<option selected>lista3</option>
<option>lista4</option>
<option>lista5</option>
</select>

Image

Etiqueta HTML
<select size=".." name=".." multiple>
<option [selected]>...</option>
...
</select>
exibe o texto entre as tags <option>...</option> numa lista
atributos
multiple: permite que vários itens sejam selecionados da lista. No exemplo acima, os itens list1 e list3 estão ambos selecionados.

2.7.1.9. Botão

botão
<input type="button" value="Limpar" name="cmdClear" onclick="clear()">

Image

Etiqueta HTML
<input type="button" value="..." name="..." onclick="clear()" ....>
atributos
type="button": define um controlo de botão. Existem outros dois tipos de botões: submit e reset.
value="Limpar": o texto exibido no botão
onclick="function()": permite definir uma função a ser executada quando o utilizador clica no botão. Esta função faz parte dos scripts definidos no documento web apresentado. A sintaxe acima é a sintaxe JavaScript. Se os scripts forem escritos em VBScript, escrever-se-ia onclick="function" sem os parênteses. A sintaxe permanece a mesma se for necessário passar parâmetros para a função: onclick="function(val1, val2,...)"
No nosso exemplo, clicar no botão Limpar chama a seguinte função de limpeza em JavaScript:
    <script language="JavaScript">
        function clear(){
          alert("Clicou no botão Limpar");
      }//clear
        </script>
A função clear exibe uma mensagem:

2.7.1.10. Botão Enviar

Botão Enviar
<input type="submit" value="Enviar" name="cmdSend">

Image

Etiqueta HTML
<input type="submit" value="Enviar" name="cmdRenvoyer">
atributos
type="submit": define o botão como um botão para enviar dados do formulário para o servidor web. Quando o utilizador clica neste botão, o navegador envia os dados do formulário para o URL definido no atributo action da tag <form>, utilizando o método definido pelo atributo method dessa mesma tag.
value="Submit": o texto exibido no botão

2.7.1.11. Botão de reinicialização

botão de reinicialização
<input type="reset" value="Reset" name="cmdReset">

Image

Etiqueta HTML
<input type="reset" value="Redefinir" name="cmdReset">
atributos
type="reset": define o botão como um botão de reinicialização do formulário. Quando o utilizador clica neste botão, o navegador restaura o formulário para o estado em que foi recebido.
value="Reset": o texto exibido no botão

2.7.1.12. Campo oculto

campo oculto
<input type="hidden" name="secret" value="aValue">
Etiqueta HTML
<input type="hidden" name="..." value="...">
atributos
type="hidden": especifica que este é um campo oculto. Um campo oculto faz parte do formulário, mas não é apresentado ao utilizador. No entanto, se o utilizador visualizasse o código-fonte no seu navegador, veria a tag <input type="hidden" value="..."> e, consequentemente, o valor do campo oculto.
value="aValue": valor do campo oculto.
Qual é o objetivo de um campo oculto? Permite que o servidor web retenha informações entre as solicitações de um cliente. Considere uma aplicação de compras online. O cliente compra um primeiro artigo art1 na quantidade q1 na primeira página de um catálogo e, em seguida, passa para uma nova página no catálogo. Para lembrar que o cliente comprou q1 artigos de art1, o servidor pode colocar estas duas informações num campo oculto no formulário web da nova página. Nesta nova página, o cliente compra q2 unidades do artigo art2. Quando os dados deste segundo formulário forem enviados para o servidor, este não só receberá a informação (q2,art2), mas também (q1,art1), que também faz parte do formulário como um campo oculto que não pode ser modificado pelo utilizador. O servidor web colocará então as informações (q1,art1) e (q2,art2) num novo campo oculto e enviará uma nova página do catálogo. E assim por diante.

2.7.2. Envio de valores de formulário para um servidor web por um cliente web

Mencionámos no estudo anterior que o cliente web dispõe de dois métodos para enviar os valores de um formulário que apresentou a um servidor web: os métodos GET e POST. Vejamos um exemplo para perceber a diferença entre os dois métodos. A página discutida anteriormente é uma página estática. Para aceder aos cabeçalhos HTTP enviados pelo navegador que solicita este documento, iremos convertê-la numa página dinâmica para um servidor web .NET (IIS ou Cassini). O foco aqui não é a tecnologia .NET — que será abordada no próximo capítulo — mas sim a comunicação cliente-servidor. O código para a página ASP.NET é o seguinte:

<%@ Page Language="vb" CodeBehind="params.aspx.vb" AutoEventWireup="false" Inherits="ConsoleApplication1.params" %>
<script runat="server">

    Private Sub Page_Init(Byval Sender as Object, Byval e as System.EventArgs)
      ' save the query
    saveRequest
  end sub
  Private Sub saveRequest
      ' saves the current query in request.txt of the page folder
    dim requestFileName as String=Me.MapPath(Me.TemplateSourceDirectory)+"\request.txt"
    Me.Request.SaveAs(requestFileName,true)
  end sub
</script>

<html>
    <head>
        <title>balises</title>
        <script language="JavaScript">
        function effacer(){
          alert("Vous avez cliqué sur le bouton Effacer");
      }//effacer
        </script>
    </head>
    <body background="/images/standard.jpg">
....
    </body>
</html>

Ao conteúdo HTML da página em questão, adicionamos uma secção de código VB.NET. Não iremos comentar este código, exceto para dizer que, cada vez que o documento acima for chamado, o servidor web guardará o pedido do cliente web no ficheiro [request.txt] na pasta do documento chamado.

2.7.2.1. Método GET

Vamos realizar um teste inicial, em que, no código HTML do documento, a tag FORM é definida da seguinte forma:


        <form method="get">

O documento anterior (código HTML+VB) chama-se [params.aspx]. Está localizado na árvore de diretórios de um servidor web .NET (IIS/Cassini) e é acedido através do URL http://localhost/aspnet/chap1/params.aspx:

Image

O navegador acabou de fazer um pedido e sabemos que este foi guardado no ficheiro [request.txt]. Vejamos o seu conteúdo:

GET /aspnet/chap1/params.aspx HTTP/1.1
Connection: keep-alive
Keep-Alive: 300
Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Encoding: gzip,deflate
Accept-Language: en-us,en;q=0.5
Host: localhost
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113

Vemos elementos que já encontrámos com o cliente [curl]. Outros aparecem pela primeira vez:

Connection: keep-alive
o cliente pede ao servidor para não fechar a ligação após a sua resposta. Isto permitirá que utilize a mesma ligação para um pedido subsequente. A ligação não permanece aberta indefinidamente. O servidor irá fechá-la após um período prolongado de inatividade.
Keep-Alive
duração em segundos durante a qual a ligação [Keep-Alive] permanecerá aberta
Accept-Charset
Conjunto de caracteres que o cliente pode processar
Accept-Language
Lista de idiomas preferidos pelo cliente.

Preenchemos o formulário da seguinte forma:

Image

Utilizamos o botão [Submit] acima. O seu código HTML é o seguinte:

<form method="get">
    ...
    <input type="submit" value="Envoyer">
    ...
</form>

Quando se clica no botão [Submit], o navegador envia os parâmetros do formulário (a tag <form>) para o URL especificado no atributo [action] da tag <form action="URL">, caso exista. Se este atributo não existir, os parâmetros do formulário são enviados para o URL que serviu o formulário. É este o caso aqui. O botão [Submit] deve, portanto, desencadear um pedido do navegador para o URL [http://localhost/aspnet/chap1/params.aspx] com os parâmetros do formulário incluídos. Uma vez que a página [params.aspx] armazena o pedido recebido, devemos ser capazes de determinar como o cliente enviou estes parâmetros. Vamos experimentar. Clicamos no botão [Submit]. Recebemos a seguinte resposta do navegador:

Image

Esta é a página inicial, mas pode ver que o URL mudou no campo [Endereço] do navegador. Passou a ser o seguinte:

http://localhost/aspnet/chap1/params.aspx?R1=Oui&C1=un&C2=deux&txtSaisie=programmation+web&txtMdp=ceciestsecret&areaSaisie=les+bases+de+la%0D%0Aprogrammation+web&cmbValeurs=choix3&lst1=liste3&lst2=liste1&lst2=liste3&cmdRenvoyer=Envoyer&secret=uneValeur

Podemos ver que as opções selecionadas no formulário se refletem no URL. Vejamos o conteúdo do ficheiro [request.txt], que guardou o pedido do cliente:

GET /aspnet/chap1/params.aspx?R1=Oui&C1=un&C2=deux&txtSaisie=programmation+web&txtMdp=ceciestsecret&areaSaisie=les+bases+de+la%0D%0Aprogrammation+web&cmbValeurs=choix3&lst1=liste3&lst2=liste1&lst2=liste3&cmdRenvoyer=Envoyer&secret=uneValeur HTTP/1.1
Connection: keep-alive
Keep-Alive: 300
Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Encoding: gzip,deflate
Accept-Language: en-us,en;q=0.5
Host: localhost
Referer: http://localhost/aspnet/chap1/params.aspx
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113

Vemos um pedido HTTP bastante semelhante ao inicialmente feito pelo navegador quando solicitou o documento sem enviar quaisquer parâmetros. Existem duas diferenças:

GET HTTP/1.1 URL
Os parâmetros do formulário foram anexados à URL do documento na forma ?param1=val1&param2=val2&...
Referer
O cliente utiliza este cabeçalho HTTP para indicar a URL do documento que estava a exibir quando efetuou a solicitação

Vamos analisar mais detalhadamente como os parâmetros foram passados na solicitação GET URL?param1=value1&param2=value2&... HTTP/1.1, onde param1, param2, etc., são os nomes dos controlos do formulário web e value1, value2, etc., são os valores a eles associados. Abaixo está uma tabela de três colunas:

  • Coluna 1: mostra a definição de um controlo HTML do exemplo
  • Coluna 2: mostra como este controlo aparece num navegador
  • Coluna 3: mostra o valor enviado ao servidor pelo navegador para o controlo da Coluna 1, na forma que assume na solicitação GET do exemplo
Controlo HTML
Visual
Valor(es) devolvido(s)
<input type="radio" value="Yes" name="R1">Sim
<input type="radio" name="R1" value="no" checked>Não
- o valor do atributo value do botão de opção selecionado pelo utilizador.
<input type="checkbox" name="C1" value="one">1
<input type="checkbox" name="C2" value="two" checked>2
<input type="checkbox" name="C3" value="three">3
C1=um
C2=dois
- valores dos atributos «value» das caixas de seleção marcadas pelo utilizador
<input type="text" name="txtInput" size="20" value="algumas palavras">
txtInput=programação+web
- texto digitado pelo utilizador no campo de entrada. Os espaços foram substituídos pelo sinal +
<input type="password" name="txtMdp" size="20" value="aPassword">
txtPassword=istoÉSecreto
- texto digitado pelo utilizador no campo de entrada
<textarea rows="2" name="inputArea" cols="20">
linha1
linha2
linha3
</textarea>
areaSaisie=o+fundamental+da+programação+web%0D%0A
programação+web
- texto digitado pelo utilizador no campo de entrada. %OD%OA é o marcador de fim de linha. Os espaços foram substituídos pelo sinal +
<select size="1" name="cmbValues">
<option>opção1</option>
<option selected>opção2</option>
<option>opção3</option>
</select>
cmbValues=option3
- valor selecionado pelo utilizador na lista de seleção única
<select size="3" name="lst1">
<option selected>list1</option>
<option>lista2</option>
<option>lista3</option>
<option>lista4</option>
<option>lista5</option>
</select>
lst1=list3
- valor selecionado pelo utilizador na lista de seleção única
<select size="3" name="lst2" multiple>
<option selected>list1</option>
<option>list2</option>
<option selected>list3</option>
<option>lista4</option>
<option>lista5</option>
</select>
lst2=list1
lst2=lista3
- valores selecionados pelo utilizador na lista de seleção múltipla
<input type="submit" value="Enviar" name="cmdSubmit">
 
cmdSubmit=Enviar
- atributos name e value do botão utilizado para enviar os dados do formulário para o servidor
<input type="hidden" name="secret" value="aValue">
 
secret=aValue
- atributo value do campo oculto

Pode estar a perguntar-se o que o servidor fez com os parâmetros que lhe foram passados. Na verdade, nada. Ao receber o pedido

GET /aspnet/chap1/params.aspx?R1=Oui&C1=un&C2=deux&txtSaisie=programmation+web&txtMdp=ceciestsecret&areaSaisie=les+bases+de+la%0D%0Aprogrammation+web&cmbValeurs=choix3&lst1=liste3&lst2=liste1&lst2=liste3&cmdRenvoyer=Envoyer&secret=uneValeur HTTP/1.1

O servidor web passou os parâmetros da URL para o documento http://localhost/aspnet/chap1/params.aspx, ou seja, para o documento que criámos inicialmente. Não escrevemos qualquer código para recuperar e processar os parâmetros que o cliente nos envia. Assim, tudo acontece como se o pedido do cliente fosse simplesmente:

GET /aspnet/chap1/params.aspx

É por isso que, em resposta ao nosso botão [Submit], recebemos a mesma página que a obtida inicialmente ao solicitar a URL [http://localhost/aspnet/chap1/params.aspx] sem parâmetros.

2.7.2.2. Método POST

O documento HTML está agora configurado para que o navegador utilize o método POST para enviar os valores do formulário para o servidor web:

    <form method="POST" >

Solicitamos o novo documento através da URL [http://localhost/aspnet/chap1/params.aspx], preenchemos o formulário tal como fizemos para o método GET e enviamos os parâmetros para o servidor utilizando o botão [Submit]. Recebemos a seguinte página de resposta do servidor:

Image

Assim, obtemos o mesmo resultado que com o método GET, ou seja, a página inicial. Note uma diferença: no campo [Endereço] do navegador, os parâmetros transmitidos não aparecem. Agora, vamos ver o pedido enviado pelo cliente e guardado no ficheiro [request.txt]:

POST /aspnet/chap1/params.aspx HTTP/1.1
Connection: keep-alive
Keep-Alive: 300
Content-Length: 210
Content-Type: application/x-www-form-urlencoded
Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Encoding: gzip,deflate
Accept-Language: en-us,en;q=0.5
Host: localhost
Referer: http://localhost/aspnet/chap1/params.aspx
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113

R1=Oui&C1=un&C2=deux&txtSaisie=programmation+web&txtMdp=ceciestsecrey&areaSaisie=les+bases+de+la%0D%0Aprogrammation+web&cmbValeurs=choix3&lst1=liste3&lst2=liste1&lst2=liste3&cmdRenvoyer=Envoyer&secret=uneValeur

Novos elementos aparecem na solicitação HTTP do cliente:

POST HTTP/1.1
A solicitação GET foi substituída por uma solicitação POST. Os parâmetros já não estão presentes na primeira linha da solicitação. Podemos ver que agora estão colocados após a solicitação HTTP, seguindo uma linha em branco. A sua codificação é idêntica à da solicitação GET.
Content-Length
número de caracteres «enviados», ou seja, o número de caracteres que o servidor web deve ler após receber os cabeçalhos HTTP para recuperar o documento enviado pelo cliente. O documento em questão aqui é a lista de valores do formulário.
Content-type
especifica o tipo de documento que o cliente enviará após os cabeçalhos HTTP. O tipo [application/x-www-form-urlencoded] indica que se trata de um documento contendo valores do formulário.

Existem dois métodos para transmitir dados a um servidor web: GET e POST. Será que um método é melhor do que o outro? Vimos que, se os valores de um formulário fossem enviados pelo navegador utilizando o método GET, o navegador exibiria o URL solicitado na sua barra de endereços na forma URL?param1=val1&param2=val2&.... Isto pode ser visto como uma vantagem ou uma desvantagem:

  • uma vantagem se quiser permitir que o utilizador guarde esta URL parametrizada nos seus favoritos
  • uma desvantagem se não quiser que o utilizador tenha acesso a determinadas informações do formulário, tais como campos ocultos

A partir de agora, utilizaremos o método POST quase exclusivamente nos nossos formulários.

2.8. Conclusão

Este capítulo apresentou vários conceitos básicos de desenvolvimento web:

  • as várias ferramentas e tecnologias disponíveis (Java, ASP, ASP.NET, PHP, Perl, VBScript, JavaScript)
  • a comunicação cliente-servidor através do protocolo HTTP
  • a criação de um documento utilizando HTML
  • o design de formulários de entrada

Vimos um exemplo de como um cliente pode enviar informações para o servidor web. Não abordámos como o servidor pode

  • recuperar essas informações
  • processá-las
  • enviar ao cliente uma resposta dinâmica com base no resultado do processamento

Este é o domínio da programação web, um tópico que abordaremos no próximo capítulo com uma introdução à tecnologia ASP.NET.