6 maneiras de fazer a mesma coisa, o que é considerado boas práticas?

As vezes tem tantas maneiras diferentes de fazer o mesmo código que nós ficamos na dúvida quanto a qual maneira usar. O que seria considerado "boa prática" pela comunidade e o que sua equipe entenderia melhor. Suponhamos que você esteja trabalhando dentro de um método de um Domain Service chamado UmDomainServiceChique(objetoDoDominio) que será chamado por uma API. Você tem uma regra de negócio chique para ser verificada que por enquanto chamarei de VerificaMinhaRegraChiqueComplexa(). Você chama UmDomainServiceChique(objetoDoDominio) e caso VerificaMinhaRegraChiqueComplexa() retorne true você vai querer que UmDomainServiceChique faça o que tem que fazer e a api retornar Ok 200, caso contrário você quer que a API responda um erro qualquer, tipo BadRequest, e retornar uma mensagem dizendo que VerificaMinhaRegraChiqueComplexa deu ruim. Eu vejo 6 maneiras de fazer isso, gostaria de saber a opinião de outrs devs sobre qual seria a maneira menos gambiarr

Busca de CEP com o Lazarus - Parte 5 - Considerações finais

Voltando com tudo de um feriado muito trabalhado e 4 dias sem blogar nada, vamos começar o dia com a parte 5 do tutorial de consulta de CEP com Lazarus.

Como o leitor deve ter percebido nas postagens anteriores, colocamos a chave obtida no site http://www.buscarcep.com.br diretamente no código fonte, rigidamente. Isso é muito feio, não devemos fazer esse tipo de coisa nunca, pois exigiria uma recompilação desnecessária cada vez que fosse necessária a alteração da chave.

Peço também que os leitores não utilizem a chave utilizada nesse blog por motivos óbvios: a chave tem limite de consultas.

As primeiras coisas que vamos mudar é a classe TLazCep, que terá agora a propriedade Chave e as propriedades para trabalhar com proxy: ProxyHost, ProxyPort, ProxyLogin, ProxyPassword.


Se você não usa proxy para se conectar basta deixar os campos relativos a proxy em branco.


A interface da nova classe ficará assim:

TLazCep = class
         private

                FXML: UTF8String;
                FCEP: UTF8String;
                FXMLDoc: TXMLDocument;
                FProxyHost: string;
                FProxyPort: string;
                FProxyLogin: string;
                FProxyPassword: string;
                FChave: UTF8String;

                //sets
                procedure SetCep(const vCep: UTF8String);
                procedure SetProxyHost(const value: string);
                procedure SetProxyPort(const value: string);
                procedure SetProxyLogin(const value: string);
                procedure SetProxyPassword(const value: string);
                procedure SetChave(const value: string);

                //gets
                function GetCep: UTF8String;
                function GetTipoLogradouro: UTF8String;
                function GetLogradouro: UTF8String;
                function GetCidade: UTF8String;
                function GetEstado: UTF8String;
                function GetBairro: UTF8String;
                function GetIBGEEstado: UTF8String;
                function GetIBGECidade: UTF8String;
                function GetIBGEVerificador: UTF8String;
                function GetResultado: UTF8String;
                function GetResultadoTxt: UTF8String;
                function GetProxyHost: string;
                function GetProxyPort: string;
                function GetProxyLogin: string;
                function GetProxyPassword: string;
                function GetChave: string;


                //internal functions
                function GetXmlNode(const vNodeName: DOMString): UTF8String;
         public
               constructor Create;
               destructor Destroy;
               procedure Consultar;
               procedure ConsultarString;
               function GetXML: UTF8String;
               property Cep: UTF8String read GetCep write SetCep;
               property TipoLogradouro: UTF8String read GetTipoLogradouro;
               property Logradouro: UTF8String read GetLogradouro;
               property Cidade: UTF8String read GetCidade;
               property Estado: UTF8String read GetEstado;
               property Bairro: UTF8String read GetBairro;
               property IBGEEstado:UTF8String read GetIBGEEstado;
               property IBGECidade:UTF8String read GetIBGECidade;
               property IBGEVerificador: UTF8String read GetIBGEVerificador;
               property Resultado: UTF8String read GetResultado;
               property ResultadoTxt: UTF8String read GetResultadoTxt;
               property ProxyHost: string read GetProxyHost write SetProxyHost;
               property ProxyPort: string read GetProxyPort write SetProxyPort;
               property ProxyLogin: string read GetProxyLogin write SetProxyLogin;
               property ProxyPassword: string read GetProxyPassword write SetProxyPassword;
               property Chave: string read GetChave write SetChave;

         end;  

