HTTP Carlos Bazilio Depto de Ciência e Tecnologia Pólo Universitário de Rio das Ostras Universidade Federal Fluminense Arquitetura HTML – Como funciona o envio desta mensagem? <body> <form action=“processaForm.jsp" > Nome: <input type="text" name="firstname"><br /> Sobrenome: <input type="text" name="lastname"><br /> Senha: <input type="password" name="senha"> <input type="submit" value="Enviar"> </form> </body> • URL após clicar no botão: .../sirius/processaForm.jsp?firstname=Carlos&lastname= Bazilio&senha=abcdefg Tipos de requisições HTTP • GET – Parâmetros são enviados na url da solicitação – http://localhost:8080/sirius/processaForm.jsp?firstnam e=Carlos&lastname=Bazilio&senha=abcdefg – Envio de parâmetros firstname e lastname e senha para um recurso no servidor (neste caso, uma página jsp – processaForm.jsp) – Estas urls podem ser armazenadas como favoritos – Tipo padrão (default) – Não recomendado para o envio de informações sigilosas Tipos de requisições HTTP • POST – Parâmetros são enviados de maneira invisível para o cliente (no cabeçalho da solicitação e não na url) – Com isso, a url não pode ser armazenada – Interessante para o envio de informações sigilosas • HEAD – Solicitar apenas o cabeçalho da solicitação – Interessante quando se deseja saber o tamanho ou data da atualização de um recurso Tipos de requisições HTTP Pouco Utilizados • PUT – Colocar um documento diretamente no servidor • DELETE – Remover um documento do servidor • TRACE – Efetuar um debug da solicitação. Retorna para o cliente o conteúdo exato da solicitação • OPTIONS – Perguntar ao servidor que métodos ele suporta ou que opções estão disponíveis para algum recurso particular Exemplos de Requisição HTTP GET / HTTP/1.1 Host: www.siriusnet.com.br Connection: close User-agent: Mozilla/4.0 Accept-language: fr GET http://www.siriusnet.com.br/comochegar.html HTTP/1.1 GET / HTTP/1.1 Como testar uma requisição HTTP • Uma forma simples é abrindo uma conexão com o servidor web desejado: Configura o prompt local para que os comandos sejam exibidos C:\...> telnet<Enter> telnet> set localecho<Enter> telnet> open www.siriusnet.com.br 80 <Enter> Servidor a ser no servidor; get / HTTP/1.1<Enter> conectado Porta 80 é a porta padrão http <Enter> Cabeçalho http Formato de Requisição HTTP <Método> <Url> <Versão> <nome-campo-cabecalho_n> : <valor_n> ... <nome-campo-cabecalho_n> : <valor_n> Corpo da Requisição (possíveis parâmetros de uma requisição do tipo POST) Documentação: http://www.w3.org/Protocols/rfc2616/rfc2616sec5.html#sec5 Alguns campos de cabeçalho de requisição • Host: ... Especifica o servidor no qual o objeto/recurso reside • Connection: close Solicita ao servidor que feche a conexão após envio do objeto • User-agent: ... Tipo de browser que faz a requisição • Accept-language: ... Indica língua preferida para o recebimento do objeto • If-Unmodified-Since: ... Indica ao servidor para enviar apenas uma versão atualizada do objeto <html> <frameset cols="100%,*" framespacing="0" border="0" frameborder="0"> <frame src="home.asp"> <frame src="br.htm"> <noframes> <body topmargin="0" leftmargin="0"> O seu navegador nπo suporta frames Para visualizar estß pßgina Θ necessßrio<br> usar um navegador atualizado </body> </noframes> </frameset> </html> Exemplo de Resposta HTTP HTTP/1.0 200 OK Date: Wed, 21 Jan 2009 13:00:53 GMT Server: Microsoft-IIS/6.0 X-Powered-By: ASP.NET Content-Length: 342 Content-Type: text/html Set-Cookie: ASPSESSIONIDSSTTAADC=LNDHNMIDCHPLLEOPNAMFFGLE; path=/ Cache-Control: private X-Cache: MISS from CACHE-04 Via: 1.1 CACHE-04:3128 (Cacheboy) Connection: close Formato de Resposta HTTP <Versão> <Código_Status> <Msg_Status> <nome-campo-cabecalho_n> : <valor_n> ... <nome-campo-cabecalho_n> : <valor_n> Corpo da Resposta (mensagem HTML) • Documentação: http://www.w3.org/Protocols/rfc2616/rfc2616sec6.html#sec6.1.1 Códigos e Mensagens de Status • Alguns exemplos de códigos e mensagens que indicam o resultado de uma requisição: – 200 OK: Bem sucedida – 301 Moved Permanently: Objeto requisitado foi removido permanentemente; A nova url é especificada no campo de cabeçalho Location, que é recuperada automaticamente pelo software do cliente – 400 Bad Request: Requisição mal formatada – 404 Not Found: Documento inexistente no servidor – 505 HTTP Version Not Supported: Versão do protocolo HTTP não suportada pelo servidor Alguns campos de cabeçalho de resposta • Connection: close Indica ao cliente que o servidor fechará a conexão (TCP) após enviar a mensagem • Date: ... Data de geração da mensagem • Server: ... Identificação do servidor (análogo a User:agent) • Last-Modified: ... Última modificação do recurso no servidor • Content-Length: ... Tamanho do recurso • Content-Type: text/html Tipo do recurso Lista de Campos de Cabeçalho Gerais • Vários campos de cabeçalhos podem ser usados tanto em requisições quanto em respostas • Uma lista completa pode ser obtida no site da W3C – http://www.w3.org/Protocols/rfc2616/rfc2616sec14.html#sec14 Cookies • O protocolo HTTP por si só não mantém estado entre requisições • Cookies são uma forma de termos alguma informação de estado • São compostos de 4 componentes: – Um cabeçalho de cookie na mensagem de resposta – Um cabeçalho na mensagem de requisição – Um arquivo de cookie mantido no cliente e gerenciado pelo browser – Um banco de dados de apoio no site web Cookies • Após uma primeira requisição do cliente, o servidor gera uma identificação para o usuário e insere o campo no cabeçalho da resposta: – Set-cookie: 1678453 • Nas futuras requisições do cliente, o browser irá inserir o cabeçalho abaixo para identificação do cliente – Cookie: 1678453 Conexão a servidores web em Java • O método setPage(String url) da classe javax.swing.JEditorPane recebe uma url e apresenta o conteúdo html renderizado • Entretanto, imagine a situação em que queremos obter o texto de algum recurso html • Como fazemos isso em Java? Conexão a servidores web em Java • A comunicação entre servidores e clientes web é, na essência, uma comunicação via sockets • Ou seja, um cliente (navegador, por exemplo) abre uma conexão com outra máquina na sua porta 80 (porta padrão http) • Para tal, incialmente, utilizaremos classes do pacote java.net (Socket e InetAddress) • A classe InetAddress representa o protocolo IP, e possui métodos úteis como a “conversão” de nomes de máquinas em ip’s Conexão a servidores web em Java - Socket String hostname = "www.siriusnet.com.br"; int port = 80; InetAddress addr; try { // Cria conexão addr = InetAddress.getByName(hostname); Socket socket = new Socket(addr, port); // Prepara cabeçalho BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF8")); wr.write("GET / HTTP/1.1\r\n"); wr.write("\r\n"); // Envia cabeçalho wr.flush(); // Obtém a resposta BufferedReader rd = new BufferedReader(new InputStreamReader(socket.getInputStream())); String line; while ((line = rd.readLine()) != null) { System.out.println(line + "\n"); } wr.close(); rd.close(); socket.close(); } catch (UnknownHostException e) {...} catch (IOException e) {...} Conexão a servidores web em Java • Na linguagem Java há classes que tornam estas conexões mais abstratas • Por exemplo, a classe java.net.UrlConnection • Observe que a manipulação de parâmetros de requisição deve ser feita manualmente com sockets • A classe UrlConnection possui métodos específicos para a manipulação de parâmetros de requisição, por exemplo: – getLastModified(): retorna a data da última modificação – setRequestProperty(key, value): define um parâmetro de requisição Conexão a servidores web em Java - UrlConnection URL url; try { url = new URL("http://www.siriusnet.com.br"); URLConnection conn = url.openConnection(); InputStream in = conn.getInputStream(); int c; while ((c = in.read()) != -1) System.out.print((char)c); } catch (MalformedURLException e) { } catch (IOException e) { } WebCrawler • Com as classes vistas, temos ferramentas suficientes para criarmos um robô para varrer a web • Por exemplo, poderíamos buscar na web onde ocorrem as palavras “Sirius Sistemas Digitais” • Para tal, deveríamos buscar uma página inicial e, à partir desta, buscar recursivamente os links existentes nela WebCrawler – Algoritmo Geral Obtém do usuário o que se deseja buscar e a url inicial Adicione a url à lista de urls a serem pesquisadas Enquanto a lista de urls a serem pesquisadas não for vazia, faça: Obtenha a primeira url da lista Mova a url para uma lista de urls já pesquisadas Confirme que o protocolo da url é http; caso contrário, volte ao início do Enquanto Tente abrir a url (recuperar o documento do servidor web) Percorra o documento procurando por outros links Localize alguma referência (href de uma tag <a/>) Verifique se é algum documento texto (html, txt, xml, etc ..); caso contrário, busque outro Se o link não estiver presente na lista de urls a serem pesquisadas, nem na de já pesquisadas, adicione à lista das urls a serem pesquisadas Processe o documento (por exemplo, percorra procurando por alguma informação desejada – pode ser feito em combinaçao com o item anterior) Exiba resultado da busca “Código de Ética” para acesso a servidores web • Conexões a servidores são custosas e podem prejudicar o desempenho destes • Estas conexões indevidas acontecem com freqüência com os robôs • Existe um padrão para a exclusão de robôs: http://www.robotstxt.org/ • Basicamente, você precisa criar um arquivo texto e deixá-lo publicamente disponível no seu servidor web configurado para exclusão dos robôs “Código de Ética” para acesso a servidores web • A validade deste código depende do bom senso dos implementadores de robôs Referências • http://www.w3schools.com/ – Site com tutoriais on-line rápidos e com muita qualidade • http://del.icio.us/carlosbazilio/java – Meus favoritos sobre o assunto • http://www.w3.org/ – Site do consórcio W3C • http://java.sun.com/developer/technicalArticles/T hirdParty/WebCrawler/ – Artigo que apresenta a implementação de um webcrawler utilizando um applet como interface