/ NodeJS

República Virtual e NodeJS

Se você já fez algum formulário de cadastro, é provável que você tenha tido que fazer alguma consulta a um CEP e é muito provável que você já tenha ouvido falar do http://republicavirtual.com.br/cep/ que tem uma base atualizada e free dos CEPs.

Eles são uma referência fantástica para quem quer fazer um sistema de consulta de CEPs e não quer sofrer baixando os arquivos em .mdb dos correios. Isso é incrivelmente importante quando se usa tecnologias que não são Microsoft. PHP, Perl, e é claro, nosso amigo Node.

Eu recentemente estava brincando com o Node e precisei fazer uma consulta de CEPs. Fui diretamente no nosso amigo Republica Virtual. Eles possuem uma página repleta de exemplos de como deve ser implementado o código. Para minha surpresa, não havia um código em Node. Assim, eu decidi fazer um exemplo de utilização do serviço deles usando o Node e publiquei um projeto no GitHub para vocês poderem brincar.

Consideração e bom senso

Antes de sair fazendo consultas no serviço deles, lembre-se que eles tem custos para manter o serviço no ar. Dessa forma, quanto menos você consultar o sistema deles, melhor. Para isso é recomendado que você crie uma base local com os CEPs e consulte a sua base antes de ir consumir os recursos deles. Um pouco de consideração e bom senso não machucam ninguém né?

O mínimo do mínimo

O primeiro passo é você conseguir buscar as informações de um serviço remoto. No node isso é relativamente fácil. Existem centenas de bibliotecas HTTP, o axios e o request são as que eu uso com alguma frequência.

Vamos ao primeiro código em node. No seu projeto, importe a biblioteca de sua preferência:

npm install --save request

ou via Yarn

yarn add request

Isso vai dispnibilizar a biblioteca para uso no seu projeto.

Agora vamos criar um arquivo qualquer para testar:

arquivo.js

const request = require('request');

// CEP Que vamos procurar:
let cep = "04523001";

// faz a busca
request('http://republicavirtual.com.br/web_cep.php?cep=' + cep + '&formato=json', 
  function(err, res, body){
    console.log(body);
  }
);

OK - que tal traduzir isso pra vcs...

  • Na primeira linha, eu importo a biblioteca request.
  • Depois eu defino o cep que iremos consultar.
  • Finalmente, o grosso do arquivo acontece na linha que começa com request
  • A gente busca do republica virtual o cep desejado e seta o callback para fazer um console.log com os dados recebidos.

Execute o arquivo usando o comando:

node arquivo.js

você deveria receber uma resposta do tipo:

{"resultado":"1","resultado_txt":"sucesso - cep completo","uf":"SP","cidade":"S\u00e3o Paulo","bairro":"Indian\u00f3polis","tipo_logradouro":"Avenida","logradouro":"Macuco"}

Bom já fizemos o básico né? Consumimos um request lá do República Virtual com sucesso. Agora precisamos pensar no resto.

Você pode ver no meu Git o fluxo que estou seguindo - mas aqui vai ele para você não precisar sair daqui:

Você busca o CEP usando o metodo *modelo.findCEP('00000-000')*

O CEP é valido? Se sim, fazemos um consulta na base local.
Se o CEP existe na base local, retornamos o documento.
Se o CEP não existe na base, fazemos uma consulta no Republica Virtual.
Se o CEP não existe no RV retornamos um erro avisando que não foi encontrado o CEP
Se o CEP existe, salvamos ele na base local, e retornamos o documento salvo.

Explicando o código do github

Você deve estar curioso para saber como tudo funciona né?

Vou passar bem por cima do código para que você possa entender seu funcionamento e implementar essa solução nos seus projetos.

O projeto tem na sua raiz o arquivo server.js. Ele é responsável por iniciar o express (eu não vou entrar em detalhes do que é o express, mongo, body-parser e etc neste post), definir o banco e setar as rotas.

Nosso projeto tem duas rotas - a principal (que possue um formulário que permite você digitar um cep para consulta), e a página de resposta.

Vejamos as nossa duas rotas e views para entender o que está acontecendo rapidamente.

No arquivo routes/routes.js temos as duas rotas definidas, a primeira:

router.get('/', function(req, res){
    res.render('home.ejs');
});

chama o arquivo home.ejs que está localizado na pasta de views.