E lembre-se que nossa classe tem dois métodos para consulta: o Consulta e o ConsultaString. Ambos devem usar o campo privado para a propriedade chave (FChave) para compor a string do host, assim:

host := 'http://www.buscarcep.com.br/?' + 'cep='+FCEP+'&formato=xml&chave='+UrlEncode(FChave);  

E as chamadas aos métodos Sobrescritos, nessa mesma unit, HttpGetBinary e seu irmão HttpGetText devem ter seus parâmetros preenchidos com as informações de proxy, como segue:

HttpGetBinary(host, Response, FProxyHost, FProxyPort, FProxyLogin, FProxyPassword);
//(...)
HttpGetText(host, Response, FProxyHost, FProxyPort, FProxyLogin, FProxyPassword);

Faremos também algumas melhorias para que as propriedades já retornem strings do tipo UTF8, assim faremos a conversão por dentro para que ela não precise ser feita por fora e eliminamos erros de conversão de strings vazias ou ponteiros nulos. Faremos também toda uma verificação se foi possivel ou não estabelecer uma conexão e se uma string XML foi retornada e um XMLDoc criado.

Colocaremos uma mensagem de erro dizendo quando não foi possível obter a conexão e/ou o xml e colocaremos no formulario principal quatro edits para servirem de parâmetros para o proxy.

Se a chave ou algum outro parâmetro estiver errado a conexão pode funcionar, mas o XML pode trazer uma mensagem de erro, por isso iremos tratar essa mensagem de erro logo que chegar.

Trataremos também do tipo de logradouro. Incluiremos esse campo do XML na classe.

Visualmente nossa form ficará assim:
Form FrmLazCep


O lfm da form ficará assim:

