Numa primeira olhada, a utilidade do HTTP não parece muito diferente do FTP usado para fazer downloads. O código abaixo, por exemplo, obtém o documento padrão do site do Google Brasil, isto é, a página HTML que é exibida quando se digita o endereço do Google Brasil num navegador. No exemplo, estou usando o componente TIdHTTP da paleta do projeto Indy:
var lResponse : TStringStream;
begin
lResponse := TStringStream.Create('');
try
{ lResponse conterá a página HTML requisitada :}
idHttp1.Get('http://www.google.com.br', lResponse);
finally
lResponse.Free();
end;
Apesar de não ser necessário configurar explicitamente um servidor/porta e usuário/senha como no FTP, o resultado final é o mesmo: o download de um arquivo remoto. Na verdade, a infraestrutura da internete mapeia automaticamente o endereço do Google para um servidor/porta; nesse caso, o usuário e senha é dispensável pois se trata de um site público que permite acesso anônimo.begin
lResponse := TStringStream.Create('');
try
{ lResponse conterá a página HTML requisitada :}
idHttp1.Get('http://www.google.com.br', lResponse);
finally
lResponse.Free();
end;
Se olharmos mais a fundo, no entanto, veremos que o HTTP é mais flexível porque permite adicionar parâmetros à requisição enviada ao servidor. Na prática, isso dá ao servidor a chance de montar dinamicamente a resposta mais adequada à solicitação feita. As APIs de serviços publicados na internete normalmente são baseados no HTTP e se valem dos parâmetros pra flexibilizar as requisições. É o caso, por exemplo, do Google Docs e de outros serviços do Google, que usam a API de dados da empresa. Em outro post, eu mostro como se comunicar com o Google Docs usando a API de dados para ler os documentos salvos nesse serviço.
Se você já trabalhou com HTML, deve ter notado que a sintaxe dos Forms inclui uma "action", um método de envio e os diversos campos que serão preenchidos pelo usuário da página, sendo admitido até mesmo a existência de campos invisíveis contendo informações pré alimentadas.
Para relembrar o significado dessas propriedades do Form HTML : A "action" é o endereço na internete para onde a requisição será submetida. O "método" diz repespeito a como e quais informações serão enviadas; os valores mais comuns são GET (as informações são formatadas e acrescentadas ao endereço da "action", que então é enviado ao servidor) ou POST (as informações são transportadas à parte e não é possível enxergá-las na barra de endereço do navegador).
O form de pesquisa do Google, por exemplo, admite que você selecione a língua na qual deseja obter as repostas e, claro, os termos a serem pesquisados. O exemplo abaixo submete ao Google uma pesquisa em português com o nome do blog:
var lURL : String;
lResponse : TStringStream;
begin
lResponse := TStringStream.Create('');
try
lURL := 'http://www.google.com.br/search?' +
'hl=pt-BR&' +
'q=balaio%20tecnologico';
idHttp1.Get(lURL, lResponse);
lResponse.Position := 0;
{ Exemplo de uso do response : carregar o conteúdo num RichEdit : }
reResp.Lines.LoadFromStream(lResponse);
finally
lResponse.Free();
end;
Veja que cada parâmetro é composto de um nome (o mesmo configurado nas tags input do form) seguido por um sinal de igual (=) e o valor que o parâmetro deve assumir (normalmente, os próprios valores fornecidos pelo usuário). Cada parâmetro é concatenado ao anterior através de um "E Comercial" (&).lResponse : TStringStream;
begin
lResponse := TStringStream.Create('');
try
lURL := 'http://www.google.com.br/search?' +
'hl=pt-BR&' +
'q=balaio%20tecnologico';
idHttp1.Get(lURL, lResponse);
lResponse.Position := 0;
{ Exemplo de uso do response : carregar o conteúdo num RichEdit : }
reResp.Lines.LoadFromStream(lResponse);
finally
lResponse.Free();
end;
Ambos os parâmetros considerados pelo exemplo estão incluídos no form da pesquisa do Google. Ou seja, se você souber quais são os parâmetros de um form, poderá simular via Delphi a requisição que ele submeteria numa página da Web e, então, obter exatamente a mesma reposta, podendo tratá-la do modo que for mais apropriado para sua aplicação.
Por causa dessa facilidade de simular requisições via programação, muitos sites se protegem implementando um CAPTCHA. Trata-se de uma imagem com um texto embutido que é gerada dinamicamente pelo servidor de modo que apenas operadores humanos consigam ler. O texto deve, então, ser digitado num campo e enviado junto com as demais informações. A requisição só é atendida se o texto estiver correto.
Como podemos notar pelo exemplo, usar o GET para recuperar um documento pode ser problemático se certas informações sensíveis - como uma senha - tiverem que ser transmitidas direto na URL. Nestes casos, é recomendado usar o POST pois com ele as informações trafegam por outros meios.
O uso do POST também é simples. Basta passar os parâmetros num TStringList separado. A URL do "action" é informada sem quaisquer decorações extras:
var lParams :TStringList;
lResponse : TStringStream;
begin
lParams := TStringList.Create;
lResponse := TStringStream.Create('');
try
lParams.Add('filt=all');
lParams.Add('p=balaio%20tecnologico');
idHttp1.Post('http://br.search.yahoo.com/search', lParams, lResponse);
{ Exemplo de uso do response : carregar o conteúdo num RichEdit : }
lResponse.Position := 0;
reResp.Lines.LoadFromStream(lResponse);
finally
lParams.Free();
lResponse.Free();
end;
Neste exemplo, usei o Yahoo! porque o Google não implementa POST para pesquisas.lResponse : TStringStream;
begin
lParams := TStringList.Create;
lResponse := TStringStream.Create('');
try
lParams.Add('filt=all');
lParams.Add('p=balaio%20tecnologico');
idHttp1.Post('http://br.search.yahoo.com/search', lParams, lResponse);
{ Exemplo de uso do response : carregar o conteúdo num RichEdit : }
lResponse.Position := 0;
reResp.Lines.LoadFromStream(lResponse);
finally
lParams.Free();
lResponse.Free();
end;
Ajustes ainda mais finos para submeter a requisição podem ser configurados na propriedade Request do TIdHTTP. Com ele, é possível ajustar o tipo de documento que se espera receber de volta (HTML, XML, etc.), o tipo de encoding, se há necessidade de passar por um proxy, etc.
36 comentários :
Se eu coloco o site para abrir a partir de um edit da Unknown Protocol, como contorno?
Você colocou uma caixa de texto (edit) na tela para o usuário poder entrar com o endereço do site? Neste caso, certifique-se de que o endereço digitado está completo, incluindo o "http" no início. Os navegadores hoje acrescentam isso automaticamente mas chamadas via API (como as do post) não. Então, se o usuário não passar isso no seu edit, o seu programa pode completá-lo antes de chamar get ou post.
[]s
No caso seria correto eu criar o idHttp dentro da thread ou quando chamo na unit principal? Caso eu queria fazer vários downloads.
No caso algo como:
Crio o idhttp
crio a thread indicando o idhttp criado.
E quando terminar o downlaod eu dou um free na thread?
Como vou identificar a thread correta se eu uso a mesma variável para todas as threads?
O TidHTTP não precisa estar embutido num TForm. Por isso, você pode criar o TidHTTP como um membro da sua thread e instanciá-lo manualmente, evitando a necessidade de sincronizar o uso do recurso compartilhado.
Se você tem alguma restrição para criar mais que um TidHTTP, dê veja o post Trabalhando com Threads em Delphi - Seções Críticas. Nele há exemplos de sincronização no uso de recursos compartilhados em ambiente multi-thread.
[]s
Luis, utilizei a tua sugestão de rotina para buscar o retorno de uma url que no caso o retorno é um xml, ao executar:
IdHTTPxml.get('urldoclientecomparametros',lresponse);
XMLresposta.Active := True;
XMLresposta.Encoding := 'iso-8859-1';
XMLresposta.LoadFromStream(lResponse);
Não está vendo como um xml e sim apenas dividindo em duas linhas, sendo a segunda todo o conteudo do xml como um texto. O que pode estar errado ?
Sobre o comentario anterior, queria adicionar o seguinte. qdo visualizo o codigo fonte do retorno desta URL, realmente volta todo o xml em uma unica linha.
Você consegue enxergar o XML de retorno no navegador(IE, Firefox ou Chrome) ? Isto é, ao invés de carregar no TDomXml, salve o retorno para um arquivo e veja se o navegador consegue abrí-lo corretamente.
PS:Não tenho certeza mas talvez vc precise voltar a posição do lResponse para o começo do stream antes de carrega-lo no XMLResposta. Algo como lResponse.Position := 0;
[]s
Olá amigo!
Muito bom seu tutorial, ótimos exemplo!
Tenho uma dúvida em relação ao exemplo do método POST, que é o seguinte. Como posso pegar o endereço do site, exibir o código fonte no RichEdit só que eu queria utilizar um Edit para digitar o endereço do site e pegar o código fonte. Poderia me responder essa dúvida por gentileza? Email de contato: nerd.supreme@gmail
Paz e espero respostas suas, sucesso com blog! ;)
Daniel
Uma vez que você tenha colocado o edit no form, basta substituir o endereço fixo do post pelo valor da propriedade Text do seu edit:
idHttp1.Post(Edit1.Text, lParams, lResponse);
Como agora o usuário precisa informar o endereço, vc tb pode usar o código pra carregar o conteúdo dentro do evento OnClick de um botão na tela.
[]s
Utilizando o idHTTP.Post retornou o seguinte erro 'HTTP/1.1 500 INTERNAL SERVER ERRO' ao dar o Post. Que erro seria este, abaixo esta o meu código:
lParams := TStringList.Create;
lResponse := TStringStream.Create('');
lParams.Add('razao_social=' + QuotedStr(cdsClientePortsDSC_RAZAO_SOCIAL.AsString));
IdHttp.Request.Username := 'xxx@yahoo.com.br'; //Aqui eu entro com o Usuário que a Api exige
IdHttp.Request.Password := '112233'; //Aqui eu entro com a Senha que a Api exige
IdHttp.Request.BasicAuthentication := True;
IdHttp.Post('http://69.164.203.63:8080/api/v1/clientes', lParams, lResponse);
Dempsey
Essa mensagem indica que o servidor não foi capaz de atender sua requisição porque deu "pau" na lógica interna dele.
Pode ser um valor errado que você passou ou alguma informação esperada mas não fornecida pelo seu código.
Reveja a documentação sobre o modo de se comunicar com o site pra determinar o que está faltando (ou sobrando).
[]s
Boa tarde Luis não estou conseguindo montar o post, quando o vem com javascript exemplo abaixo:
javascript:__doPostBack('ctl00$frameCorpo$gdvAgrupamentoDetalhe$ctl02$gdvListaNfe$ctl02$lnkNnf','')">122308
IdHTTP1.Post('www.set.rn.gov.br/uvt/nfeentrada.aspx', Params, Stream);
Bruno
Como vc mesmo diz, o __doPostBack é um código javascript e não representa URL para onde se possa submeter uma requisição. Vc terá que entender como funciona a função pra determinar qual é a URL base e quais são os parâmetros necessários. A URL base deve ser a mesma da página contendo a chamada ao script. Como parâmetros, são esperados no mínimo os valores para __EVENTTARGET e __EVENTARGUMENT.
O artigo Understanding the JavaScript __doPostBack Function dá uma boa noção sobre esse assunto.
[]s
Estou tentando enviar um XML para um webservice do INMETRO. Estou com dúvidas em como enviar. O WS usa REST, com método POST e retorna um XML de resposta. Meu código está assim:
var
dado : TStringList; // Variável que contém o XML a ser enviado
retorno : TStringStream;
host : string; // Endereço do INMETRO
begin
retorno := TStringStream.Create('');
host := 'https://webservicedesenv.cronotacografo.inmetro.rs.gov.br/informarEnsaio';
dado := TStringList.Create;
dado.text := textoxml; // textoxml é uma Widestring recebida com o XML
IdHTTP.Request.ContentType := 'text/xml';
IdHTTP.Post(host, dado, retorno);
Acontece o seguinte erro : IOHandler value is not valid.
Alguém tem uma ideia de como fazer isso ?
Para enviar um XML deve ser usado outra forma, ou pode ser como fiz ?
Egon
Como você está manipulando um endereço seguro (HTTPS), terá quer fornecer um iohandler apropriado para lidar com a conexão. Instancie um TIdSSLIOHandlerSocket e use-o como iohandler do seu idHTTP.
Obs: Pode ser necessário encontrar na web as DLLs do OpenSSL para usar com sucesso o handler seguro.
[]s
Ok. Deu certo, funcionou, tive que buscar como vc me alertou a versão adequada das DLLs. No meu caso uso DELPHI 7 com INDY 10, a versão da DLL é a 0.9.6a...
Agora estou enfrentando algumas dificuldades relativas ao site do INMETRO, mas não é relacionado ao componente...
Muchas gracias pela atenção...
Obrigado pela resposta Luís Gustavo... Realmente era dados que deixei de enviar...
Agora, tenho outra dúvida, preciso pegar uns Headers de respostas de HTTP.Post, como faço isso??? Já tentei de tudo q eh jeito aq e não consegui.
Não sei se me expressei bem...
Querendo pegar o retorno do WebService (O restorno vem pelo Header)... é um codigo de nome 'MeusPedidosID' que me informa que meu Post deu certo e me retorna o codigo do registro inserido...
Dempsey
Por conveniência, o conteúdo da resposta do Post é lançado no stream passado como parâmetro à função.
Se quiser obter mais detalhes sobre a resposta, inspecione as propriedades do Response que é membro do idHttp responsável pelo Post.
Entre outros dados, o Response traz o tipo de conteúdo retornado (ex: HTML), o charset usado, data e hora do retorno, data e hora de expiração do conteúdo e os headers enviados pelo servidor (RawHeaders) na forma de uma lista.
[]s
Obrigado novamente... Perfeito....
IdHttp.Post(lUrl, lParametros, Response); //Enviando
lResposta := IdHttp.Response.RawHeaders[5]; //Retorno
Como faço para verificar se o arquivo existe ?
Faça o Get conforme mostra o post e verifique o valor da propriedade ResponseCode do TIdHttp. Ela estará com valor 404 quando o arquivo buscado não existir.
Outros valores possíveis são listados neste link.
[]s
Esqueci de mensionar... uso delphi 7 com indy 9
Checar pelo erro 404 só vai funcionar se o servidor não redirecionar sua requisição. Parece ser esse o caso do endereço que vc usou no seu código: o servidor não encontra o arquivo mas ao invés de retornar erro 404 ele retorna uma página válida.
Uma alternativa, neste caso, é testar o Response.ContentType do IdHTTP para saber se a resposta contém uma imagem ou um HTML.
[]s
Deu certinho conforme você mencionou:
vRestring := IdHTTP1.Response.ContentType;
strm1.Seek(0,soFromBeginning);
if (vRestring <> 'text/html') then
begin
foto1.LoadFromStream(strm1);
cxfoto1.Picture.Assign(foto1);
end;
Muito obrigado!
Boa tarde Luiz Gustavo,
vi aqui no blogger algumas ajudas suas para o pessoal.
Gostaria de saber se você pode me ajudar quanto a elaboração da interação de uma aplicação delphi2007 com o google drive. Seria upload e download de arquivos apenas.
Roger
Que tipo de dificuldade você encontrou? Nunca trabalhei com o Drive mas imagino que funcione como o Docs, onde você fornece a URL de um serviço e passa outras informações necessárias através de entradas no header - como os dados de login ou o nome da planilha com a qual quer trabalhar. As repostas destas requisições são formatadas como XML, de modo que seu programa terá que lê-las e interpretá-las de acordo com a documentação do próprio serviço. Para lidar com planilhas, a documentação está em https://developers.google.com/google-apps/spreadsheets/?csw=1.
[]s
Não encontrei código em delphi para que eu possa tentar fazer a comunicação com o drive. Vou trabalhar apenas colocando arquivos e retirando arquivos (upload e download).
A unica coisa que encontrei, foi um objeto de terceiro mas que vale por 30 dias apenas, este eu consegui fazer o upload e o downloads, mas para autenticar tenho que efetuar o login no google chrome e não posso fazer isso, porque se não qualquer usuário vê os arquivos que estão la no drive.
Quanto ao objeto de terceiro, eu queria ver se tem como efetuar o upload e o download do arquivo sem usar este objeto, ou seja, queria criar algo que fizesse este processo.
Roger
Comece procurando a documentação que descreve como integrar uma aplicação com o Drive. Ela provavelmente trará dicas dos passos para estabelecer a comunicação com os servidores do Google.
[]s
Olá, Luis! Gostaria de saber se você poderia me ajudar. Estou tentando enviar um SMS usando método Post para seguinte
URL= https://sms.comtele.com.br/api/{sua_chave}/sendmessage?sender={remetente}&receivers={destinatarios}&content={conteudo}
como devo passar esses parâmetros? estou tentando assim:
lParams := TStringList.Create;
lResponse := TStringStream.Create('');
try
lParams.Add('G2');
lParams.Add('8597403015');
lParams.Add('Teste de envio');
lHTTP.Post('https://sms.comtele.com.br/api/f7cd25bf-0f1c-4bbf-9fd0-9a51c8ba4c99/sendmessage?', lParams, lResponse);
lResponse.Position := 0;
reResp.Lines.LoadFromStream(lResponse);
finally
lParams.Free();
lResponse.Free();
Mas sempre recebo o erro de Bad Request.
Obrigado pela atenção
Rafael
Pelo formato da URL me parece que deve ser usado o método GET. Monte a URL final, adicionando ao endereço base os pares nomes/valores de parâmetros. Algo como :
https://sms.comtele.com.br/api/{sua_chave}/sendmessage?sender=G2&receivers=8597403015&content=teste
Se preferir, veja a documentação do seu provedor para saber se ele aceita requisições com post e com quais nomes de parâmetros isso deve ser feito. Obs: ao adicionar o parâmetro, o nome deve ser incluído:
lParams.Add('sender=G2');
lParams.Add('receivers=8597403015');
lParams.Add('contente=Teste de envio');
[]s
Ola Luiz,
Estou tentando passar o coidio abaixo atravez de post mas não tá dando certo. O que estou fazendo de errado?
lParams := TStringList.Create;
lResponse := TStringStream.Create('');
reResp.Lines.Clear;
try
lParams.Add('codigo_transacao=5');
lParams.Add('loja_primaria=teste');
lParams.Add('nome_primario=teste');
lParams.Add('Senha_primaria=teste');
// lParams.Add('loja_primaria=3477535000146');
// lParams.Add('nome_primario=gatesteacs');
// lParams.Add('Senha_primaria=34740216');
lParams.Add('versao=3.95');
lParams.Add('compra=1');
lParams.Add('produto=1417');
lParams.Add('valor=5.00');
lParams.Add('ddd=85');
lParams.Add('fone=88276717');
idHttp1.Post('https://www.cellcard.com.br/teste/integracao_xml.php', lParams, lResponse);
lResponse.Position := 0;
reResp.Lines.LoadFromStream(lResponse);
finally
lParams.Free();
lResponse.Free();
end;
Olá Luiz,
O codigo abaixo não está dando certo. O que tem de errado com ele
lParams := TStringList.Create;
lResponse := TStringStream.Create('');
reResp.Lines.Clear;
try
lParams.Add('codigo_transacao=5');
lParams.Add('loja_primaria=teste');
lParams.Add('nome_primario=teste');
lParams.Add('Senha_primaria=teste');
// lParams.Add('loja_primaria=3477535000146');
// lParams.Add('nome_primario=gatesteacs');
// lParams.Add('Senha_primaria=34740216');
lParams.Add('versao=3.95');
lParams.Add('compra=1');
lParams.Add('produto=1417');
lParams.Add('valor=5.00');
lParams.Add('ddd=85');
lParams.Add('fone=88276717');
idHttp1.Post('https://www.cellcard.com.br/teste/integracao_xml.php', lParams, lResponse);
lResponse.Position := 0;
reResp.Lines.LoadFromStream(lResponse);
finally
lParams.Free();
lResponse.Free();
end;
Rômulo
Que tipo de problema você encontrou com esse código? Há alguma mensagem de erro? Tecnicamente, ele me pareceu correto...
[]s
Dempsey Silva voce conseguiu integrar com meus pedidos..
adiciona skype olivercds
Postar um comentário
OBS: Os comentários enviados a este Blog são submetidos a moderação. Por isso, eles serão publicados somente após aprovação.
Observação: somente um membro deste blog pode postar um comentário.