Esse arquivo tem apenas um form com um campo de entrada para o CEP que iremos consultar.

<form action="/resposta" method="post">
    <h2>Formulário</h2>
    <label for="cepval">Digite seu CEP</label>
    <input type="text" id="cepval" name="txtcep" placeholder="00000-000" /><br/>
    <input type="submit" value="enviar" />
</form>

Toda mágica acontece na parte da resposta - quando invocamos o modelo de endereços e fazemos a consulta do CEP.
Na segunda rota do arquivo routes.js temos o seguinte:

router.post('/resposta', function(req, res){
    let end = new Endereco();
    end.findCEP(req.body.txtcep).then((result)=>{
        res.render('resposta.ejs',{result:result});
    }).catch((err)=>{
        console.log('Erro',err);
    });
});

Nessa rota eu crio um novo Endereco, uso a chamada findCEP pasasndo o CEP entrado no formulário. Se tivermos um resultado, eu mostro a view resposta.ejs caso contrário, dou um console.log do erro.

Até aí bem simples. Vejamos o que esse "findCEP" faz:

// remover caracteres que nao são digitos
const arrumaCEP = (cep) => {
    return cep.replace(/[^\d]/,'');
};

// chamada findCEP
EnderecoSchema.methods.findCEP = (cep)=>{
    return new Promise((resolve, reject)=>{
        // normalizar o cep
        cep = arrumaCEP(cep);
        
        // fazer busca em promessa
        let endp = Endereco.findOne({cep:cep}).exec();
        endp.then( (end) => {
            if (end){
                // achamos um endereco na base - resolva a promessa
                resolve(end);
            }else{
                // nao achamos um endereco - vamos buscar no republica virtual
                rp('http://republicavirtual.com.br/web_cep.php?cep=' + cep + '&formato=json')
                .then( (results) => {
                    // voltaram os resultados - vamos verificar se temos um resultado positivo
                    let json = JSON.parse(results);
                    if (json.resultado==1) {
                        // OK temos um endereço - vamos salvar ele na base
                        let tmp = {
                            tipo_log: json.tipo_logradouro,
                            logradouro: json.logradouro,
                            bairro: json.bairro,
                            cidade: json.cidade,
                            estado: json.uf,
                            pais: 'Brasil',
                            cep:cep};
                        return Endereco.create(tmp);
                    }else{
                        // nao achamos o cep no republica - rejeitar a promessa
                        reject(("SEM RESULTADOS"));
                    }
                })
                .then((results)=>{
                    if (results==undefined) reject( new Error(results))
                    // devolver o objeto de repsosta
                    resolve(results);
                })
                .catch((err) => {
                    console.log("Erro: ", err);
                });
            }
        })
        .catch((err)=>{
            console.log("error: ", err);
        });
    });
};

Tá, é bastante coisa para se digerir... vamos quebrar isso em pequenos pedaços mastigáveis.

A primeira coisa que faço é arrumar o cep com a chamada arrumaCEP. Ela basicamente retorna um cep composto apenas por números. Assim, seu eu digitar o CEP: '03510-002s', a função irá retornar '03510002'.

Na sequência, eu faço uma consulta no banco local:
Endereco.findOne({cep:cep}).exec();
Se eu acho um endereço, eu resolvo a promessa e volto o valor encontrado para a rota.

Caso eu não encontre um resultado:

else{
   // nao achamos um endereco - vamos buscar no republica virtual

a gente vai lá no RV buscar os dados (como fizemos anteriormente no nosso exemplo simples só que agora com a biblioteca request-promise)

Se eu tenho um resultado, eu salvo ele na base e retorno o objeto recém salvo:

// OK temos um endereço - vamos salvar ele na base
let tmp = {
    tipo_log: json.tipo_logradouro,
    logradouro: json.logradouro,
    bairro: json.bairro,
    cidade: json.cidade,
    estado: json.uf,
    pais: 'Brasil',
    cep:cep};
return Endereco.create(tmp);

Claro, essa é a versão super resumida do arquivo - tirando todas as partes de validação, promises e etc... No github você tem o código completo para sua análise.

Acho que dá pra ter uma idéia de como funciona o projeto e de quais partes você pode querer usar para implementar no seu projeto né?

Gregory Brown

Gregory Brown

Baker, cake designer, cook and just by chance, a full featured developer that is passionate about technology.

Read More