object Form1: TForm1
  Left = 252
  Height = 314
  Top = 281
  Width = 718
  Caption = 'Form1'
  ClientHeight = 314
  ClientWidth = 718
  LCLVersion = '0.9.28.2'
  object Label1: TLabel
    Left = 8
    Height = 14
    Top = 8
    Width = 20
    Caption = 'CEP'
    ParentColor = False
  end
  object Label2: TLabel
    Left = 96
    Height = 14
    Top = 8
    Width = 32
    Caption = 'Chave'
    ParentColor = False
  end
  object Label3: TLabel
    Left = 280
    Height = 14
    Top = 8
    Width = 20
    Caption = 'URL'
    ParentColor = False
  end
  object Label4: TLabel
    Left = 552
    Height = 14
    Top = 15
    Width = 51
    Caption = 'ProxyHost'
    ParentColor = False
  end
  object Label5: TLabel
    Left = 552
    Height = 14
    Top = 39
    Width = 49
    Caption = 'ProxyPort'
    ParentColor = False
  end
  object Label6: TLabel
    Left = 552
    Height = 14
    Top = 61
    Width = 54
    Caption = 'ProxyLogin'
    ParentColor = False
  end
  object Label7: TLabel
    Left = 552
    Height = 14
    Top = 84
    Width = 75
    Caption = 'ProxyPassword'
    ParentColor = False
  end
  object mResquest: TMemo
    Left = 8
    Height = 202
    Top = 104
    Width = 176
    Lines.Strings = (
      '"Conversas" HTTP:'
      '============'
    )
    TabOrder = 0
  end
  object mResponse: TMemo
    Left = 192
    Height = 202
    Top = 104
    Width = 168
    Lines.Strings = (
      'Respostas:'
      '============='
    )
    TabOrder = 1
  end
  object edCep: TEdit
    Left = 8
    Height = 21
    Top = 24
    Width = 80
    TabOrder = 2
    Text = '01136-001'
  end
  object btTestarTlazCep: TButton
    Left = 368
    Height = 25
    Top = 56
    Width = 120
    Caption = 'Testar Classe TLazCep'
    OnClick = btTestarTlazCepClick
    TabOrder = 3
  end
  object btTeste: TButton
    Left = 112
    Height = 25
    Top = 56
    Width = 136
    Caption = 'Testar HttpSend Direto'
    OnClick = btTesteClick
    TabOrder = 4
  end
  object btTestaUrlEncode: TButton
    Left = 8
    Height = 25
    Top = 56
    Width = 96
    Caption = 'Testa UrlEncode'
    OnClick = btTestaUrlEncodeClick
    TabOrder = 5
  end
  object edUrl: TEdit
    Left = 280
    Height = 21
    Top = 24
    Width = 256
    TabOrder = 6
  end
  object edChave: TEdit
    Left = 96
    Height = 21
    Top = 24
    Width = 179
    TabOrder = 7
    Text = '1Z3s3/2ZjDt.dcyiLuBy/6mitlDNgt/'
  end
  object mXml: TMemo
    Left = 368
    Height = 202
    Top = 104
    Width = 168
    Lines.Strings = (
      'XML:'
      '============'
    )
    TabOrder = 8
  end
  object mEndereco: TMemo
    Left = 544
    Height = 202
    Top = 104
    Width = 168
    Lines.Strings = (
      'Endereço:'
      '============'
    )
    TabOrder = 9
  end
  object edProxyHost: TEdit
    Left = 632
    Height = 21
    Top = 8
    Width = 80
    TabOrder = 10
  end
  object edProxyPort: TEdit
    Left = 632
    Height = 21
    Top = 32
    Width = 80
    TabOrder = 11
  end
  object edProxyLogin: TEdit
    Left = 632
    Height = 21
    Top = 54
    Width = 80
    TabOrder = 12
  end
  object edProxyPassword: TEdit
    Left = 632
    Height = 21
    Top = 77
    Width = 80
    EchoMode = emPassword
    PasswordChar = '*'
    TabOrder = 13
  end
end

O arquivo .pas da form, onde terá o uso da classe TLazCep com as novas propriedades e campos ficará assim:
unit Unit1; 

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils,  LResources, Forms, Controls, Graphics,
  Dialogs, StdCtrls, LazCep, httpsend, DOM;

type

  { TForm1 }

  TForm1 = class(TForm)
    btTestarTlazCep: TButton;
    btTeste: TButton;
    btTestaUrlEncode: TButton;
    edCep: TEdit;
    edChave: TEdit;
    edProxyHost: TEdit;
    edProxyPort: TEdit;
    edProxyLogin: TEdit;
    edProxyPassword: TEdit;
    edUrl: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    mResquest: TMemo;
    mResponse: TMemo;
    mXml: TMemo;
    mEndereco: TMemo;
    procedure btTestaUrlEncodeClick(Sender: TObject);
    procedure btTestarTlazCepClick(Sender: TObject);
    procedure btTesteClick(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end; 

var
  Form1: TForm1; 

implementation

{ TForm1 }

procedure TForm1.btTestarTlazCepClick(Sender: TObject);
begin
     with TLazCep.Create do
     try

          //setando a chave
          Chave:= edChave.Text;

          //setando atributos de proxy
          ProxyHost:=edProxyHost.Text;
          ProxyPort:=edProxyPort.Text;
          ProxyLogin:=edProxyLogin.Text;
          ProxyPassword:=edProxyPassword.Text;


          Cep:=edCep.Text;
          Consultar;
          mXml.Lines.Append(GetXML);
          mEndereco.Lines.Append(Resultado);
          mEndereco.Lines.Append(ResultadoTxt);
          mEndereco.Lines.Append(TipoLogradouro);
          mEndereco.Lines.Append(Logradouro);
          mEndereco.Lines.Append(Bairro);
          mEndereco.Lines.Append(Cidade);
          mEndereco.Lines.Append(Estado);
          mEndereco.Lines.Append(IBGECidade);
          mEndereco.Lines.Append(IBGEEstado);
          mEndereco.Lines.Append(IBGEVerificador);

          mXml.Append('============');
          mEndereco.Append('============');

          ConsultarString;
          mXml.Lines.Append(GetXML);
          mEndereco.Lines.Append(Resultado);
          mEndereco.Lines.Append(ResultadoTxt);
          mEndereco.Lines.Append(TipoLogradouro);
          mEndereco.Lines.Append(Logradouro);
          mEndereco.Lines.Append(Bairro);
          mEndereco.Lines.Append(Cidade);
          mEndereco.Lines.Append(Estado);
          mEndereco.Lines.Append(IBGECidade);
          mEndereco.Lines.Append(IBGEEstado);
          mEndereco.Lines.Append(IBGEVerificador);
     finally
            Free;
     end;
end;

procedure TForm1.btTestaUrlEncodeClick(Sender: TObject);
begin
  edUrl.Text:='http://www.buscarcep.com.br/?' + 'cep='+UrlEncode(edCep.Text)+'&formato=xml&chave='+UrlEncode(edChave.Text);
end;

procedure TForm1.btTesteClick(Sender: TObject);
var
  HTTP: THTTPSend;
  sucesso: boolean;
begin

  sucesso := false;
  HTTP := THTTPSend.Create;
  try

    edUrl.Text:= 'http://www.buscarcep.com.br/?' + 'cep='+edCep.Text+'&formato=xml&chave='+UrlEncode('1Z3s3/2ZjDt.dcyiLuBy/6mitlDNgt/');
    sucesso := HTTP.HTTPMethod('GET', edUrl.Text);
    mResquest.Lines.Add('URL: ' + edUrl.Text);
    mResquest.Lines.add('---------------------');
    mResquest.Lines.Add(HTTP.Headers.Text);
    mResquest.Lines.add('---------------------');
    mResquest.Lines.add(HTTP.ResultString);
    mResquest.Lines.add(inttostr( HTTP.ResultCode));

    if sucesso then
    begin
        HTTP.Document.Seek(0, soFromBeginning);
        mResponse.Lines.LoadFromStream(HTTP.Document);
    end;
  finally
    HTTP.Free;
  end;
end;

initialization
  {$I unit1.lrs}

end.


A unit LazCep completa segue abaixo:
{
        usando TXmlDocument:
        http://wiki.lazarus.freepascal.org/XML_Tutorial
        http://wiki.lazarus.freepascal.org/XML_Tutorial/pt

        encoding:
        http://wiki.lazarus.freepascal.org/LCL_Unicode_Support

        Serviços de CEP:
        http://www.autocep.com.br/download_autocep_webservice.htm
        http://www.byjg.com.br/site/xmlnuke.php?xml=onlinecep
        http://www.buscarcep.com.br/
        http://www.maniezo.com.br/webservice/soap-server.php
}

unit LazCep;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, DOM, XMLRead, httpsend, dialogs;

type

         { TLazCep }

         TLazCep = class
         private

                FXML: UTF8String;
                FCEP: UTF8String;
                FXMLDoc: TXMLDocument;
                FProxyHost: string;
                FProxyPort: string;
                FProxyLogin: string;
                FProxyPassword: string;
                FChave: UTF8String;

                //sets
                procedure SetCep(const vCep: UTF8String);
                procedure SetProxyHost(const value: string);
                procedure SetProxyPort(const value: string);
                procedure SetProxyLogin(const value: string);
                procedure SetProxyPassword(const value: string);
                procedure SetChave(const value: string);

                //gets
                function GetCep: UTF8String;
                function GetTipoLogradouro: UTF8String;
                function GetLogradouro: UTF8String;
                function GetCidade: UTF8String;
                function GetEstado: UTF8String;
                function GetBairro: UTF8String;
                function GetIBGEEstado: UTF8String;
                function GetIBGECidade: UTF8String;
                function GetIBGEVerificador: UTF8String;
                function GetResultado: UTF8String;
                function GetResultadoTxt: UTF8String;
                function GetProxyHost: string;
                function GetProxyPort: string;
                function GetProxyLogin: string;
                function GetProxyPassword: string;
                function GetChave: string;


                //internal functions
                function GetXmlNode(const vNodeName: DOMString): UTF8String;
         public
               constructor Create;
               destructor Destroy;
               procedure Consultar;
               procedure ConsultarString;
               function GetXML: UTF8String;
               property Cep: UTF8String read GetCep write SetCep;
               property TipoLogradouro: UTF8String read GetTipoLogradouro;
               property Logradouro: UTF8String read GetLogradouro;
               property Cidade: UTF8String read GetCidade;
               property Estado: UTF8String read GetEstado;
               property Bairro: UTF8String read GetBairro;
               property IBGEEstado:UTF8String read GetIBGEEstado;
               property IBGECidade:UTF8String read GetIBGECidade;
               property IBGEVerificador: UTF8String read GetIBGEVerificador;
               property Resultado: UTF8String read GetResultado;
               property ResultadoTxt: UTF8String read GetResultadoTxt;
               property ProxyHost: string read GetProxyHost write SetProxyHost;
               property ProxyPort: string read GetProxyPort write SetProxyPort;
               property ProxyLogin: string read GetProxyLogin write SetProxyLogin;
               property ProxyPassword: string read GetProxyPassword write SetProxyPassword;
               property Chave: string read GetChave write SetChave;

         end;


function UrlEncode(url: DOMString):UTF8String;

implementation

function UrlEncode(url: DOMString): UTF8String;
var
   substitutos:      array[1..20] of  string = ('%21', '%2A', '%27', '%28', '%29', '%3B', '%3A', '%40', '%26', '%3D', '%2B', '%24', '%2C', '%2F', '%3F', '%25', '%23', '%5B', '%5D', '%2E');
   substituidos:  array[1..20] of  char = ('!', '*', '''', '(', ')', ';', ':', '@', '&', '=', '+', '$', ',', '/', '?', '%', '#', '[', ']', '.');
   i, j: integer;
   tmp: string;
begin
     for i := 1 to Length(url) do
     begin
          for j := 1 to 20 do
          begin
               if url[i] = substituidos[j] then
               begin
                  tmp := substitutos[j];
                  break;
               end
               else
                   tmp := url[i];
          end;
          Result := Result + tmp;
     end;
end;


function HttpGetBinary(const URL: string; const Response: TStream;
         ProxyHost, ProxyPort, ProxyUser, ProxyPass: string): Boolean;
var
  HTTP: THTTPSend;
begin
  HTTP := THTTPSend.Create;
  try
    HTTP.ProxyHost := ProxyHost;
    HTTP.ProxyPort := ProxyPort;
    HTTP.ProxyUser := ProxyUser;
    HTTP.ProxyPass := ProxyPass;
    Result := HTTP.HTTPMethod('GET', URL);
    if Result then
    begin
      Response.Seek(0, soFromBeginning);
      Response.CopyFrom(HTTP.Document, 0);
    end;
  finally
    HTTP.Free;
  end;
end;

function HttpGetText(const URL: string; const Response: TStrings;
         ProxyHost, ProxyPort, ProxyUser, ProxyPass: string): Boolean;
var
  HTTP: THTTPSend;
begin
  HTTP := THTTPSend.Create;
  try
    HTTP.ProxyHost := ProxyHost;
    HTTP.ProxyPort := ProxyPort;
    HTTP.ProxyUser := ProxyUser;
    HTTP.ProxyPass := ProxyPass;
    Result := HTTP.HTTPMethod('GET', URL);
    if Result then
      Response.LoadFromStream(HTTP.Document);
  finally
    HTTP.Free;
  end;
end;

{ TLazCep }

procedure TLazCep.SetCep(const vCep: UTF8String);
begin
     FCEP:=vCep;
end;

procedure TLazCep.SetProxyHost(const value: string);
begin
  FProxyHost:=value;
end;

procedure TLazCep.SetProxyPort(const value: string);
begin
     FProxyPort:=value;
end;

procedure TLazCep.SetProxyLogin(const value: string);
begin
     FProxyLogin:=value;
end;

procedure TLazCep.SetProxyPassword(const value: string);
begin
     FProxyPassword:=value;
end;

procedure TLazCep.SetChave(const value: string);
begin
  FChave:=value;
end;

function TLazCep.GetCep: UTF8String;
begin
     Result := FCEP;
end;

function TLazCep.GetTipoLogradouro: UTF8String;
begin
    Result := GetXmlNode('tipo_logradouro');
end;

function TLazCep.GetLogradouro: UTF8String;
begin
     Result := GetXmlNode('logradouro');
end;

function TLazCep.GetCidade: UTF8String;
begin
    Result := GetXmlNode('cidade');
end;

function TLazCep.GetEstado: UTF8String;
begin
    Result := GetXmlNode('uf');
end;

function TLazCep.GetBairro: UTF8String;
begin
   Result := GetXmlNode('bairro');
end;

function TLazCep.GetIBGEEstado: UTF8String;
begin
    Result := GetXmlNode('ibge_uf');
end;

function TLazCep.GetIBGECidade: UTF8String;
begin
    Result := GetXmlNode('ibge_municipio');
end;

function TLazCep.GetIBGEVerificador: UTF8String;
begin
     Result := GetXmlNode('ibge_municipio_verificador');
end;

function TLazCep.GetResultado: UTF8String;
begin
     Result := GetXmlNode('resultado');
end;

function TLazCep.GetResultadoTxt: UTF8String;
begin
     Result := GetXmlNode('resultado_txt');
end;

function TLazCep.GetProxyHost: string;
begin
     Result := FProxyHost;
end;

function TLazCep.GetProxyPort: string;
begin
     Result := FProxyPort;
end;

function TLazCep.GetProxyLogin: string;
begin
     Result := FProxyLogin;
end;

function TLazCep.GetProxyPassword: string;
begin
     Result := FProxyPassword;
end;

function TLazCep.GetChave: string;
begin
     Result := FChave;
end;

function TLazCep.GetXmlNode(const vNodeName: DOMString): UTF8String;
var
   temp: DOMString;
begin

  try

     if (FXML <> '') and (FXMLDoc <> nil)  then
     begin
          if (FXMLDoc.FindNode('webservicecep') <> nil) and
             (FXMLDoc.FindNode('webservicecep').FindNode('retorno') <> nil) and
             (FXMLDoc.FindNode('webservicecep').FindNode('retorno').FindNode(vNodeName) <> nil) then
          begin
               temp := FXMLDoc.FindNode('webservicecep').FindNode('retorno').FindNode(vNodeName).TextContent;
               if (temp <> '') then
                  Result := AnsiToUtf8(temp)
               else
                   Result := '';
          end
          else
              Result := '';
     end
     else
         Result := '';

  except
      Result := '';
  end;

end;

constructor TLazCep.Create;
begin
  //constructor
end;

destructor TLazCep.Destroy;
begin
     //destructor
end;

procedure TLazCep.ConsultarString;
var
    host: string;

    {StringList que conterão o resultado do site}
    Response: TStringList;
    S: TStringStream;

begin

  host := 'http://www.buscarcep.com.br/?' + 'cep='+FCEP+'&formato=xml&chave='+UrlEncode(FChave);

  {destruindo o XMLDoc caso já exista}
  if(FXMLDoc <> nil) then
  try
       FXMLDoc.Free;
  except
  end;

  FXMLDoc := nil;

  try

    {criando o stringlist que conterão o resultado do site}
    Response:=TStringList.Create;

    {consultando com httpGetText ou httpGetBinary}
    if HttpGetText(host, Response, FProxyHost, FProxyPort, FProxyLogin, FProxyPassword) then
    begin

         if  (FXML <> '') then
         begin
              try
                  {capturamos em uma string o conteudo do response}
                  FXML:=Response.Text;
                  {criamos uma string stream a partir dele para alimentar o XMLDoc}
                  S := TStringStream.Create(FXML);
                  {Criamos e alimentamos o XMLDoc}
                  ReadXMLFile(FXMLDoc, S);
                  {coloco o encoding desejado}
                  FXMLDoc.Encoding:='iso-8859-1';


                  //aqui pode ser uma exception também
                  if StrToInt(Resultado) <= 0 then
                     ShowMessage('Erro ao consultar CEP: ' + ResultadoTxt);

              finally
                  S.Free;
              end;
         end
         else
             FXML:='';
    end
    else
    begin
         FXML := '';
         raise Exception.Create('Não foi possível estabelecer uma conexão!');
    end;
  finally
    Response.Free;
  end;
end;

procedure TLazCep.Consultar;
var

    host: string;

    {streams que conterão o resultado do site}
    Response: TMemoryStream;
    S: TStringStream;

begin

  host := 'http://www.buscarcep.com.br/?' + 'cep='+FCEP+'&formato=xml&chave='+UrlEncode(FChave);

  {destruindo o XMLDoc caso já exista}
  if(FXMLDoc <> nil) then
  try
       FXMLDoc.Free;
  except
  end;

  FXMLDoc := nil;

  try

    {criando os streams que conterão o resultado do site}
    Response:=TMemoryStream.Create;

  {consultando com httpGetText ou httpGetBinary}
  if HttpGetBinary(host, Response, FProxyHost, FProxyPort, FProxyLogin, FProxyPassword) then
  begin
   try
    {posiciona o stream de resposta no inicio}
    Response.Seek(0, soFromBeginning);
    {Cria e Lê o documento XML a partir da stream}
    ReadXMLFile(FXMLDoc, Response);
    {posiciona o stream de resposta no inicio novamente}
    Response.Seek(0, soFromBeginning);
    {Copia o stream de resposta para um string stream, recém criado, para extrair dele uma string}
    S := TStringStream.Create(FXML);
    S.CopyFrom(Response, Response.Size-1);
    s.Seek(0, soFromBeginning);
    {atribui o conteudo todo a propriedade XML da classe, para termos acesso ao xml de retorno}
    if (s <> nil)and(s.DataString <> '') then
    begin
     FXML:= s.DataString;
    end
    else
    begin
     FXML:= '';
    end;
    {coloco o encoding desejado}
    FXMLDoc.Encoding:='iso-8859-1';

                                //aqui pode ser uma exception também
                                if StrToInt(Resultado) <= 0 then
                                   ShowMessage('Erro ao consultar CEP: ' + ResultadoTxt);

   finally
    S.Free;
   end;
  end
                else
                begin
                    FXML := '';
                    raise Exception.Create('Não foi possível estabelecer uma conexão!');
                end;
  finally
    Response.Free;
  end;
end;

function TLazCep.GetXML: UTF8String;
begin
     if  (FXML <> '') then
        Result := FXML
     else
         Result := '';
end;


end.


Não se esqueça: Se você não usa proxy para se conectar basta deixar os campos relativos a proxy em branco.

Desculpem pelo tamanho do post. Mesmo dividindo em 5 partes a parte concludente acabou ficando grande demais.

O código fonte completo dessa aplicação pode ser baixado aqui

Espero que tenha sido útil a todos para o aprendizado de HTTPSend e XML.

Num próximo post falaremos apenas sobre a função URLEncode e como ela pode ser melhorada. Falaremos também sobre HtmlEntities. Até lá.



Have fun ;)


Ir Para:


Parte 1 | Parte 2 | Parte 3 | Parte 4 | Parte 5

Comentários

  1. Olá Vitor, muito bom e muito bem explicado seu exemplo, gostei bastante, só queria saber como posso adicionar o HTTPUser e HTTPPassword para sites com autenticação.

    ResponderExcluir
  2. Eu nunca usei esses componentes, Alexandre. Teria que tentar fazer um exemplo/estudo deles. Use esse source como ponto de partida, e se você conseguir poste ele aqui, eu adiciono um post e te dou os créditos, ou você posta em um blog seu. To meio corrido hoje para fazer esses exemplos.

    ResponderExcluir
  3. da este erro lazcep.pas(358,27) Error: identifier idents no member "Encoding"

    ResponderExcluir
  4. Da este erro lazcep.pas(358,27) Error: identifier idents no member "Encoding"
    Será que alterou algo na unit

    ResponderExcluir
  5. Esse código é muito antigo. Provavelmente algo mudou no webservice e agora eles exigem mais informações.

    ResponderExcluir

Postar um comentário

Postagens mais visitadas deste blog

Uso de memória no SQL Server

Busca de CEP com o Lazarus - Parte 1 - UrlEncode

Botão Add This para adicionar seu post em qualquer rede