O Protocolo HTTP – Parte 06

Introdução

No post anterior (O Protocolo HTTP – Parte 05), o Web Site local de testes com o TOTVS Application Server ganhou mais uma funcionalidade, vimos como o Browse montou uma requisição de POST de um formulário HTML com campos de preenchimento do usuário, e mais detalhes sobre GET e POST. Agora, vamos fazer alguns ajustes nas páginas HTML do site de testes, e ver se ou quais impactos terão estes ajustes, e acrescentar mais algumas coisas …

Utilizando HTML5

HTML versão 5 traz novos identificadores, recursos, e já está bem suportado pelos Web Browses de mercado. Embora marcadores foram declarados “obsoletos”, já que é para colocar a mão na massa, é elegante declarar na primeira linha de cada página HTML, que a versão usada é a HTML5. Para isso, basta inserir a linha abaixo como primeira linha do arquivo:

<!DOCTYPE html>

HTML Head e HTML Body

De forma similar ao protocolo HTTP, uma página HTML possui identificadores para declaração de elementos de cabeçalho de página (Header), e para delimitar o corpo do HTML (Body), inclusive delimitar o inicio e fim do HTML. Se nada disso for colocado, e voce simplesmente criar um arquivo HTML sem estes identificadores, normalmente o Web Browse vai interpretar tudo como HTML Body… Mas é deveras recomendável que você monte as suas páginas HTML declarando onde fica o que, vide exemplo abaixo:

<!DOCTYPE html>
<html>
<head>
<title>Título do Documento</title>
</head>
<body>
Conteúdo do Documento...
</body>
</html>

Entre o inicio e final do cabeçalho HTML, delimitado pelos marcadores <head> e </head>, usamos outros marcadores HTML para identificar características (ou meta-dados) de um documento e/ou página HTML, como um título — usado na barra de navegação e por mecanismos de busca –, scripts — executados pelo web browser na estação onde a página e/ou documento HTML está sendo mostrado, entre outras coisas interessantes.

Salve esse arquivo com o nome “html5.htm” na pasta htto-root, e com o Application Server em execução, abra a URL http://locahost/html5.htm, e vejamos como a tela apareceu:

Se o arquivo foi salvo usando CodePage 1252, os caracteres acentuados serão mostrados corretamente. Se ele foi salvo pelo NOTEPAD usando UTF-8, serão mostrados caracteres “estranhos” nos acentos … Isso é UTF-8 interpretado como CP1252 …

Agora, vamos pegar esse “padrão”, e refazer os arquivos do nosso site de testes. Eles devem ficar assim:

  • Arquivo default.htm
<!DOCTYPE html>
<html>
<head>
<title>Meu primeiro Web Site - Página Inicial</title>
</head>
<body>
<h3>Meu primeiro Web Site</h3>
<a href="testepost.htm">Teste de Post</a>
</body>
</html>
  • Arquivo testepost.htm
<!DOCTYPE html>
<html>
<head>
<title>Meu primeiro Web Site - Teste de POST</title>
</head>
<body>
<h3>Teste de Post</h3>
<hr>
<form name="mydataform" method="post" action="testepost.htm">
<input type="text" name="CAMPO1"></input>
<input type="text" name="CAMPO2"></input>
input type="submit"/>
</form>
<hr>
<a href="/">Voltar ao Início</a>
</body>
</html>

Agora, com tudo funcionando, vamos passar a usar a codificação UTF-8 nos nossos arquivos HTML, bastando para isso suas coisas :

  • Usando por exemplo o editor NOTEPAD++, insira logo após a linha de abertura do header <head>, antes do <title>, a linha abaixo:
<meta charset="UTF-8">
  • Agora, use a opção Encoding -> Convert to UTF-8, e salve o arquivo. ( Verifique se o arquivo já não está com esta codificação … os editores de textos simples mais recentes, mesmo o NOTEPAD do Windows, já codifica o arquivo como UTF-8 se você cria o arquivo e preenche com algum caractere acentuado.)

E, finalmente, vamos abrir novamente os arquivos no Web Browser. Com o conteúdo codificado em UTF-8, e a informação meta charset no HTML head, tudo deve ser mostrado corretamente pelo Web Browser.

Executando o POST novamente, agora informando caracteres acentuados

No teste de post anterior, sem utilizar o charset UTF-8 nos nossos HTML(s), a letra “a” minúsculo acentuado foi enviada pelo Web Browser ao realizar o POST usando o (Codepage) CP-1252, e enviada pelo post codificada como “%E1″. Agora que estamos usando UTF-8, se acessarmos a tela de teste de post, digitarmos no primeiro campo “Olá” e no segundo “Mundo”, e verificarmos usando o painel do desenvolvedor como o Google Chrome codificou a letra “á”, veremos novidades:

Reparem que agora a letra “á” foi codificada como “%C3%A1” .. Essa é a seqüência de bytes no padrão UTF-8 que representa a letra a minúscula com acento agudo no alfabeto latino. Deste ponto em diante, todos os arquivos HTML dos nossos testes passam a declarar HTML5 e codificação em UTF-8. 😀 E, conseqüentemente, o Web Browser vai entender que, se o conteúdo do arquivo é UTF-8, e existe um formulário de entrada de dados, esses dados serão codificados como UTF-8.

Mas, o que eu ganho com isso ?

Utilizando UTF-8, é possível codificar e representar múltiplos alfabetos e caracteres de outros idiomas — mais de 1 milhão — do formato internacional “Unicode”, até “emoticons”. UTF-8 signfica “Unicode Transformation Format – 8 bits”. Eu posso por exemplo, usar uma ferramenta como o Google Translator, e traduzir “olá” de português para Russo e Chinês, e colocar dois parágrafos no arquivo “default.htm”, copiando e colando os caracteres da tradução, usando o Notepad++ ou o NOTEPAD do Windows … veja como o ficou o arquivo:

E, ao ser mostrado no Web Browser, ficou assim:

Vamos colocar uma imagem no HTML ?

Eu peguei uma foto do meu perfil do Facebook, salvei como uma uma imagem JPG, usei o PaintBrush do Windows para fazer um “resize” na imagem .. e ela ficou um “quadrado” de 192×192 pixels…. Salvei essa imagem no disco, com o nome “mypicture.jpg”, dentro de uma nova pasta chamada “pictures”, criada dentro da pasta http-root.

Agora, vamos editar a nossa pagina “default.htm”, e colocar essa imagem para ser mostrada no HTML, acrescentando as duas linha em negrito abaixo, antes do </body>:

<hr>
<img src="./pictures/mypicture.jpg">

A linha com <hr> insere uma barra horizontal no documento, e o marcador <img permite a inserção de uma imagem dentro do HTML. Reparem que, para a imagem ser localizada, eu informo na propriedade “src=” a informação “./pictures/mypicture.jpg”. Vamos ver como ficou ?

Agora, ao usar as ferramentas do desenvolvedor do Google Chrome, e pedir para recarregar essa página, vamos ver uma informação nova:

Quando o Web Browser pediu a página “default.htm” ao HTTP Server, ele recebeu apenas a página HTML… Após receber a página e começar a “desenhar” o HTML na tela, o Web Browse encontrou o marcador de imagem, para mostrar a imagem “./pictures/mypicture.jpg” … Então, o Web Browse abre internamente uma nova solicitação de GET, pedindo esse arquivo para o HTTP Server. O HTTP Server, ao receber o pedido, verifica que o arquivo existe em disco, na pasta identificada, e retorna o arquivo ao Browser, que mostra a imagem na tela.

Como o HTTP server sabia que a imagem era do tipo JPEG ?

Então, existem algumas extensões de arquivo conhecidas e tratadas pelo Totvs Application Server como servidor de HTTP. Ao receber uma instrução GET, foi informado no protocolo que o recurso “mypicture.jpg” foi solicitado .. Ao receber uma solicitação, o servidor verifica qual o path, nome e extensão do recurso solicitado, e baseado na extensão informada (.jpg ou .jpeg), ele já sabe que é um arquivo em disco, e que o formato do arquivo é “image/jpeg”. Veja abaixo a lista de arquivos tratadas pelo HTTP Server — Totvs Application Server, e o content-type retornado para cada uma:

HTM ou HTML : text/html
XML         : text/xml
TXT         : text/plain
GIF         : image/gif
JPG ou JPEG : image/jpeg
BMP         : image/bmp
SVG         : image/svg+xml
ZIP         : application/zip
DOC         : application/msword
AU          : audio/au
WAV         : audio/wav
MPEG ou MPG : video/mpeg
AVI         : video/avi
CSS         : text/css
JS          : application/x-javascript
TODAS AS DEMAIS : application/octet-stream";

Dessa forma, baseado na extensão utilizada no nome do recurso solicitado pelo Browser, verificando a extensão do recurso, ele já sabe qual Content-type de retorno deve ser utilizado para o Web Browser interpretar o recurso corretamente. Caso seja um arquivo de extensão desconhecida pelo Application Server, ele retorna ao Browser que o conteúdo do arquivo é uma seqüencia de bytes (
octet stream“, ou “seqüencia de octetos” — afinal 1 byte corresponde a uma seqüência de 8 bits) 😛

Por que foi criada a pasta “pictures” ? A imagem não poderia estar na pasta “http-root”?

Sim, claro que poderia. Criar pastas ou subdiretórios a partir da pasta raiz de publicação (no nosso caso, http-root) permite ORGANIZAR melhor os arquivos dentro do site. Podemos criar uma pasta para centralizar ou agrupar as folhas de estilo utilizadas (CSS), imagens, scripts (JavaScript), etc …. Calma que a gente chega lá ..rs..

Referências

O Protocolo HTTP – Parte 05

Introdução

No post anterior (O Protocolo HTTP – Parte 04), vimos como funciona por dentro uma requisição GET de HTTP, como passar parâmetros pela URL, e como fazer um fonte em AdvPL com os tratamentos de códigos de retorno necessários. Agora, vamos ver mais alguns detalhes do GET , e ver por dentro o método POST do HTTP, primeiro pelo visão do protocolo e pelo Web Browse.

HTTP GET – Mais informações

Como já vimos anteriormente, uma requisição do tipo GET do HTTP possui restrições de tamanho e não deve ser usada para trafegar dados sensíveis. Um outro ponto muito importante é : Uma requisição do tipo GET somente é usada para CONSULTAR uma informação, e não atualizar ou mudar o estado de uma informação. Como o “dite de uma página” que começou a ser criado no post anterior ainda está muito simples, ainda tem muita coisa a ser vista sobre o HTML e como as páginas são processadas pelo Web Browser.

Quando precisamos mudar o estado de uma informação em um Web Site, usamos uma requisição POST, não apenas por ser mais flexível quando ao tamanho dos dados, mas também pela forma de passagem dos dados — dentro do “Corpo do HTTP” — não visível na URL — mas também pelos comportamentos das aplicações intermediárias envolvidas, a começar pelo Web Browser.

Fazendo um POST pelo Web Browser

Lembrando que o Web Browser carrega páginas HTML e arquivos do Web Server, para fazer uma requisição POST, precisamos fazer no mínimo uma página HTML com um formulário (form), indicando para onde (qual URL) os dados desse formulário será enviado, e como será enviado — GET ou POST. E, antes de mais nada, para conhecimento: Ao abrir o seu Web Browser e digitar uma URL qualquer, o Web Browse vai sempre fazer um GET daquela URL.

Agora, vamos incrementar a página de entrada do Web Site de testes, editando o arquivo “default.htm” da pasta “http-root” com o NOTEPAD ou outro editor de textos ASCII simples, e acrescentar a linha em negrito no arquivo … a nova página deve ficar assim:

<html>
<body">
<h3>Meu primeiro Web Site</h3>
<a href="testepost.htm">Teste de Post</a>
</body>
</html>

Ao executar o Totvs Application Server configurado para servidor de HTTP, e acessar o endereço http://localhost/, deve ser mostrado o seguinte:

O elemento <a > no HTML é uma “âncora”, onde podemos referenciar um conteúdo qualquer, e o Web Browser vai criar um LINK na tela para este conteúdo. No caso, criamos um link para uma nova página no Web Site, chamada “testepost.htm” (que ainda não existe no servidor). Se clicarmos no link “Teste de Post”, deve ser apresentada a tela de erro 404 – Not Found pelo Web Browser.

Agora, vamos criar — usando o editor de textos simples — o arquivo “testepost.htm”, dentro da pasta http-root, com o seguinte conteúdo:

<html>
<body>
<h3>Teste de Post</h3>
<hr>
<form name="mydataform" method="post" action="testepost.htm">
<input type="text" name="CAMPO1"></input>
<input type="text" name="CAMPO2"></input>
<input type="submit"/>
</form>
<hr>
<a href="/">Voltar ao Início</a>
</body>
</html>

Neste exemplo simples, criamos um formulário HTML, nomeado “mydataform”, definimos que o método de submeter esse formulário ao Web Server será “POST”, e na propriedade “action” definimos que ele deve abrir novamente o arquivo “testepost.htm”. Agora sim, ao clicar no link “Teste de Post” da página inicial do nosso site de testes, devemos ver o seguinte no Web Browser:

Testando o formulário

Preencha o primeiro campo na tela com “Ola”, o segundo com “Mundo”, e clique no botão “Enviar”. E, para nossa surpresa …

O que aconteceu ?

Bem, primeiramente … o Web Browse está “reclamando” do retorno que ele recebeu do servidor … ele fez a requisição POST do HTTP, para o arquivo “/testepost.htm”, os dados foram enviados — já vamos ver como confirmar isso –, mas o HTTP Server não retornou “nada”… sim, “nada”. Agora, vamos ver POR QUE.

  • Uma requisição de POST recebida pelo HTTP Server — no nosso caso estamos usando o Totvs Application Server — somente será “atendida” corretamente pelo Totvs Application Server, se ele estiver configurado para execução de páginas DINÂMICAS — conhecidas por “AdvPL ASP”. Calma, vamos ver isso em muitos detalhes mais para a frente. Lembre-se dos posts anteriores, que por hora o Totvs Application Server está configurado como servidor HTTP de páginas e arquivos ESTÁTICOS. Isto é, você pode montar um site “fixo”, com páginas e fotos … mas ele vai aceitar apenas GET, para mostrar as páginas e fazer download de arquivos. — Também vou montar exemplo disso …

De qualquer forma, o Web Browse não sabe disso… e ele vai fazer o que o formulário mandou .. POST para “testepost.htm”. Agora, vamos entrar nos detalhes de como o Web Browse montou o POST, usando neste caso o F12 do Google Chrome — que abre as “ferramentas do desenvolvedor” na página que você está acessando.

Refazendo o teste no Chrome

Estamos com o Google Chrome aberto em “http://localhost/testepost.htm&#8221;, vendo aquela tela de erro … clique no botão “Voltar” na parte superior esquerda da janela do Web Browser, e você deve ver novamente a tela “testepost.htm”, inclusive com os campos preenchidos.

Agora, pressione a tecla F12 do teclado, OU, pressione a combinação de teclas CONTROL + SHIFT + I — Isso abre a janela de ferramentas do desenvolvedor. Se a janela de desenvolvedor aparecer “dentro” da janela do Browse, aumente o tamanho da tela ( maximize a janela ). E você deve ver algo assim:

Agora,

Na janela do desenvolvedor, existem varias “abas”. Clique na aba “Network”, ela é que nos interessa nesse momento. Agora, vamos fazer a mágica acontecer … clique novamente no botão “Enviar”… e vamos ver o que aparece na janela do desenvolvedor, do lado direito:

Repare que a primeira linha das atividades de rede (Network) do Web Browser aparece em vermelho, indicando uma falha. O retorno recebido do HTTP Server foi um pacote de 0 bytes — ele não retornou “nada”… Agora, vamos ver o que foi enviado, clicando com o mouse em cima no nome “testepost.htm” que aparece em vermelho … Vou redimensionar a tela para a janela do desenvolvedor ficar maior ..

Ao clicar sobre uma requisição na lista de requisições feitas pelo Web Browser, ele mostra os detalhes dessa requisição, mostrando primeiro definições gerais, e logo depois em “Request Headers” tudo o que ele enviou no HTTP Header da requisição realizada — são muitas informações. As duas mais importantes agora são “Content-Type: application/x-www-form-urlencoded” , e “Content-Length: 23“.

Elas indicam que essa requisição de POST possui um Http Body, onde o conteúdo possui 23 bytes, e está CODIFICADO no formato “x-www-form-urlencoded“. Agora, se “rolarmos” essa tela para baixo, veremos algo interessante no final da página:

O Web Browse mostra que os valores preenchidos nos campos de input dentro do formulário foram enviados … Se clicarmos em “view source”, veremos COMO ele realmente enviou o corpo (Http Body) dessa requisição:

CAMPO1=Ola&CAMPO2=Mundo

Agora, conte quantas letras e símbolos aparecem nessa linha … Exatamente 23, que é o Content-length indicado no HTTP Header 😀 Após o HTTP Header, foi enviado um HTTP Body.

E, você também reparou ? Os dados estão “codificados” como se fossem os dados de uma requisição do tipo GET — URL Encoded … por isso o Web Browser informou que o Content-Type é “x-www-form-urlencoded” ( dados codificados igual a uma URL).

E AGORA ?

Faça um teste… volte para a página anterior, e no lugar da palavra “Mundo”, digite “Você S&A”.. e veja novamente nos detalhes da requisição, como os dados foram enviados pelo Web Browser:

CAMPO1=Ola&CAMPO2=Voc%EA+S%26A

Repare QUATRO coisas importantes:

  • Ao usar um caractere acentuado (ê – letra e minúscula com acento circunflexo), ela foi enviada utilizando o PERCENT ENCODING contendo o valor hexadecimal “EA” (recomendo fortemente a leitura de O que é CODEPAGE e ENCODING – Parte 01 e demais posts). Se consultarmos a tabela de caracteres do Windows (em português ou inglês, CP1252 ou CodePage 1252), veremos que o código Hexadecimal EA representa a letra “ê”
  • O espaço em branco foi codificado com o sinal de “+” (mais)
  • Como usamos no conteúdo do texto um caractere separador de parâmetros do protocolo “&”, ele foi codificado como “%26” — que na prática é o código hexadecimal do caractere “&”
  • E , por fim, o Content-length aumentou para 33 … veja, o tamanho do HTTP Body é o numero de bytes usados para representar os dados CODIFICADOS.

Mais informações, mais …

Se você ligar o log de requisições HTTP do Totvs Application Server, você vai reparar que o conteúdo do POST não e mostrado no log … ele não é mostrado pois pode ser muito grande, e codificado de formas que ele não pode ser visualmente visto no log, por isso o LOG das requisições recebidas mostra apenas o HTTP Header no Application Server.

Já existem outros posts sobre AdvPL ASP, mas que não entram “tão fundo” no protocolo … se voce quiser complementar seus conhecimentos, recomendo a leitura a partir do Protheus e AdvPL ASP – Parte 01 e demais posts da seqüência. Mais para frente vamos abordar boa parte do que foi mostrado sobre AdvPL ASP aqui no protocolo HTTP, porém com uma visão mais “interna” de como as coisas funcionam 😀

F.A.Q.

E, como cada post pode levantar muitas dúvidas, vamos ver algumas… respondidas de forma simples.

  • Esses exemplos de HTML, estão “corretos” ? Que versão de HTML esses arquivos estão usando ?

Então, os exemplos funcionam, o Web Browse “engole”, mas eles não estão usando as melhores práticas de codificação. Por convenção, a primeira linha de um arquivo HTML “elegante” informa a versão do HTML utilizada. Para indicar o uso de HTML5, a primeira linha do arquivo HTML deve ser

<!DOCTYPE html>

A partir de agora, nossos exemplos vão ser “elegantes”, e declarar o uso de HTML5.

  • Por quê foi usado o CodePage CP-1252 ? Em nenhum lugar isso aparece ?

Essa é a pergunta de 1 milhão ! No meio do HTTP Header da requisição feita pelo Web Browser, ele informa em alguns pontos o que ele “aceita” de retorno …

Accept-Encoding: gzip, deflate, br
Accept-Language: pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,es;q=0.6,sv;q=0.5

Como o Browser está configurado para Português do Brasil, rodando em uma máquina Windows, e em nenhum momento o HTTP Server informa um detalhamento sobre quais caracteres estão sendo utilizados — ao pedir o arquivo “default.htm” ou “testepost.htm”, é informado no HTTP Header apenas que o content-type é “text/html”, sem mais detalhes inclusive no corpo do HTML — o Web Browser assume que ele deve tratar o retorno baseado no que ele aceita .. e trata os caracteres acentuados enviados na página como “CP1252”.

  • CP-1252, WINDOWS-1252 e ANSI são a mesma coisa ?

R: Na prática, SIM. Em versões anteriores do Windows, os CodePages utilizados pelo DOS ( 437 e 850, para inglês e português, respectivamente) foram nomeados como code-pages OEM, e a nova tabela ASCII do Windows como ANSI, e posteriormente WINDOWS-1252 e CP-1252. Existe um codepage muito parecido com o CP1252, usado ainda em algumas aplicações, chamado IS8-8859-15 — mas que possui diferenças na interpretação gráficas dos caracteres em faixas específicas. ** Curiosidade: Desde a primvera versão do Totvs Application Server, em meados de 1999, para recompilar e executar os códigos do ERP da Microsiga – ainda escritos para MS-DOS — havia a necessidade de conversões de OEM para ANSI e vice-versa, desde arquivos de texto e dados. Para isso, foram disponibilizadas as funções OemToAnsi() e AnsiToOem() na linguagem AdvPL, que estão presentes desde então.

  • Posso usar UTF8 dentro do meu arquivo HTML ?

SIM, mas isso exige que você informe dentro do HTML que os caracteres do corpo do HTML ( HTML Body – não confunda com HTTP Body, o corpo do HTML começa após a declaração “<body>” e termina na declaração “</body>” ). Vamos entrar em mais detalhes disso mais para a frente, mas a título de curiosidade, uma das formas de você especificar que o texto dentro do seu HTML está codificado como UTF-8, é acrescentar antes do <body> a sequencia de linhas abaixo:

 <head>
 <meta charset="UTF-8">
 </head>

Quer fazer um teste ? Abra o arquivo “testepost.htm” com um editor um pouco mais avançado ( recomendo o NOTEPAD++), troque a codificação do arquivo para UTF-8, e coloque acento na palavra início … faça isso, salve e reabra a página no Web Browse — sem colocar o meta-charset .. Você vai ver que no lugar do “í” vão aparecer duas letras esquisitas … ( UTF8 interpretado erroneamente como CP1252), e depois de acrescentar as linhas head e meta-charset, salvar e recarregar o arquivo pelo Web Browser … o acento aparece certinho ! Depois vamos ver como fazer isso usando o HTTP Header 😀

*** Usar UTF-8 traz outras implicações, que veremos mais adiante. A mais imediata é que, ao abrir um campo de digitação de informação para o usuário preencher, os dados enviados para o servidor HTTP estarão codificados em UTF-8. E isso exige que você trate isso adequadamente ao receber os dados para a execução de páginas dinâmicas. Não se preocupe com isso agora, veremos esses detalhes mais para a frente.

  • Existem outros Content-Type usados para POST ?

R: SIM, para muitas outras finalidades. Normalmente o Web Browser usa o Content-Type “multipart/form-data” para submeter arquivos (POST de formulários HTML com upload de arquivos para o HTTP Server), e diversos outros Content-Types são usados na comunicação entre aplicações por serviços SOAP ou REST sobre HTTP, como text/xml, text/json … calma que veremos isso em detalhes mais pra frente.

Conclusão

Quanto mais informações são apresentadas, mais informações são necessárias. Aos poucos vamos abrindo o que tem por baixo do capô do Web Browse e dos protocolos, e vamos ver várias formas de se fazer muita coisa ! Espero que este conteúdo sempre lhe seja útil, e novamente desejo a todos TERABYTES DE SUCESSO ❤

Referências

O Protocolo HTTP – Parte 04

Introdução

No post anterior, vimos as requisições GET que um Web Browse fez a um Totvs Application Server configurado como um servidor de páginas estáticas, e mais detalhes do protocolo, criando uma página html bem simples, e colocando ela como “tela de entrada” do site. Agora, vamos ver como fazer um programa AdvPL recuperar essa página do Web Site.

Função HTTPGET()

De uma forma simples, a função HttpGet() do AdvPL permite ao servidor de aplicação conectar em um Web Site, e recuperar um conteúdo usando a instrução GET do protocolo HTTP. Vamos ver isso um pouco mais a fundo, usando o Protheus Server como servidor de HTTP, e também dando atenção a funções auxiliares para os tratamentos dos possíveis retornos, entre outros truques interessantes. Para isso, vamos começar com um programinha bem simples:

#include "protheus.ch"

USER Function Myget1()
cHtml := HttpGet("http://localhost/")
conout("HTTP Body retornado:")
conout(cHtml)
return

Antes de mais nada, remova ou comente as configurações de log de requisições da seção http, senão o log vai ficar muito cheio … Ao compilar e executar o programa acima — pelo SmartClient , e verificar o log de console do Application Server, no nosso ambiente HTTP montado no post anterior, devemos obter o seguinte resultado:

HTTP Body retornado:
<html>
<body>
Meu primeiro Web Site 
</body>
</html>

Então, onde estão os Headers de retorno ?

A função HttpGet() retorna o “Html Body” retornado pelo Servidor Http acessado, mas também é possível retornar o Header da requisição usando o 5o parâmetro por referência.. vamos melhorar o programa, criando agora a função MyGet2():

USER Function Myget2()
cHeadRet := ''
cHtml := HttpGet("http://localhost/",,,,@cHEadRet)
conout("HTTP Header retornado:")
conout(cHEadRet)
conout("HTTP Body retornado:")
conout(cHtml)
return

Agora, ao executar o programa, vamos conferir o retorno:

HTTP Header retornado:
HTTP/1.1 200 OK
Date: Sat, 23 Jan 2021 02:33:11 GMT
Server: Application Web Server
MIME-version: 1.0
Content-type: text/html
Last-modified: Fri, 22 Jan 2021 23:33:29 GMT
Content-length: 55
X-Frame-Options: SAMEORIGIN

HTTP Body retornado:
<html>
<body>
Meu primeiro Web Site 
</body>
</html>

E se houver um erro ? O que pode dar errado ?

Então, muita coisa pode dar errado, desde não ser possível estabelecer a conexão HTTP com o host/servidor informado na URL, até ser possível estabelecer a conexão, mas o servidor não entender o pedido, ou não conseguir processar a requisição … Vamos começar com uma requisição de algo que não existe, alterando a linha 2 desse fonte, para pedir o arquivo “naoexiste.htm”:

cHtml := HttpGet("http://localhost/naoexiste.htm",,,,@cHEadRet)

Agora, vamos ver o que é retornado ao executar esse código, no log de console:

HTTP Header retornado:

HTTP Body retornado:
NIL

Então, com esse retorno a gente fica simplesmente “a pé”, não temos idéia do que aconteceu … Vimos apenas que o Header retornado por referencia está vazio, e o corpo HTTP retornado para a variável cHTML não contém uma string, mas o valor “NIL” (nulo) AdvPL.

Agora, vamos usar algumas funções auxiliares de tratamento de retorno de requisição.. e criar a função MyGet3():

USER Function Myget3()
  cHeadRet := ''
  cHtml := HttpGet("http://localhost/naoexiste.htm",,,,@cHEadRet)

  // Apos chamar a função HttpGet(), podemos obter alguns resultados \
  // usando algumas funções auxiliares 
  cHttpStatus := ''
  nHttpCode := HTTPGETSTATUS(@cHttpStatus)

  conout("HTTP Return Code ... "+cValToChar(nHttpCode))
  conout("HTTP Return Status ... "+cValToChar(cHttpStatus))

  If empty(cHEadRet)
    conout("HTTP Header nao retornado...")
  Else
    conout("HTTP Header retornado:")
    conout(cHEadRet)
  Endif

  if empty(cHtml)
    conout("HTTP Body nao retornado...")
  Else
    conout("HTTP Body retornado:")
    conout(cHtml)
  Endif

return

E, agora, ao executar esse código, temos algumas novas informações:

HTTP Return Code … 404
HTTP Return Status … Requested file not found
HTTP Header nao retornado:
HTTP Body nao retornado…

Repare que agora a gente sabe o que aconteceu … o status 404 retornado indica que a página solicitada (naoexiste.htm) realmente não existe no servidor … risos … Agora, vamos mexer no fonte novamente, para buscar explicitamente a página de entrada do site, chamada “default.htm”.

cHtml := HttpGet("http://localhost/default.htm",,,,@cHEadRet)

Agora, ao rodar o U_MYGET3 com esta alteração, obtemos o seguinte resultado:

HTTP Return Code … 200
HTTP Return Status … OK

( o resto está igual ) 

E se der erro de conexão ?

Vamos ver … alteramos o programa para buscar a página “default.htm”, mas agora vamos colocar uma porta DIFERENTE da 80 … Simples assim:

cHtml := HttpGet("http://localhost:8080/default.htm",,,,@cHEadRet)

Se não tiver nenhum serviço HTTP na porta 8080 do seu computador, essa requisição deve falhar .. então, vamos ver o resultado da execução do programa com esta alteração no log de console:

HTTP Return Code … 10061
HTTP Return Status … Connection refused.
HTTP Header nao retornado…
HTTP Body nao retornado…

O erro retornado não é do HTTP, mas da interface de SOCKETS do sistema operacional … A conexão foi “recusada” pois não tem nenhum serviço “ouvindo” na porta 8080. Agora, vamos colocar um nome de host ou de um site que não existe …

cHtml := HttpGet("http://naoexiste/default.htm",,,,@cHEadRet)

E, temos então o seguinte retorno:

HTTP Return Code … 11001
HTTP Return Status … Host not found.
HTTP Header nao retornado…
HTTP Body nao retornado… ... 

E os outros parâmetros ?

Sim, tem vários …. Vamos ver primeiro o segundo parâmetro da função. Ele chama-se “cGetParms” — vide documentação completa na TDN no link https://tdn.totvs.com/display/tec/HTTPGet — e serve para a passagem de parâmetros pela URL.

A operação de GET do HTTP permite eu solicitar um arquivo ou página ao servidor HTTP, e na própria URL podemos colocar um ou mais parâmetros, na forma “?chave=valor[,chave2=valor2…]” . Estes parametros são conhecidos como parâmetros de busca ou “search parameters”. E existem duas formas de passar estes parâmetros no AdvPL : Eles podem estar diretamente na URL — informada no primeiro parâmetro — ou separados da URL, no segundo parâmetro da chamada da função HttpGet() — mas não podem estar em ambas ao mesmo tempo.

A passagem de parâmetros via URL deve ser feita após a página solicitada, usando o separador “?”(interrogação), seguido de um identificador ou chave, o sinal de igual “=” e um determinado valor. Para especificar mais combinações de chave e valor, use o separador “&” (e comercial). Por exemplo:

http://localhost/default.htm?id=no&page=1

Dessa forma, estou solicitando uma requisição para o protocolo HTTP, para o host “localhost”, solicitando a página “default.htm”, e informando pela URL os parâmetros “id” com o valor “no”, e “page” com o valor “1”. A nossa página default não tem avaliação de parâmetros, então qualquer coisa informada será “ignorada”, mas será transmitida ao HTTP Server.

Para passar a URL acima para a função HTTPGET, podemos passar os parâmetros juntos da URL ou separados. Vale lembrar que, não é necessário colocar a “?” interrogação para passar os parâmetros separados, veja abaixo os exemplos, o resultado final será o mesmo :

cReturn := HttpGet("http://localhost/default.htm?id=no&page=1")
cReturn := HttpGet("http://localhost/default.htm","id=no&page=1")

Observações muito importantes

Além dos separadores a serem utilizados para indicar o inicio dos parâmetros de busca (“?”), o separador entre o identificador (ou chave) “=” e o separador para informar mais parâmetros “&”, existem alguns pontos muito importantes:

  • Nos parâmetros de busca, em uma chave deve-se evitar usar caracteres especiais, símbolos e acentuação.
  • Caso seja necessário o uso de caracteres deferentes do alfabeto alfanumérico (letras maiúsculas e/ou minúsculas não acentuadas e números), quaisquer caracteres diferentes disso devem ser escritos em um formato chamado “URL Encoding” ou “Percent Encoding”

PERCENT QUEM ?

Cada caractere especial ou diferenciado pode ser convertido no formato “%HH”, onde HH é a representação HEXADECIMAL — com letras maiúsculas — do código ASCII do caractere a ser enviado. Por exemplo, se eu quero passar a chave “nome” com o valor “C&A” — lembrando que “&” é um caractere separador da lista de parâmetros, eu devo obter o código ASCII da letra “&” — que é 38 — e converter para hexadecimal ( 26 ), então informar na URL http://localhost/default.htm?nome=C%26A

Outro detalhe importante, é que o caractere “espaço em branco”, pode ser passado de duas formas como parâmetro da URL: Pode ser %20, ou o sinal de soma “+”.

E como isso entra no HTTP Header ?

Simples assim, todos os parâmetros passados por GET são colocados na primeira linha do HTTP Header:

GET /default.htm?id=no&page=1 HTTP/1.1
Host: localhost
(... other fields ...)

Isso tem limite ?

Essa é uma pergunta importante… sim, têm limite sim. Mas o limite é arbitrário, depende da capacidade do servidor HTTP e do Web Browser utilizado. Em linhas gerais, a recomendação é que não se use mais do que 2000 caracteres em uma URL. A maioria dos Web Browses e HTTP Servers lida tranqüilamente dentro desse limite. Veja mais informações das referências.

Posso passar dados sensíveis pela URL ?

Então, poder você pode, mas não deve … afinal os dados ficam expostos na URL … para passar dados sensíveis, e maiores que 2000 bytes, veremos mais pra frente o comando POST do protocolo HTTP, que permite receber parâmetros pela URL (igual ao GET), mas também permite receber parâmetros pelo HTTP Body 😀

Conclusão

Aos poucos vamos mergulhando no HTTP, e ao mesmo tempo vamos ver o que o AdvPL nos oferece para lidar com essa camada. Espero que as informações lhe sejam muito úteis, e como de costume lhes desejo TERABYTES DE SUCESSSO !!!

Referências

O Protocolo HTTP – Parte 03

Introdução

Nos posts anteriores, vimos uma introdução ao protocolo, TCP, redes, e um glossário de muitos termos ligados a Internet e Redes de computadores. Agora, vamos voltar pro HTTP, explicando um pouco mais por dentro do que acontece, e usando o Totvs Application Server como um servidor de HTTP de arquivos e páginas estáticas.

Mas, já vimos isso no blog …

Sim, viram mesmo, em posts anteriores, e eu recomendo que você leia esses dois post, pois todas as informações sobre o protocolo HTTP preenchem algumas “lacunas” de informação que estes dois posts não contemplavam.

E agora ?

Se você não quiser, não precisa… mas eu recomendo ler os posts novamente, e configurar um Application Server como servidor de HTTP, porta 80. Basta criar uma pasta/diretório dentro do rootpath do seu ambiente — por exemplo “http-root”, e acrescentar no arquivo de configuração appserver.ini as seguintes chaves:

[HTTP]
ENABLE=1
PORT=80
PATH=C:\Protheus12\envp12127\http-root

No exemplo acima, basta trocar o PATH informado para a pasta que você criou. Agora, vamos fazer algumas brincadeiras e ver como o lance funciona por dentro. Esta é a configuração mínima para subir o Totvs Application Server como um servidor de páginas estáticas e arquivos.

Detalhes para novas builds de Application Server

O Totvs Application Server LG (Lobo Guará) possui implementações de porta muilti-protocolo — a mesma porta do Application Server que atende a conexões do SmartClient pode ser usada. No exemplo acima, vamos usar a configuração “tradicional”, sem a porta multiprotocolo. Para isso, basta acrescentar as chaves abaixo (destacadas em negrito) na seção [drivers] do arquivo de configuração (appserver.ini):

[drivers]
active=tcp
MultiProtocolPortSecure=0
MultiProtocolPort=0

Subindo o serviço

Ao iniciar o Totvs Application Server em modo console, nas mensagens de inicialização — em caso de sucesso — devemos ver entre as mensagens o seguinte:

Http server is ready.
Root path is c:\protheus12\envp12127\http-root\
Listening port 80 (default)

Então, a nossa pasta de publicações “raiz” está vazia, não tem nenhum arquivo. Agora, vamos ver o que acontece quando abrimos um Web Browse nessa máquina, e abrimos a URL http://localhost/

Agora, vamos ver o que o servidor HTTP recebeu e retornou para o Web Browse. Nas builds mais atuais do Totvs Application Server, existem duas novas configurações para a seção HTTP — usadas para teste e depuração, pois elas colocam no log de console cada requisição recebida pela porta HTTP, e cada resposta retornada para uma requisição. Vejamos como ficará a seção http com as novas configurações :

[HTTP]
ENABLE=1
PORT=80
PATH=C:\Protheus12\envp12127\http-root
LogRequest=1
LogResponse=1

Okay, agora paramos e iniciamos o Application Server, e pressionamos F5 no Web Browser — para tentar buscar a página raiz de publicação novamente, e vemos no log de console a mensagem recebida pelo Application Server, e o que ele retornou ao Web Browser.

[INFO ][SERVER] [22/01/2021 20:15:30]-[THREAD 11228] Received Http Connection!!! Starting Reading Data…
 Connection: keep-alive
 Cache-Control: max-age=0
 sec-ch-ua: "Google Chrome";v="87", " Not;A Brand";v="99", "Chromium";v="87"
 sec-ch-ua-mobile: ?0
 Upgrade-Insecure-Requests: 1
 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
 Sec-Fetch-Site: cross-site
 Sec-Fetch-Mode: navigate
 Sec-Fetch-User: ?1
 Sec-Fetch-Dest: document
 Accept-Encoding: gzip, deflate, br
 Accept-Language: pt,en-US;q=0.9,en;q=0.8
 [THREAD 5348] End Message
 
[22/01/2021 20:15:30]-[THREAD 5348] Starting Parsing
 [22/01/2021 20:15:30]-[THREAD 5348] End Parsing. Result 1
 [22/01/2021 20:15:30]-[THREAD 5348] Processing GET | CUT_HEAD

 [INFO ][SERVER] [22/01/2021 20:15:30]-[THREAD 5348] Sending Message
 HTTP/1.1 404 Requested file not found

O servidor HTTP recebeu um HTTP Header cheio de detalhes, solicitando a página raiz do Web Site. Como essa página ainda não existe — na verdade não tem nenhuma página (arquivo HTML) dentro da pasta de publicação http-root, foi retornado apenas o HTTP Header em negrito, informando o erro 404 — página não encontrada. A tela “bonitinha” que o Google Chrome desenhou é a forma dele mostrar ao usuário o que significa esse retorno do servidor.

Criando a página de entrada do site

De forma simples, apenas para ver o servidor funcionando, use um editor de texto simples — como o Notepad (Bloco de notas), crie um arquivo com o conteúdo abaixo, e salve ele dentro da pasta “http-root” com o nome “default.htm” :

<html>
<body>
Meu primeiro Web Site
</body>
</html>

E, agora, sem parar ou reiniciar o Application Server, volte no Web Browse, que aponta para http://localhost/, e pressione F5 novamente para tentar carregar a página, e veja o que aparece na tela:

E, ao verificar o log de console do Application Server, vamos ver o que foi enviado pelo browser, e o que o Application Server respondeu:

[22/01/2021 21:12:31]-[THREAD 23252] Received Message
GET / HTTP/1.1
Host: localhost
Connection: keep-alive
sec-ch-ua: "Google Chrome";v="87", " Not;A Brand";v="99", "Chromium";v="87"
sec-ch-ua-mobile: ?0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,es;q=0.6,sv;q=0.5
[THREAD 23252] End Message

[22/01/2021 21:12:31]-[THREAD 23252] Starting Parsing
[22/01/2021 21:12:31]-[THREAD 23252] End Parsing. Result 1
[22/01/2021 21:12:31]-[THREAD 23252] Processing GET | CUT_HEAD

[INFO ][SERVER] [22/01/2021 21:12:31]-[THREAD 23252] Sending Message
HTTP/1.1 200 OK
Date: Sat, 23 Jan 2021 00:12:31 GMT
Server: Application Web Server
MIME-version: 1.0
Content-type: text/html
Last-modified: Fri, 22 Jan 2021 23:33:29 GMT
Content-length: 55
X-Frame-Options: SAMEORIGIN

[INFO ][SERVER] [22/01/2021 21:12:31]-[THREAD 23252] Sending Message
<html>
<body>
Meu primeiro Web Site 
</body>
</html>

Entendendo o HTTP Header retornado

  • Primeira linha do Header de retorno, informa o protocolo utilizado ( Http versão 1.1 ), o código de retorno ( 200 significa “sucesso” ), e um texto complementar (opcional) relacionado ao código de retorno (OK).
HTTP/1.1 200 OK 
  • Segunda linha do Header de retorno, informa ao cliente (Web Browser) através da propriedade “Date” a data e hora atuais no servidor — no formato GMT (Greenwitch Mean Time), hoje chamado de UTC (Universal Time Coordinated).
Date: Sat, 23 Jan 2021 00:12:31 GMT
  • Terceira linha do header, informa através da propriedade “Server” uma informação sobre quem é a aplicação que respondeu a requisição. Meramente informativo para o Web Browse.
Server: Application Web Server
  • Quarta linha do header — mantida por compatibilidade no servidor Protheus, não é importante neste contexto.
MIME-version: 1.0
  • Quinta linha do header, importante, informa ao cliente que o conteúdo do HTTP Body (Corpo de retorno HTTP) deve ser interpretado como texto HTML.
Content-type: text/html
  • Sexta linha do header, informa ao cliente a data e horário no formato GMT da última modificação desse arquivo html no servidor — vamos ver por que isso é útil daqui a pouco.
Last-modified: Fri, 22 Jan 2021 23:33:29 GMT
  • Sétima linha do header, importante, informa ao cliente o tamanho do texto html que será retornado no corpo HTTP.
Content-length: 55
  • Oitava linha do header, informada por questões de segurança, instrui ao Client que ele não deve permitir uma requisição para este conteúdo quando ele estiver processando uma página de um outro website. Vamos ver isso mais pra frente.
X-Frame-Options: SAMEORIGIN

Até aqui tudo bem ? Então, tudo funcionando bem … agora, sem fechar o navegador — estou usando o Google Chrome — vamos pressionar F5 novamente, para “recarregar essa página”. Tudo deve ser igual, certo ? — Não necessariamente ….. a página mostrada no Browse foi a mesma … mas alguma coisa mudou na requisição feita pelo Browser, e no retorno do Application Server… Veja abaixo o que mudou na solicitação e no retorno, destacado em negrito:

[22/01/2021 21:25:18]-[THREAD 23252] Received Message
GET / HTTP/1.1
Host: localhost
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: "Google Chrome";v="87", " Not;A Brand";v="99", "Chromium";v="87"
sec-ch-ua-mobile: ?0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,es;q=0.6,sv;q=0.5
If-Modified-Since: Fri, 22 Jan 2021 23:33:29 GMT
[THREAD 23252] End Message

[22/01/2021 21:25:18]-[THREAD 23252] Starting Parsing
[22/01/2021 21:25:18]-[THREAD 23252] End Parsing. Result 1
[22/01/2021 21:25:18]-[THREAD 23252] Processing GET | CUT_HEAD

[INFO ][SERVER] [22/01/2021 21:25:18]-[THREAD 23252] Sending Message
HTTP/1.1 304 Not Modified
Date: Sat, 23 Jan 2021 00:25:18 GMT
Server: Application Web Server
MIME-version: 1.0
X-Frame-Options: SAMEORIGIN

Na última linha do header http da requisição feita pelo Web Browser, apareceu uma nova informação :

If-Modified-Since: Fri, 22 Jan 2021 23:33:29 GMT

Isso indica que, essa página html já está na memória do Web Browse ( conhecido por CACHE de navegação do Browser). Neste caso, ele informa que o servidor não precisa enviar de novo o arquivo , DESDE QUE ele não tenha sido modificado desde a ultima vez que ele pediu o arquivo. Ele recebeu essa informação na primeira requisição que ele fez, quando o Application Server informou a propriedade Modified-since ao retornar o HTML.

Quando o Application Server recebe essa informação, ele verifica se o arquivo no disco realmente ainda está com a última data de modificação igual ao que o Browser conhece … e como não houve alteração nesse arquivo desde então, o servidor não manda mais para ele o arquivo, e nem retorna status “200 OK”, mas sim um Header HTTP de retorno com o status 304 (Not Modified). Desse modo, ele não precisou trafegar pela rede o conteúdo da página default.htm … e o browse pode usar a informação que ele tem no cache dele. E ele mostra a página 😀

Reparem que nesse header de retorno, não entrou nenhuma informação de content-type, content-length ou modified-since … afinal, o Web Browse já tem tudo isso … isso economiza banda de rede na navegação de páginas.

Acessando a mesma página, mas usando o “nome” da máquina

Agora, vamos no prompt de comando do sistema operacional, e usamos o comando “tracert localhost”. Esse comando serve para coisas mais avançadas, mas atende a nossa necessidade agora, para obter de uma forma simples o HOSTNAME, ou o “nome” da máquina para efeitos de conexão de rede.

C:\Users\juliow>tracert localhost
 Tracing route to NOTE-I7-JULIOW [::1]
 over a maximum of 30 hops:
 1    <1 ms    <1 ms    <1 ms  NOTE-I7-JULIOW [::1]
 Trace complete.

Com isso, descobrimos que o nome da minha máquina é “note-i7-juliow”. Agora, vamos no Chrome novamente, e entramos com a URL http://note-i7-juliow/, e vejamos o que acontece com os logs do Totvs Application Server:

[INFO ][SERVER] [22/01/2021 21:38:27]-[THREAD 23252] Received Http Connection!!! Starting Reading Data…
[22/01/2021 21:38:27]-[THREAD 23076] Received Message
GET / HTTP/1.1
Host: note-i7-juliow
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,es;q=0.6,sv;q=0.5
[THREAD 23076] End Message

[22/01/2021 21:38:27]-[THREAD 23076] Starting Parsing
[22/01/2021 21:38:27]-[THREAD 23076] End Parsing. Result 1
[22/01/2021 21:38:27]-[THREAD 23076] Processing GET | CUT_HEAD

[INFO ][SERVER] [22/01/2021 21:38:27]-[THREAD 23076] Sending Message
HTTP/1.1 200 OK
Date: Sat, 23 Jan 2021 00:38:27 GMT
Server: Application Web Server
MIME-version: 1.0
Content-type: text/html
Last-modified: Fri, 22 Jan 2021 23:33:29 GMT
Content-length: 55
X-Frame-Options: SAMEORIGIN
[INFO ][SERVER] [22/01/2021 21:38:27]-[THREAD 23076] Sending Message
<html>
<body>
Meu primeiro Web Site 
</body>
</html>

[22/01/2021 21:38:28]-[THREAD 23252] Received Message
GET /favicon.ico HTTP/1.1
Host: note-i7-juliow
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36
Accept: image/avif,image/webp,image/apng,image/,/*;q=0.8
Referer: http://note-i7-juliow/
Accept-Encoding: gzip, deflate
Accept-Language: pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,es;q=0.6,sv;q=0.5
[THREAD 23252] End Message

[22/01/2021 21:38:28]-[THREAD 23252] Starting Parsing
[22/01/2021 21:38:28]-[THREAD 23252] End Parsing. Result 1
[22/01/2021 21:38:28]-[THREAD 23252] Processing GET | CUT_HEAD

[INFO ][SERVER] [22/01/2021 21:38:28]-[THREAD 23252] Sending Message
HTTP/1.1 404 Requested file not found

Nossa, algo mudou bem aqui … vamos por partes:

  • O browse não foi fechado, eu pedi a página de entrada do site, que não mudou … por que o Browse não mandou um “if-modified-since” ?
    R: O browse já tem em cache a página de entrada do site “localhost”, agora voce pediu a página de entrada do site “note-i7-juliow” … Para o Browse, isso é um OUTRO Web Site. Ele não pode misturar os caches ..
  • Por que apareceu mais uma requisição “GET favicon.ico” feita pelo Browse ?
    R: Então, isso é um comportamento do Browse, e é bem provável que ele tenha feito isso também no primeiro teste — http://localhost/ — e eu não tenha visto … O Browse pede ao servidor http um arquivo chamado “favicon.ico” – trata-se de um arquivo de imagem contendo um “ícone”, que quando existe na pasta de publicações raiz ( no nosso caso, http-root), o Browse recebe esse arquivo e mostra a imagem do ícone contida no arquivo na barra de navegação do site, e caso você adicione esse site aos seus “Sites Favoritos” no seu navegador, ele também mostra o ícone do site junto do nome do site. Repare quando você abre o site do blog, aparece o ícone do “WordPress” na aba do Browser…

Vamos criar um ícone ?

Embora ele seja uma imagem, a extensão “.ico” é um formato diferente, não é igual a um BMP ou JPEG … e não é qualquer programa gráfico que permite você criar um ícone .. Mas, graças a internet, eu fiz uma “carinha” com o PaintBrush, salvei em disco, usei um site de conversão de imagens para ícone gratuito — https://icoconvert.com/ — , criei um ícone, fiz download para o meu computador, e agora eu vou salvar ele no disco, dentro da pasta “http-root”, com o nome de “favicon.ico” .. e vamos ver o que acontece ?

  • Observação : Como o navegador já tinha aberto o site, e viu que não tinha o ícone, ele não vai mais perguntar isso ao servidor, a menos que você feche o Browse e abra novamente.

Agora, vejam na aba superior do browse… do lado esquerdo ao nome do host, “apareceu” o ícone que eu criei 😀

Tem mais diferenças ?

Sim… reparem que, ao trocar “locahost” para o nome da máquina, o Web Browse mostra uma informação adicional na barra de endereços … um ícone em forma de triângulo com uma exclamação dentro, e do lado a mensagem “Não seguro” — isso serve para informar ao usuário que está navegando no Web Site, que a conexão “não é segura”.

Calma, não criemos pânico … o termo “seguro” na prática significa “não criptografado”… aí já entramos em conexão segura ( Protocolo HTTPS ..), calma que vamos ver isso mais pra frente, e já tem posos no blog que falam sobre criptografia e segurança — que eu fortemente recomendo a leitura …

Conclusão

Por hora eu acho que aqui já tem bastante o que mastigar … muita informação ao mesmo tempo dá “tilt” 😛 Então, por hoje é só pessoal, aguardem mais novidades e detalhes no próximo post. E desejo como sempre a todos TERABYTES DE SUCESSO!!!

Referências

O Protocolo HTTP – Parte 02 – Glossário

Introdução

No post anterior, vimos com alguns detalhes “internos” uma requisição HTTP, e várias terminologias — como HTTP, Web Browser, Web Server — e alguma coisas “por dentro” do protocolo. Agora, para continuar sem ficar “voando” muito, vamos ver o que significam algumas terminologias usadas para definir componentes do universo de redes, conectividade e internet, de uma forma “conectada”.

Glossário

Rede de computadores — Dois ou mais computadores, ligados entre si — conectados — por um meio físico (cabeamento) ou sem fio (wireless), onde os equipamentos conectados trocam informações entre si usando a rede.

Wireless (Rede Sem Fio)— Termo utilizado para indicar que a conexão entre os equipamentos é “sem fio” (Wi-fi, Bluetooth e 3G são exemplos de conexões Wireless).

Rede cabeada — (ou wired — com fio) — Termo utilizado para indicar que a conexão entre os equipamentos possui um ou mais “fios” e/ou “cabos”. Os tipos dos fios e cabos podem variar muito dependendo do tipo da rede. Pode ser desde cabo coaxial (NET/Claro, TVs a Cabo), cabo de par trançado (redes cabeadas domésticas e industriais), Fibra Óptica (redes de alta velocidade ou “Banda Larga”).

Roteador — (Router) — Equipamento responsável por direcionamento e encaminhamento de pacotes de rede entre redes diferentes. É uma das peças chave responsáveis pelo funcionamento da Internet.

Switch (ou Comutador) e Hub — Outros dois tipos de equipamento para conectar computadores em rede. São mais simples que um roteador, vamos ver depois onde e por quê.

MODEM — Nome dado a um equipamento de telecomunicações, capaz de converter e desconverter (ou modular e demodular — MO-DEM) uma informação de um determinado tipo de sinal ou informação para ser trafegado por um meio físico. Por exemplo, as conexões primeiras conexões com a Internet para uso doméstico no Brasil foram feitas através de linhas telefônicas convencionais, que suportavam apenas modulação de áudio (linhas analógicas). Usando um MODEM no seu computador, você estabelecia uma conexão com outro MODEM, no servidor ou provedor de internet, e o MODEM transformava os pacotes TCP em áudio analógico para serem enviados pela linha telefônica, e o MODEM no servidor recebia esse áudio, e recodificava o pacote original que o seu computador enviou, e vice-versa.

Protocolo de comunicação — Conjunto de regras e definições de como os dados são transmitidos (enviados e recebidos) em telecomunicações e redes de computadores. Por exemplo TCP/IP, HTTP, FTP, SMTP, IMAP, POP, SSH…

Cliente (Client) — Aplicação que inicia uma conexão para uma aplicação Servidora (Server).

Servidor (Server) — Aplicação que espera e atende a requisições de conexões feitas por uma aplicação Cliente.

IP – Numero de identificação único de uma interface de rede atribuído manualmente ou automaticamente, que permite endereçar (acessar) portas de comunicação da interface através da rede. Ele “identifica” o computador na rede.

Porta (TCP) – Número atribuído a um canal de conexão, associado ao IP. Uma conexão de rede TCP envolve o par de informações IP + Porta da interface de rede de origem e de destino. No protocolo TCP/IP v4, uma interface de rede suporta 65536 portas diferentes por interface — numeradas de 0 a 65535. Vale lembrar que a faixa de portas de 0 a 1024 possuem uso reservado para determinados protocolos, e as as demais portas são utilizadas a critério do sistema operacional do equipamento — incluindo uma faixa de portas reservada para aceite de conexões — conhecidas por “faixa de portas efêmeras”.

Porta efêmera (TCP – Ephemeral port) — Número de porta atribuído automaticamente para um IP em uma conexão.

Porta ouvinte (TCP – Listening Port) — Número de porta fixo, atribuído a uma interface de rede, para ficar esperando (listening) por uma conexão de rede. Por exemplo, um Web Server HTTP aloca a porta 80 (que faz parte de uma faixa de numeração pré-definida) em uma ou mais interfaces de rede de um equipamento para aceitar as conexões HTTP vindas de um ou mais navegadores Web ou aplicativos.

DDOS (Distributed Denial of Service) — Um tipo de ataque coordenado utilizando vários computadores a um determinado Web Site/ Web Server, tendo como objetivo “metralhar” o Web Server com requisições, até que haja o esgotamento de recursos computacionais e ele não consiga responder as requisições — causando a “negação de serviço” (Denial of Service).

DHCP (Dynamic Host Configuration Protocol) — Protocolo utilizado entre os equipamentos de uma rede e um equipamento ou serviço dedicado (DHCP Server) para atribuir dinamicamente um IP a um equipamento que quer ingressar em uma rede.

Pacote de Rede TCP (TCP Packet) — Nome dado a uma sequência de bytes que são transferidos entre interfaces de rede através de uma linha de comunicação (ou conexão). Um Cliente envia um pacote contendo uma requisição HTTP GET para um servidor HTTP, o servidor responde essa requisição para este cliente, enviando um ou mais pacotes em sequência com a resposta.

Socket — Como uma conexão TCP é identificada pelo par de informações IP+Porta das duas interfaces envolvidas, cada uma dessas “pontas” (end points) é chamada de Socket. Ao criar uma conexão, usamos um conjunto de funções (API) do sistema operacional para criar e manipular conexões. Um programa Cliente, ao criar uma conexão, recebe um número identificador dessa conexão, chamado de manipulador de socket (Socket Handle), e através dele usamos as demais funções da API para usar este Socket para enviar e receber pacotes de dados.

Firewall – Nome dado a uma barreira de proteção entre redes, ou entre um determinado equipamento e a rede. Permite criar regras de bloqueio para aceite e respostas de conexões, entre outros recursos. Firewall em si é uma funcionalidade, que pode ser exercida por um software em um equipamento, ou um equipamento inteiro dedicado para esta finalidade.

F.A.Q.

A estas alturas do campeonato muitas informações de uma vez dão um nó na cabeça da gente, e geram mais dúvidas… vamos tentar tirar algumas dessas dúvidas com alguns questionamentos devidamente respondidos.

  • Eu tenho NET com Internet em casa. Aquele MODEM da Net, o que ele faz ?
    R:
    Ele não é “apenas” um modem, ele acumula as funções de um roteador, decodificador, um DHCP local, e um modulador Wi-fi (rede sem fio). Ao aceitar a conexão de um dispositivo qualquer (Computador, telefone celular. SmartTV), ele atribui um endereço IP para cada equipamento — através do DHCP — criando uma rede local dentro da sua casa, fazendo a “ponte” de comunicação entre os seus dispositivos, e entre cada dispositivo e a Internet.
  • Tem umas entradas para cabos de rede atrás do modem da NET … pra que serve isso?
    R:
    Cada entrada daquela permite uma conexão cabeada entre os dispositivos e o modem. A conexão cabeada é mais rápida que a conexão wireless (Wi-fi). Se você tem uma SmartTv com NetFlix, por exemplo, embora a SmartTv tenha configuração de conexão por Wi-fi, procure instalar o Modem da Net perto da TV, e prefira uma conexão cabeada para ligar a SmartTv ao modem da NET.
  • Dá pra conectar dois computadores sem roteador ou modem ?
    R:
    Sim, a mais simples possível seria uma rede cabeada com um HUB ou SWITCH — dê preferência ao switch — Basta ter dois computadores com conexões para o cabo de rede RJ45 (aquele cabo com fiozinhos coloridos nas pontas)… mas sem um roteador e um DHCP, você tem que atribuir “manualmente” um endereço de IP para os 2, e ligar os dois em um Hub ou Switch. Você não vai ter uma “rede” efetivamente, mas vai conseguir abrir conexões via aplicativos entre uma máquina e outra. Como você não tem um DNS, ao colocar um servidor HTTP em uma das máquinas, você deve usar o IP da máquina que você definiu para abrir o site através da outra máquina.
  • Quais linguagens tem suporte a sockets e conexão TCP/IP ?
    R:
    Praticamente todas as linguagens de mercado possuem este recurso. Algumas como um recurso nativo da linguagem, outras mediante a utilização de Libs (bibliotecas de funções) ou Plugins. A maioria delas já possui classes ou componentes para lidar diretamente com os protocolos HTTP, FTP, IMAP, SMTP, etc..
  • O quanto a Internet é “segura” ?
    R:
    Depende do que você usa e de como você usa. Existem várias formas de colocar conteúdo na Internet, e algumas pessoas ou grupos de pessoas mal intencionadas, que buscam formas de usar as suas informações em benefício próprio. Phishing, Spam, Virus, Trojans, Ransomare, tem de tudo .. é prudente e importante estar atento a isso, uma vez que você vai usar esses recursos no seu dia-a-dia. Mas não importa o quanto se invista em segurança nos protocolos e equipamentos, os procedimentos de segurança começam no usuário.
  • Têm tudo isso no AdvPL ?
    R: SIM,
    com recursos nativos do servidor de aplicação — TOTVS Application Server — e da linguagem AdvPL. Vamos entrar nos detalhes de alguns posts anteriores, só que agora explicando a coisa “por dentro”, e usando AdvPL na brincadeira.

Conclusão

Eu sei, o tamanho disso assusta, mas é um conhecimento muito legal, e as tecnologias vindas dele são muito utilizadas — em larga escala e para implementar soluções integradas. Envolvem conhecimentos em diversas áreas — eletrônica, telecomunicações, hardware, software — mas abrem um universo de possibilidades. Espero que tenham gostado do post, já já sai mais !!!! E desejo a todos TERABYTES DE SUCESSO !!!

Referências

O Protocolo HTTP – Parte 01

Introdução

Para quebrar o gelo após um turbulento — eu diria, pandêmico — período de inatividade, vamos ver uma introdução ao protocolo HTTP — usado entre os navegadores de internet e os sites que acessamos, e entre serviços cliente e servidor de WebServices, entre outros. Vamos ver como funciona por dentro o que você vê aparecendo na tela do seu Web Browser.

Visão básica do Protocolo HTTP

O protocolo HTTP pode ser usado para transferir textos e demais dados de diversos formatos através de uma conexão de rede entre computadores. Para isso ser possível, uma requisição e uma resposta de requisição possuem sempre um cabeçalho — conhecido como “HTTP Header“, composto por uma ou mais linhas de texto em um formato e/ou disposição pré-determinados, e podem (ou não) conter dados adicionais após o cabeçalho, que chamamos de “corpo” (HTTP Body). No cabeçalho HTTP, cada linha deve ser finalizada com a seqüencia de caracteres ASCII 13 + ASCII 10 ( ou CRLF ), e a última linha do cabeçalho deve ser uma linha em branco, apenas com o “fim de linha” (CRLF). O Formato do corpo HTTP depende das definições e parâmetros informados no Header HTTP.

Conceito Cliente-Servidor

Um servidor HTTP é um programa que captura para uso exclusivo uma porta TCP ( por default, para o protocolo HTTP, porta 80, para HTTPS, porta 443), e atende a requisições feitas por um Programa cliente — normalmente um navegador de internet (Web Browse), realizadas através de uma conexão TCP-IP, iniciada pelo programa Cliente e atendida pelo Servidor HTTP.

Requisição mínima para HTTP

Uma requisição mínima HTTP precisa ter pelo menos a primeira linha de Header. Essa primeira linha deve conter uma operação ( GET por exemplo ), no seguinte formato:

GET / HTTP/1.0\r\n\r\n

Na descrição acima, “\r” significa o caractere ASCII 13 (ou CR), e “\n” significa o caractere ASCII 10 (ou LF). E, vale mencionar também, que essa requisição “mínima” pode não ser aceita por todos os serviços de HTTP, pois a maioria exige pelo menos uma linha a mais de cabeçalho, informando o nome do host (IP ou HostName) do website que você deseja acessar. E, essa requisição mínima indica ao servidor HTTP que você deseja recuperar a página inicial (ou “raiz”) do website hospedado no endereço solicitado. Na mensagem também vai a versão do protocolo usada, pode ser HTTP/1.0 ou HTTP/1.1 — veremos depois as diferenças entre eles.

Requisição mínima usando AdvPL

Quando utilizamos a função HttpGet() do AdvPL, da forma exemplificada abaixo, passamos para a função apenas o primeiro parâmetro, na forma de URL — protocolo : host [ : porta ] [ /pagina/ … ]

cRet := HttpGet("http://www.google.com.br/")

Internamente, a função HttpGet() vai “desmontar” a URL informada, para realizar a conexão com o host informado — na porta 80 (Http) — e montar um header de requisição http. Porém, o header http montado pela função vai ter mais conteúdo:

GET / HTTP/1.1
Host: localhost
Connection: Keep-Alive

Uma requisição de GET montada pela função HttpGet() do AdvPL após desmembrar a URL, contém apenas um header http contendo o Host, e um parâmetro de conexão ( Keep-Alive ), e por default informa o uso do protocolo HTTP 1.1

Retornos de requisição HTTP

Quanto ao retorno da requisição, feito pelo servidor que a atendeu, a estrutura dos dados retornados é similar a uma requisição http: O retorno do protocolo http contém um header http, onde a primeira linha possui o protocolo de resposta e código de retorno http, e normalmente contém mais linhas de header com outras informações — como o tipo e tamanho do retorno — e também pode (ou não) conter um corpo de retorno (http body), vamos ver abaixo um exemplo de retorno http:

HTTP/1.1 200 OK
Date: Tue, 19 Jan 2021 13:31:50 GMT
Server: Application Web Server
MIME-version: 1.0
Content-type: text/html
Last-modified: Tue, 19 Jan 2021 13:31:50 GMT
Pragma: no-cache
Set-cookie: SESSIONID=fcd8b19e003a5f8596abd71af7715bad
X-Frame-Options: SAMEORIGIN
Content-Length: 110

Essa resposta de requisição contém várias informações no http header. Na primeira linha, temos o protocolo de retorno ( HTTP 1.1 ), o código de retorno (200), e uma string opcional, descrevendo o código (OK), e as informações mais relevantes para este momento são o tipo de conteúdo retornado (Content-Type) e o tamanho do conteúdo (Content-Length). Vamos ver elas e as demais em detalhes mais pra frente.

Mais um retorno

Se fizermos uma requisição para a página inicial do Google em português — http://www.google.com.br — devemos obter um header http de retorno com outras informações, veja abaixo:

HTTP/1.1 200 OK
Date: Tue, 19 Jan 2021 14:53:36 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=ISO-8859-1
P3P: CP="This is not a P3P policy! See g.co/p3phelp for more info."
Server: gws
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN
Set-Cookie: 1P_JAR=2021-01-19-14; expires=Thu, 18-Feb-2021 14:53:36 GMT; path=/; domain=.google.com.br; Secure
Set-Cookie: NID=207=g6_nLFdLmIpY9MoV1ueTqoa_pCkzwnnNf3WCIacz5e2t3vPKE2FrniMSldXPAENrRninRNCr0NjXVr2_tOHqkwX9O2CXNr5IMQs1YFK1Gam1-SGlCM_5WOpQeLAFw9NksyR6zVAsWinZms7zdL0tsI7NBM5z38rS1Gpvb1iqp_Y; expires=Wed, 21-Jul-2021 14:53:36 GMT; path=/; domain=.google.com.br; HttpOnly
Accept-Ranges: none
Vary: Accept-Encoding
Transfer-Encoding: chunked

Temos bem mais informações… desde instruções para caches/proxy, tipo detalhado do retorno, e instruções de como um navegador de internet (Web Browser) deve tratar esse conteúdo.

Pontos de atenção

Devemos lembrar que o protocolo HTTP serve para transporte de texto, arquivos de diversos formatos, imagens, scripts, XML, JSON, etc… tudo depende de o quê está sendo solicitado, e quem está atendendo ao pedido. Uma requisição GET para uma URL onde o servidor Http está atendendo a um Web Service do tipo REST deve retornar um text/json, um GET de uma URL onde está uma imagem deve retornar no corpo do http (Http body) o conteúdo (bytes) da imagem, e assim por diante.

Outro ponto importante, é que o conteúdo http retornado será tratado e avaliado pelo cliente que fez a requisição. Ao retornar um determinado tipo de conteúdo, como um arquivo PDF por exemplo, o navegador de internet utilizado pode optar por mostrar o conteúdo do arquivo na tela do usuário, ou oferecer a opção de “download” desse arquivo. Vamos começar com a abordagem mais simples, para depois acrescentar os comportamentos e os “por quês” das coisas.

HTML, o que é afinal ?

HTML (Hyper Text Markup Language) é uma forma de representar um conteúdo de uma página em um Web Site. Visto de uma forma simples, é um arquivo de TEXTO, onde podemos colocar caracteres especiais — chamados de “marcadores” — que indicam ao programa Cliente usado para a navegação no site (Web Browser) como ele deve “mostrar” esse conteúdo na tela. HTML não é um protocolo ou uma linguagem de programação, mas apenas uma forma de representar uma informação, criado para disponibilizar conteúdo de forma padronizada através da Internet. Para permitir a evolução do HTML, ele também é “versionado” — versões mais novas do protocolo possuem novos marcadores para mostrar conteúdos de novas formas, e novos tipos de conteúdo. Por outro lado, esse conteúdo somente será mostrado corretamente se o Web Browse utilizado suportar (entender) aquela versão do HTML. Atualmente o HTML está na versão 5, a versão anterior é a 4.01. As especificações do HTML e de outros formatos e protocolos para Internet são criados por uma comunidade internacional de colaboradores, chamada W3C (World Wide Web Consortium).

F.A.Q.

  • Um servidor HTTP funciona como se fosse um servidor de “arquivos” ?
    R: SIM
    — Na prática, ao configurar um servidor HTTP, na máquina onde está este servidor, você tem uma pasta no disco — chamada “pasta raiz de publicação”, onde você coloca pelo menos uma página (arquivo HTML) de “entrada” do seu Web Site, e pastas contendo outras páginas, e imagens e scripts e folhas de estilo (CSS) usadas pelas páginas.
  • Como o servidor HTTP “sabe” qual é a página inicial do meu site ?
    R:
    Isto normalmente é uma configuração do servidor, que já possui um nome de arquivo inicial da pasta raiz pré-definido (default), como por exemplo “index.html”.
  • Dá pra fazer um programa em HTML ?
    R: Não
    … MAS, dentro do HTML você pode usar JavaScript, que é capaz de acessar e alterar os componentes HTML da página durante a execução dos scripts e exibição da página. Os códigos JavaScript colocados dentro do HTML são executados pelo Web Browser, na estação do usuário que abriu a página.
  • Dá para fazer um site inteiro com apenas uma página?
    R:
    Sim, dá sim. Essa técnica se chama Single Page Application, onde você atualiza dinamicamente o conteúdo da página do site usando scripts, que buscam informações no Web Server sem a necessidade de alterar a URL da página em exibição, redesenhando a página no Web Browse.
  • Posso criar e publicar um Web Site no meu computador ?
    R: SIM, pode. Criar, com certeza .. MAS … mesmo que você instale um Web Server no seu equipamento, tornar o seu site “publicado” na internet, para que ele possa ser acessado através de uma URL (www.seusite.com.br) exige várias outras etapas e recursos. Vamos ver isso mais pra frente.
  • Posso criar e disponibilizar um site em uma rede “local” ? |
    R: Sim
    . Nestes casos, uma rede menor (Intranet) pode hospedar por exemplo um site que não estará publicado na Internet, mas será acessado por um ou mais Web Browser’s apenas dentro da Intranet.
  • Posso publicar um site dentro da rede da minha casa ?
    R: Sim
    , cada computador acessando a rede da sua casa tem um “nome” — conhecido por “hostname”. Ao publicar o servidor HTTP na sua máquina, qualquer máquina de dentro da sua rede pode acessar o seu site usando http://nomedamaquina/
  • Eu realmente preciso saber de tudo isso?
    R:
    Não necessariamente … mas saber como a BASE daquilo que você usa funciona, abre as portas para você entender tudo o que foi criado SOBRE esta base, e escolher a melhor forma de usá-la. E, isso é só o começo ….

Glossário

  • Web Browser – Programas que abrem sites e páginas, feitos para navegar na Internet — Como por exemplo o Mozzila Firefox, Microsoft Internet Explorer, Microsoft Edge, Google Chrome, Opera, Safari, entre outros.
  • Web Server – Programas utilizados para serem servidores de Web Sites para Internet. Os mais conhecidos e utilizados são o Apache, e o Microsoft IIS.
  • TCP/IP – Nome do conjunto (ou pilha) de protocolos projetado para comunicação entre computadores conectados em uma rede. Atualmente são utilizadas as versões TCP/IP v4 e TCP/IP v6.

Conclusão

O universo de Internet e Web Sites é imenso, mas quando dividido em camadas e componentes, fica mais fácil entender como ele funciona. Ao longo dos próximos posts, vamos entrar mais no que a linguagem AdvPL oferece para realizar integrações com Web Sites e Serviços que utilizam o protocolo HTTP. Espero que as informações desse post lhe sejam úteis, e lhes desejo como sempre TERABYTES DE SUCESSO 😀

Referências adicionais e leitura complementar

Criptografia em AdvPL – Parte 07

Introdução

No post anterior, configuramos um TOTVS Application Server como servidor HTTP e HTTPS, usando um certificado digital criado na raça usando a OpenSSL, do tipo “auto-assinado”, sem uma Autoridade Certificadora. Agora, aproveitando que temos um ambiente com um site que atende conexões não-seguras e seguras, vamos ver o que passa por dentro da camada de rede usando esses dois tipos de conexão.

Posts anteriores

Usando um analisador de pacotes de rede

Como temos agora um servidor configurado para conexões HTTP (Porta TCP 80) e HTTPS (Porta TCP 443), vamos ver como é possível “interceptar” a comunicação entre o navegador e o servidor HTTP usando um programa “espião de pacotes” — também chamados de Sniffer ou Network Packets Analyzer.

No caso, vou usar um analisador de rede chamado Wireshark — OpenSource, já tem Builds prontas para Windows e Linux, disponíveis no link https://www.wireshark.org/download.html — A instalação é tão simples quanto Next->I Agree->Next->Next->Next->Finish. Não vou entrar em mais detalhes desse recurso no momento, não é o foco desse post, apenas vou mostrar como o conteúdo transferido entre o servidor HTTP e o navegador pode ser visto — este é o pacote de resposta do servidor com a página HTML, usando uma conexão HTTP (não segura):

wireshark_http.png

A requisição que a imagem acima mostra é a resposta do servidor HTTP quando eu abri o navegador e pedi a página http://note-juliow-ssd.index.html. Se a gente ver o quando de informações o navegador enviou para o servidor quando pediu essa página, o Browser manda muitas informações:

GET /index.html HTTP/1.1
Host: note-juliow-ssd
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate
Accept-Language: pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,es;q=0.6,sv;q=0.5

As informações acima foram enviadas pelo Chrome ao servidor HTTP do Protheus quando eu pedi um “Refresh” da página Index.html.

Interceptando os pacotes de uma conexão segura

Bem, meu chapa, o analisador de pacotes de rede intercepta tudo, inclusive uma conexão segura … Você consegue ver todas as etapas de HandShake e trocas de cifras e certificados entre as partes envolvidas, e depois os pacotes de dados … mas não adianta NADA, mesmo que você intercepte TODOS os pacotes … os tipos de informações trocadas entre o navegador e o servidor também estão criptografadas, o máximo que você pode fazer é olhar para os pacotes de dados e chorar … por que somente o servidor e o navegador sabem o que tem dentro 😀

https_application_data

Por exemplo, na imagem acima vemos um dos pacotes de dados trocados entre o navegador e o servidor HTTPS … não dá pra saber se foi uma pergunta ou uma resposta, ou o que isso quer dizer … e mesmo que você consiga fazer um ataque conhecido como “Man In The Middle”, isto é, fazer esta conexão passar por um “Tunnel TCP” dentro de uma aplicação sua, se você tentar mexer em um bit desse conteúdo, a decodificação da mensagem falha e a requisição sequer será processada, a camada de segurança que encapsula a conexão retorna um erro, e tchau.

Todo esse mecanismo tem como base a chave criptográfica privada armazenada no arquivo  “note-juliow-ssd.key”, em formato codificado BASE64. Como esta chave é única, e ainda foi criada sem senha, se eu usar ela para uma comunicação segura de uma aplicação de comunicação oficial, eu já comecei errado, por várias razões.

  • Chave privada sem proteção de senha
  • Certificado emitido sem uma Autoridade Certificadora

Se alguém coloca a mão nessa chave privada, desprotegida, e ela é usada para trocas de dados importantes, é possível gerar um outro certificado com outros dados baseado nesta chave, e usá-lo por exemplo para subir um servidor que finge ser “eu” em outro endereço na internet. e usando outros artifícios, fazer um “Tunnel TCP” entre o cliente e o meu servidor verdadeiro, capaz de ver o conteúdo descriptografado das mensagens — inclusive eu pretendo fazer esse teste mais pra frente.

E, se eu perder a minha chave privada, ou ela está protegida por senha e eu esquecer a senha … e eu usei essa chave para criptografar documentos, arquivos, imagens, qualquer coisa, esquece. Sem ela nem eu consigo decodificar as informações. Por isso que foram criados até dispositivos de hardware — como o HSM — para o acesso e uso controlado e restrito destas chaves. A segurança dessas chaves é criada de tal forma, que é possível saber que a senha está errada, mas não é possível determinar a senha certa.

F.A.Q.

P: O certificado foi gerado para o host  “note-juliow-ssd”, o que acontece se eu tentar acessar o HTTPS usando por exemplo https://localhost/index.html ou o IP da máquina ?

R: Como o certificado possui uma definição de DNS usando “note-automan-ssd“, se eu usar outro hostname para abrir o site, o Navegador avisa que tem algo errado — mais precisamente o erro “NET::ERR_CERT_COMMON_NAME_INVALID”

https_failed

P: Tentei abrir o endereço certinho no Mozzila, mesmo depois de importar o certificado. Por que não funcionou ?

mozilla_failedR: Repare na mensagem de erro :  MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT — O navegador Mozilla é mais restritivo, mesmo eu importando o certificado, ele avisa que trata-se de um certificado auto-assinado, mas permite continuar desde que você clique no link “Aceite o risco e continue” 😛 

P: Se eu entrar no site do Google por exemplo, digitando http://www.google.com , aparece um cadeado ?! Como ?! Eu não entrei no site com uma conexão não-segura ???

R: Sim, você entrou, o site do Google, Facebook e muitos outros possuem o acesso por HTTP (Porta 80 sem criptografia) e HTTPS (Porta 443 com criptografia). Mas, quando você entra pela conexão não segura, o site atende a conexão com HTTP, e retorna uma instrução de redirecionamento para o navegador solicitar novamente a mesma URL, porém mas usando a conexão segura. Veja por exemplo o pacote retornado pelo Google quando eu abri uma URL de pesquisa usando http://www.google.com.br/search?q=siga0984

HTTP/1.1 307 Internal Redirect
Location: https://www.google.com.br/search?q=siga0984
Non-Authoritative-Reason: HSTS

P: Como uma conexão HTTPS de um site qualquer é segura, se eu não precisei instalar na minha máquina nenhum certificado para ela funcionar ?!

R: Uma conexão segura de HTTPS exige que pelo menos uma das extremidades tenha um certificado e uma chave. No caso, os sites “abertos” como Facebook , Google e a grande maioria, usam um certificado oficial apenas no servidor, para garantir a identidade do servidor, e a chave de criptografia para codificar a conexão. O navegador acessa o certificado do servidor no “HandShake“, e com isso pode confirmar que o site que você acessou é “oficial”. Alguns sites, como os da Receita Federal, podem exigir uma autenticação por cerificado digital, como um eCPF ou eCNPJ por exemplo, que você vai usar na sua máquina, para o site conseguir determinar quem é você 😀 Não é apenas uma conexão segura e codificada, mas também permite ao servidor saber mediante o seu certificado digital quem é você, e que “você é mesmo você” 😀

Conclusão

O que vimos nestes dois últimos posts foi apenas o be-a-bá de como subir um site de testes com HTTPS. Nos próximos posts, vamos desbravar mais possibilidades desse universo.

Espero que vocês aproveitem bem e usem com sabedoria e responsabilidade estes conhecimentos, e desejo a todos como sempre TERABYTES DE SUCESSO !!! 

Referências

 

Criptografia em AdvPL – Parte 06

Introdução

No post anterior, vimos o procedimento passo a passo para instalar a biblioteca de ferramentas OpenSSL 1.1.1c no Windows. Agora, vamos abordar o primeiro caso de uso: Como gerar um certificado digital para testes do TOTVS Application Server como um servidor HTTP com conexão segura (HTTPS) 😀

Posts anteriores

O que é HTTP e HTTPS ?

Bem, HTTP é o protocolo de comunicação criado sobre uma conexão TCP/IP, usado entre os navegadores de internet (ou Web Browsers) e sites que você acessa. O protocolo HTTP permite a transferência de vários tipos de conteúdos, desde páginas HTML estáticas, imagens, vídeos , arquivos, páginas dinâmicas, etc… Os dados podem ser trafegados em diversas codificações, inclusive compactados. Mas o HTTP usa uma conexão TCP “simples”, não segura. Desse modo, existem utilitários que permitem “farejar” conexões de rede (Sniffers) que podem interceptar e ver os conteúdos dos pacotes de dados trocados entre o navegador de Internet que você usa e o site que você está acessando.

Quando você acessa  um site que pode prover uma conexão segura, criptografada, o protocolo HTTPS é utilizado — o sufixo “S” significa “Secured”. A conexão segura é feita sobre SSL/TLS, onde no início da conexão existe uma etapa chamada de “Handshake” (aperto de mãos) entre o navegador e o servidor do site, onde eles literalmente “negociam” uma conexão criptografada — vamos ver mais pra frente os detalhes dessa negociação.

Uma vez estabelecida a conexão segura, os dados transferidos entre o navegador e o site são apenas encapsulados em pacotes codificados — criptografados –, mas ao serem decodificados, as mensagens trocadas estão no padrão HTTP. Apenas o meio de comunicação faz a ponte segura entre ambos.

TOTVS Application Server como servidor HTTP

Nos posts abaixo, eu explico como configurar o TOTVS Application Server como um servidor HTTP, recomendo essa leitura antes de prosseguir:

Refrescou a memória ? Legal, vamos partir da configuração inicial do TOTVS Application Server como um servidor HTTP de páginas estáticas, e criar a configuração para ele também aceitar conexões seguras. O Arquivo de configuração appserver.ini deve ficar assim:

[http]
enable=1
port=80
path=c:\Protheus12LG\Http\note-juliow-ssd

[https]
enable=1
port=443
path=c:\Protheus12LG\Http\note-juliow-ssd

Dessa forma eu configuro o Application Server para ser, ao mesmo tempo, servidor para conexões HTTP (não seguras) e HTTPS (seguras). As portas default usada para conexões HTTP e HTTPS são 80 e 443, respectivamente.

Dentro da pasta c:\Protheus12LG\Http\note-juliow-ssd, eu vou colocar apenas um arquivo, chamado index.html. Trata-se de um arquivo texto simples, que pode ser criado com o Bloco de Notas do Windows, apenas com o seguinte conteúdo para teste:

<html>
<body>
<h1><center>Olá Mundo HTTP do Protheus
</h1></center>
</body>
</html>

Agora, quando você tenta subir o TOTVS Application Server em modo console ou serviço … ele não sobe 😀 Aparece a tela de console, e desaparece rapidinho … quando abrimos o log de console ( console.log ) do servidor, encontramos as seguintes mensagens:

[INFO ][SERVER] [Thread 17340] HTTP Server started on port 80.

Http server is ready.
Root path is c:\protheus12lg\http\note-juliow-ssd\
Listening port 80 (default)

[INFO ][SSL] [tSSLSocketAPI][Initialize] Initializing SSL/TLS.
[ERROR][SSL] [tSSLSocketAPI][Initialize] There is no configuration of SSL certificates for the server.
[FATAL][SERVER] [14/08/2019 19:54:29][Thread 17340] *** HTTPS SERVER FAILED TO START ***

[INFO ][SERVER] [Thread 17340][14/08/2019 19:54:29] Application SHUTDOWN in progress...

Bem, como eu configurei o TOTVS Application Server para ser um servidor de conexões seguras para HTTPS, eu preciso ter um certificado digital configurado para isso. Bem, como o HTTPS ainda não sobe, altere para 0 o valor da configuração Enable da seção [https], e tente iniciar novamente o TOTVS Application Server.

[INFO ][SERVER] [Thread 1092] HTTP Server started on port 80.

Http server is ready.
Root path is c:\protheus12lg\http\note-juliow-ssd\
Listening port 80 (default)

Ótimo, agora parou “de pé” 😀 Vamos testar o acesso para ver a página Index.html no Browser. Você pode usar o nome do seu computador na URL do browse. Se você não lembra ou não sabe o nome do seu computador na rede, utilize o prompt de comando (cmd.exe) e digite echo %COMPUTERNAME%:

c:\>echo %COMPUTERNAME%
NOTE-JULIOW-SSD

No caso foi mostrado o nome do meu notebook. Agora, abrimos qualquer navegador (Chrome, Firefox, Internet Explorer, Opera ,…) e montamos uma URL com “http://&#8221; + o nome do computador+’/index.html’. No meu caso, http://note-juliow-ssd/index.html , e vejamos abaixo o que deve aparecer no Browse:

ola mundo http

Eu abri a URL usando o Google Chrome … reparem no texto circulado em vermelho: “Não seguro”. O navegador avisa que a conexão estabelecida não é “segura” — isso indica que a conexão atual não usa criptografia.

Como implementar e fazer funcionar o HTTPS ?!

Então, voltando pra conexão segura, temos basicamente duas etapas para conseguir habilitar o HTTPS no TOTVS Application Server:

  • Arrumar um certificado digital
  • Configurar o certificado para o Protheus usar.

Inicialmente, um certificado digital “oficial” para um servidor HTTP deve ser gerado por uma Autoridade Certificadora (ou CA – Certification Authority ). Entre as autoridades certificadoras brasileiras estão a Certisign, Serasa Experian e outras — para a lista completa veia o link https://www.iti.gov.br/icp-brasil/estrutura

Basicamente um certificado oficial deve possuir uma cadeia de autenticação — são certificados intermediários usados pelos navegadores para confirmar a autenticidade do certificado digital em uso pelo servidor HTTPS. Como não vamos publicar um site oficial, mas sim um teste de conexão segura, vamos a nossa primeira missão usando a OPENSSL: Criar um certificado digital auto-assinado 😀

Este tipo de certificado pode ser gerado por você mesmo, e da forma que ele é gerado, ele mesmo “se autentica” — na prática, é como eu criar um certificado digital com o os dados e propriedades que eu mesmo preencho, e eu mesmo digo que “esse certificado é de verdade” 😀

Criando um certificado auto-assinado para testes usando OPENSSL

Primeiramente, apenas em caráter informativo … Eu apanhei que nem “gato no saco” até chegar a uma receita de bolo que fizesse o navegador aceitar o certificado. As informações mais importantes são as seguintes:

  • O certificado requer parâmetros adicionais — chamados de “extensões” — para que o navegador entendesse que o certificado era para um site com o nome da minha máquina — note-juliow-ssd
  • O navegador de internet, por questões de segurança, verifica se o certificado possui uma Autoridade Certificadora válida, que não seja “eu mesmo”. Logo, a única forma de eu fazer o navegador ‘confiar” no meu certificado foi importar ele pelo gerenciador de certificados do próprio navegador — no meu caso o Chrome — como um “Trusted Root Certificate Authority”.

Agora, vamos para a receita de bolo — lembre-se que é necessário ter a ferramenta OPENSSL instalada para gerar a chave e o certificado. E, para o certificado que você gerar funcionar no seu computador, lembre-se de trocar note-automan-ssd para o nome do host do seu equipamento, e seguir os passos abaixo:

Passo 1:

Crie uma pasta no seu computador para guardar a chave e o certificado a serem gerado e utilizados, por exemplo c:\Protheus12LG\certificates

Passo 2:

Na instalação da OPENSSL, foi criada uma variável de ambiente apontando para o arquivo de configuração da openssl — no meu caso, “C:\Program Files\OpenSSL-Win64\bin\openssl.cfg”. Confirme o aquivo de configuração usado na sua instalação, execute o seu editor de textos ( notepad ou notepad++ por exemplo) em Modo “Administrador” — senão você não consegue mexer nesse arquivo — e abra o arquivo de configuração no editor, vá no final do arquivo, e acrescente o conteúdo abaixo:

[ v3_self_signed ]

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage=digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName=DNS:note-juliow-ssd

Com isso, eu criei uma seção de configuração nova para colocar no meu certificado os dados necessários para o Browse entender que eu vou usar esse certificado para conexão segura em um site de testes na minha máquina ( note-juliow-ssd ). Salve o arquivo e feche o editor.

Esse passo aqui é que deu trabalho descobrir — sem ele, mesmo que eu importasse o certificado como “confiável”, o Chrome retornava o erro “ERR_CERT_INVALID_COMMON_NAME”, como se o certificado não tivesse as informações corretas para ser usado em um site usando o nome da minha maquina … 

Passo 3:

Abra um prompt de comando (cmd.exe) no Windows, entre na pasta onde você vai gerar o certificado digital e a chave privada do certificado, e execute o comando abaixo:

openssl req -x509 -nodes -newkey rsa:4096 -keyout note-juliow-ssd.key -out note-juliow-ssd.cer -days 365 -subj “/C=BR/ST=SP/L=Sao Paulo/O=Tudo em AdvPL/CN=note-juliow-ssd” -extensions v3_self_signed -reqexts v3_self_signed

Com esse pequeno monstrinho, em apenas uma etapa eu consigo fazer a OpenSSL criar para mim uma chave privada de 4096 bits, usando criptografia RSA, gravar a chave SEM SENHA no arquivo note-juliow-ssd.key, criar um certificado no padrão x509 usando esta chave, com validade de um ano, colocando alguns dos meus dados no certificado, e acrescentando as extensões necessárias que colocamos no passo 2 na configuração da OpenSSL, salvando o certificado criado no arquivo note-juliow-ssd.cer

Agora vamos ver o resultado:

C:\>cd Protheus12LG\certificates

C:\Protheus12LG\certificates>openssl req -x509 -nodes -newkey rsa:4096 -keyout note-juliow-ssd.key -out note-juliow-ssd.cer -days 365 -subj "/C=BR/ST=SP/L=Sao Paulo/O=Tudo em AdvPL/CN=note-juliow-ssd" -extensions v3_self_signed -reqexts v3_self_signed
Generating a RSA private key
.......................................................................................................++++
..........................++++
writing new private key to 'note-juliow-ssd.key'
-----

C:\Protheus12LG\certificates>

Para conferir o conteúdo do certificado que foi gerado, executamos o seguinte comando:

openssl x509 -text -in note-juliow-ssd.cer -noout

E, abaixo vamos ver o que foi retornado:

Certificate:
Data:
Version: 3 (0x2)
Serial Number:
5e:a9:76:38:db:c0:3c:5e:cf:f6:8b:e0:cf:7c:b8:5c:ad:87:59:d9
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = BR, ST = SP, L = Sao Paulo, O = Tudo em AdvPL, CN = note-juliow-ssd
Validity
Not Before: Aug 16 00:06:19 2019 GMT
Not After : Aug 15 00:06:19 2020 GMT
Subject: C = BR, ST = SP, L = Sao Paulo, O = Tudo em AdvPL, CN = note-juliow-ssd
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (4096 bit)
Modulus:
00:bc:5b:56:04:e2:8a:58:88:65:22:86:ce:33:42:
c4:15:1a:ca:9b:4e:ad:7e:7b:42:92:7e:64:e9:3b:
5c:30:f9:de:34:b0:c3:fb:e2:62:69:e7:d7:3c:f1:
cb:78:c2:84:da:15:c3:2b:22:2c:30:7d:71:3f:d4:
47:34:0a:39:50:d4:8f:bc:fa:17:0b:ee:6e:38:28:
1a:06:b3:38:82:51:64:bf:7b:d0:75:ea:fd:e1:f9:
85:ac:21:fa:f8:ee:fb:b5:79:6a:02:f5:83:15:fa:
95:b5:18:1f:76:e7:57:41:a1:f7:84:23:bd:8c:31:
ee:02:c6:58:43:6a:40:ff:24:41:b6:33:ce:eb:7b:
ad:14:d0:43:cf:bf:75:ec:6d:5a:be:94:83:6e:d7:
71:ec:40:b8:68:36:c8:2a:90:9c:d0:6e:64:9c:e6:
3e:28:6e:c5:3b:70:a4:c5:7d:ff:91:0d:f8:f2:f7:
27:dd:cd:04:06:2c:3a:ce:78:23:d3:43:2f:49:77:
e5:4e:13:2d:18:8c:43:5d:2e:7d:70:c4:db:5f:dc:
9a:b1:e6:05:37:14:f8:82:8a:5a:0c:47:22:07:ab:
61:20:43:83:b5:cc:8f:09:93:5f:b4:32:9b:19:b9:
50:35:91:2b:bb:8b:f7:5c:a6:7b:1e:29:b4:73:0d:
f8:93:e9:d6:9a:90:f8:49:a4:ab:89:8a:56:9f:8f:
6b:e1:7b:64:b4:aa:f8:11:6b:b9:92:66:aa:46:04:
5d:bb:5d:17:52:e1:17:36:86:80:70:1f:64:45:47:
6f:12:f2:cb:37:20:2b:6c:36:32:a7:ed:5a:9b:a9:
fa:47:34:a8:1a:79:8d:1d:84:e1:29:9e:a9:64:97:
f3:83:64:79:9e:9d:72:2a:05:0d:4e:58:ec:ff:2c:
d7:c5:a2:5c:b2:e6:08:26:8e:17:12:e3:99:2e:50:
7f:a6:3f:ef:6c:aa:45:08:0d:f8:db:fc:15:f4:42:
29:2d:13:d1:4c:2b:3e:72:1f:e9:0c:2a:bd:38:60:
5c:27:dd:63:7c:32:ac:c0:f0:06:85:1a:dc:64:67:
d9:44:bc:bc:83:fc:65:2a:1a:0c:04:77:ea:29:06:
f8:de:35:ba:4b:cd:23:c6:87:11:bf:4d:cc:d8:d0:
20:54:28:50:dd:b2:e3:21:f2:9d:67:1a:27:11:15:
6e:92:ac:3c:ac:66:70:86:31:bc:55:39:85:fe:9f:
65:02:29:d6:cc:36:51:f2:e2:15:93:13:6f:a1:b5:
47:af:cc:20:c7:94:fe:44:37:59:90:98:46:fd:be:
7a:1c:c1:87:7a:57:94:05:db:0a:60:f3:ca:42:1b:
01:89:35
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Authority Key Identifier:
DirName:/C=BR/ST=SP/L=Sao Paulo/O=Tudo em AdvPL/CN=note-juliow-ssd
serial:5E:A9:76:38:DB:C0:3C:5E:CF:F6:8B:E0:CF:7C:B8:5C:AD:87:59:D9

X509v3 Basic Constraints:
CA:FALSE
X509v3 Key Usage:
Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment
X509v3 Subject Alternative Name:
DNS:note-juliow-ssd
Signature Algorithm: sha256WithRSAEncryption
78:55:d6:bf:57:6e:69:8b:c6:7e:27:7d:bc:e6:df:bc:17:26:
62:3b:73:e5:a5:46:51:6d:09:fa:45:c6:c3:6f:d3:9f:70:d3:
cb:2c:42:c8:48:fa:b5:ec:14:8a:d9:4c:c8:d9:eb:ab:bb:3a:
d7:35:e5:ad:88:90:1c:2d:91:ea:08:e1:87:f9:b8:dc:d4:d7:
58:77:8f:6b:b9:da:65:3c:e3:7a:fb:08:91:94:c4:43:08:53:
64:1f:ad:f9:93:66:bf:fa:58:af:25:a7:09:c8:f4:a9:77:fb:
4e:f5:33:02:f8:86:26:6e:f6:77:d1:7c:74:be:6d:09:4d:0e:
4a:38:44:08:bd:b8:a2:d3:85:c3:e7:a0:1d:81:57:3e:40:cc:
0e:08:8a:60:56:b7:c2:27:78:c1:6a:30:1e:58:ab:ab:44:a4:
9e:c6:7b:15:a9:e6:14:65:e0:b2:88:85:66:f1:cc:32:34:6b:
d9:a6:f5:e7:3d:5b:b5:a9:a8:a4:82:17:48:4e:f3:6d:26:80:
3c:72:66:23:c9:ee:d3:ed:0b:fe:0d:8d:04:b5:17:da:01:f4:
20:21:79:0f:18:7b:04:cd:c6:90:5f:a4:71:82:bd:90:d5:ce:
f0:c2:ea:1c:70:f7:5f:3c:d6:1c:cd:54:eb:7d:70:75:03:7c:
3f:49:02:3c:65:69:89:a2:c2:aa:9a:62:64:45:2f:e2:51:c2:
8f:d5:00:85:a1:e6:ec:48:4d:bb:5f:4f:09:73:4f:56:70:54:
04:0b:60:5f:2c:c0:cb:61:45:3b:5c:ff:cc:ac:67:9f:2a:67:
12:5e:38:16:af:b3:96:f1:24:2f:27:fe:63:9f:0b:d6:11:31:
08:7c:26:b9:2d:48:66:0b:b8:c3:4e:b3:0f:62:f7:79:17:0f:
a8:c7:fa:71:ad:40:7a:2c:92:a5:d8:5b:b9:ff:a5:4e:d7:88:
ad:59:ab:c4:1d:9b:ed:52:20:d0:20:70:dc:ed:09:03:f9:4e:
5d:5b:ed:51:86:74:d5:8d:62:ab:cc:5a:45:00:9d:28:d2:45:
bc:02:c1:c8:76:15:94:04:34:fe:68:69:52:72:68:13:31:ca:
6b:ac:17:0e:2c:3d:f0:4e:b8:ba:b3:48:f2:06:5b:e6:aa:be:
35:e8:81:48:78:14:3b:f6:48:eb:13:ef:bd:9b:3f:83:1c:4e:
24:be:b7:b8:c6:30:c0:00:cb:6c:74:50:3e:3d:84:d3:a5:ce:
fb:6e:ac:2c:62:eb:5f:96:d4:77:8a:46:e0:9f:6c:43:13:e9:
4f:09:3b:e1:9a:12:b6:35:83:19:8e:4b:59:78:a5:9f:cd:fc:
6d:ce:d6:53:fc:72:15:db

Se verificarmos o diretório atual, veremos que os dois arquivos — chave privada e certificado — foram criados. UFA … agora, vamos configurar o certificado e a chave privada para o Protheus utilizar e virar servidor HTTPS.

Passo 4:

Abra o arquivo de configurações do TOTVS Application Server ( appserver.ini ) , e acrescente o conteúdo abaixo:

[sslconfigure]
CertificateServer=C:\Protheus12LG\certificates\note-juliow-ssd.cer
KeyServer=C:\Protheus12LG\certificates\note-juliow-ssd.key

Com isso, eu informo ao Protheus que ele pode ser um servidor de conexão segura, usando o certificado e a chave privada informadas na configuração. Por hora é tudo o que precisamos saber e fazer pra mágica funcionar.

Aproveite que o arquivo de configuração está aberto, configure novamente a chave Enable=1 na seção [HTTPS] e salve o arquivo de configuração.

Passo 5: 

Inicie novamente o TOTVS Application Server. Se tudo estiver certo, agora ele tem que subir "certinho"

[INFO ][SERVER] [Thread 13104] HTTP Server started on port 80.

Http server is ready.
Root path is c:\protheus12lg\http\note-juliow-ssd\
Listening port 80 (default)

[ERROR][STORE] Certificates loaded from [C:\Protheus12LG\certificates\note-juliow-ssd.cer].
[INFO ][SERVER] [Thread 13104] HTTPS Server started on port 443.

Https server is ready.
Listening port 443 (default)

Passo 6: 

Abra o Chrome, e informe a URL de acesso da página de testes, mas agora usando HTTPS ao invés de HTTP

https://note-juliow-ssd/index.html

E, para nossa surpresa ….

chrome_cert_authority_invalid

O navegador de internet fez o “HandShake” com o HTTPS do Protheus, e viu que o certificado usado não tem uma Autoridade Certificadora válida. Logo, ele avisa que o site que você está acessando pode ser uma roubada …. Reparem no erro no meio da tela : ERR_CERT_AUTHORITY_INVALID. Como o certificado foi eu mesmo que gerei, e está na minha máquina, e é para testes, eu posso fazer o navegador “confiar cegamente” no meu certificado e funcionar redondinho sem mostrar mais essa mensagem.

Passo 7:

Vamos importar o certificado de testes utilizado para dentro do navegador, dizendo pra ele que este certificado é um “Trusted Root Certificate” — ATENÇÃO : PELO AMOR DE DEUS, NÃO FACA ISSO COM UM CERTIFICADO QUE NÃO FOI VOCÊ QUE GEROU OU QUE VOCÊ NÃO SABE A PROCEDÊNCIA. O certificado que a gente acabou de gerar é confiável por que você gerou ele e vai usar na sua máquina.

No Google Chrome, clique nos três pontinhos do canto superior direito da janela’e clique em “Configurações”. Ao abrir a janela de configurações, expanda a opção “Avançado”, e clique em “Privacidade e Segurança”, e depois em “Gerenciar Certificados”

chrome_avancado

Será mostrada a janela de controle de certificados. Localize e posicione na aba “Trusted Root Certification Authorities”, e depois no botão “Import”

chrome_certificates

Ao clicar em “Import”, será aberto um assistente de importação de cerificado digital:

chrome_import_1

Clique em “Next”, e na próxima tela informe o caminho completo do certificado a ser importado, ou use o botão “Browse” para localizar e selecionar o certificado que acabamos de criar.

chrome_import_2

Ao clicar em “Next” será mostrada uma tela para perguntar onde o certificado deve ser importado. Já vi vir preenchido com “Trusted Root Certification Authorities”, clique em “Next”.

chrome_import_3

Chegamos na última tela, o assistente mostra o resumo do que será feito. Clique em “Finish”.

chrome_import_4

Ao clicar em Finish, é mostrado um aviso de segurança, dizendo que você está para instalar uma Autoridade Certificadora que não pode ser verificada — por que não existe — e que diz representar o nome do host da sua máquina, e diz também que se você fizer isso, o Windows vai passar a confiar em qualquer certificado subsequente que seja emitido a partir desse. Pode confirmar 😀

chrome_import_5

Pronto! Insalado 😀

chrome_import_6

Passo 8:

Agora sim, abra novamente a página de testes com o protocolo seguro — pode ser necessário fechar e abrir novamente o navegador para o acesso funcionar. Tudo dando certo, devemos ver isso aqui:

chrome_agora_foi

Repare no “cadeado” destacado em vermelho. Isso informa que, agora sim, finalmente, estamos usando uma conexão SEGURA / CRIPTOGRAFADA. Agora, para ver os detalhes dessa criptografia do ponto de vista do browse, clique no cadeado:

chrome_valido

Vamos ver mais detalhes, clicando em cima da palavra  “Certificado”, e consultar as suas propriedades.

certificate_properties

Na aba de detalhes do certificado, podemos ver todas as propriedades que colocamos ao criá-lo, e como instalamos ele como um certificado confiável na máquina, o Windows agora confia nele 😀

Conclusão

Bem, com apenas esses “poucos passos” conseguimos montar um servidor de páginas HTTP com conexão segura … agora, no próximo post, vou mostrar o que um hacker consegue ver ao rastrear uma conexão não segura e uma conexão segura 😀

Agradeço a todos pela audiência, e lhes desejo TERABYTES DE SUCESSO !!!

Referências

 

 

Utilizando THF com AdvPL – Parte 01

Introdução

O THF (Totvs Html Framework) é um projeto aberto e colaborativo de um Framework para aplicações WEB responsivas e dispositivos móveis. Baseado em Angular e Typescript, disponibiliza uma série de componentes que facilitam a criação de aplicações. O site oficial com tudo sobre o THF é https://thf.totvs.com.br/

É altamente recomendável que você tenha algum conhecimento sobre Angular e TypeScript, senão você corre o risco de ficar meio perdido — assim como eu fiquei — ao tentar usar o THF.

Iniciando

Basta seguir o tutorial do site para instalar o NodeJS e NPM, e o AngularCli. Sem truques, apenas next-next-finish. Uma vez instaladas as aplicações necessárias, uma dica importante na criação de um novo projeto — Ao configurar as dependências do projeto criado para instalação, é disponibilizada uma lista de chaves e valores das dependências no site. Para atualizar o arquivo package.json que foi criado com o novo projeto, procure cada chave informada no site no arquivo gerado para o seu projeto. Caso a chave já exista, atualize o valor da versão, e caso a chave não exista, acrescente ela no arquivo.

Criação do Projeto AgendaTHF

Em posts anteriores, sobre o CRUD AdvPL, foi construída uma agenda simples de contatos para ser acessada via SmartClient. Então, num projeto posterior, foi construída uma interface em AdvPL ASP usando HTML/CSS e JavaScript “puro”, sem framework algum. Vamos ver agora como seria a criação de uma interface para esta Agenda usando o Totvs Html Framework.

Todas as etapas para a criação do projeto foram feitas de acordo com as instruções detalhadas no tópico “Começando com o THF”, inclusive as etapas foram seguidas até o final, com a criação do componente “hello-world” e de um menu do THF para chamá-lo na tela.

Ao criar um novo projeto, devemos abrir um prompt de comando do Windows (cmd) e usar  o comando abaixo: — onde AgendaTHF é o nome do projeto.

ng new AgendaTHF --skip-install

Após reconfigurar as dependências e versões de dependências no arquivo package.json, gerado dentro da nova pasta AgendaTHF — criada automaticamente para o Projeto — executamos o comando de instalação das dependências, e depois a instalação do THS neste projeto, executando os seguintes comandos dentro da pasta AgendaTHF:

npm install
npm install @totvs/thf-ui --save

Não se assuste, a instalação de tudo pode demorar mais de um minuto. As sub-pastas com os componentes instalados somam quase 300 MB de arquivos.

Configuração do módulo principal e demais etapas

Procure o arquivo “app.module.ts“, ele deve estar dentro da pasta “AgendaTHF\src\app“. Neste arquivo é que deve ser acrescentado o import do THFModule — os detalhes estão no Passo 2.2 do tutorial “Começando com o THF”

Os demais procedimentos são relativamente simples, ligados a edição dos arquivos modelo gerados para a aplicação, para adequá-lo ao uso do THF. A criação do componente “hello-world” é feita pelo prompt de comando ma pasta raiz do projeto (AgendaTHF), e o resultado final — depois de colocar um servidor http no ar usando o comando “ng serve”, deve ser algo assim:

THF Hello World

Teste do Hello World

A primeira impressão é muito bonita, e logo percebe-se a responsividade da interface alterando o tamanho da janela do Browser. Em tela maximizada, a página do Hello World é aberta na área de conteúdo e o menu continua visível. Ao reduzir o tamanho da interface, o menu é automaticamente “escondida”, sendo acessível novamente por um link na parte superior esquerda.

THF Hello World Option

Atualmente existem aproximadamente 81 componentes disponíveis para você codificar uma aplicação responsiva usando o THF — Vide índice de API no link “https://thf.totvs.com.br/documentation“. Além dos componentes, são disponibilizados Serviços, Diretivas, Modelos de Dados — para armazenamento em dispositivo local — enfim, têm muita coisa.

A pasta criada com este projeto é para desenvolvimento. No momento de fazer a publicação, deve-se executar uma instrução de build, explicada no portal do THF, que vai gerar uma pasta com os arquivo estáticos e scripts. A publicação da aplicação exige apenas um servidor HTML estático, o Protheus como servidor HTTP atende perfeitamente — exceto por alguns detalhes de configuração de página não encontrada, que precisam ser customizados.

Conclusão

Este artigo ficou na banheira desde o Natal de 2018, provavelmente a documentação já deve ter mais atualizações e componentes. O projeto da Agenda usando o THF vai ser continuado ao longo dos próximos posts, em breve 😀

Novamente agradeço a audiência e desejo a todos TERABYTES DE SUCESSO !!! 

Referências

 

CRUD em AdvPL ASP – Parte 04

Introdução

No post anterior (CRUD em AdvPL ASP – Parte 03), foi implementada a consulta básica da Agenda em ADVPL ASP — pelo menos os quatro botões de navegação (Primeiro, Anterior, Próximo e Último). Agora, vamos ver como mostrar no Browse a imagem de cada contato, gravada no Banco de Dados.

Trocando o retorno para o Browse

Qualquer link apw solicitado ao Web Server do Protheus executará uma função AdvPL definida em uma configuração de pool de processos, que por default devem retornar uma string em AdvPL, que será interpretada pelo Web Browse como sendo texto HTML.

Este comportamento default é implementado pelo Web Server, que por default informa no Header HTTP de retorno da requisição a informação Content-Type: text/html — Quando utilizamos a função AdvPL HTTPCTTYPE(), dentro do processamento de uma requisição AdvPL ASP, nós podemos TROCAR o tipo do conteúdo de retorno. Por exemplo, se eu quiser retornar uma imagem do tipo PNG para o Web Browse, a partir de uma requisição de link .apw, basta eu chamar a função HttpCTType(“image/png”), e ao invés de retornar ao Browse um HTML, eu retorno o conteúdo (bytes) do arquivo da imagem.

Logo, vamos implementar o retorno da imagem de forma BEM SIMPLES. Primeiro, vamos aproveitar a requisição “agenda.apw”, e verificar se ela recebeu um identificador adicional na URL, que vamos chamar de IMGID. Este identificador vai conter o numero do registro do contato da agenda que nós gostaríamos de recuperar a imagem. E, no fonte WAGENDA.PRW, vamos acrescentar o seguinte tratamento, logo no inicio da função WAGENDA() — pouco depois de abrir a tabela ‘AGENDA” no Banco de Dados.

If !empty(HTTPGET->IMGID)
  DbSelectArea("AGENDA")
  Dbgoto( val(HTTPGET->IMGID) )
  cBuffer := AGENDA->IMAGE
  HTTPCTType('image/png') 
  Return cBuffer
Endif

Simples assm, caso seja recebida a URL agenda.apw?IMGID=nnn, o programa vai posicionar no registro correspondente da tabela de agenda, ler o conteúdo da imagem gravada no campo memo “IMAGE”, e retornar ela ao Browser, avisando antes pela função HTTPCTType() que o Browse deve interpretar este conteúdo como uma IMAGEM.

Agora, dentro do fonte WAGENDA.APH, que compõe a página da agenda, vamos fazer uma alteração na tag “img”, responsável por mostrar a imagem do contato atual da agenda.

<tr><td>
<%If HTTPPOST->_SHOWRECORD .and. !Empty(AGENDA->IMAGE) %>
<img style="width: 120px;height: 160px;" src="agenda.apw?IMGID=<%=cValToChar(recno())%>">
<% else %>
<img style="width: 120px;height: 160px;" src="./images/Agenda_3x4.png">
<% Endif %>
</td></tr>

Dentro do APH em questão, eu já estou com a tabela da Agenda aberta. Caso eu vá mostrar o registro de algum contato no Browse, e o campo de imagem deste contato possua conteúdo, eu coloco que a imagem deve ser buscada no endereço

agenda.apw?IMGID=<%=cValToChar(recno())%>

Desta forma, quando o Browse receber o HTML de retorno de uma página da Agenda, o Browse vai desenhar a tela, e na hora de mostrar a imagem, o Browse internamente dispara mais uma requisição para a a URL agenda.apw, informando via URL o identificador da imagem desejada.

Vou fazer um teste no Browse, por exemplo retornando a foto do registro 2 da agenda no meu ambiente, digitando direto a URL “http://localhost/agenda.apw?IMGID=2

WEB Agenda IMGID

Ao navegar na agenda, e posicionar no contato, a imagem passa a ser atualizada na tela, veja exemplo abaixo:

WEB Agenda Imagem

Conclusão

Utilizando a troca do retorno, eu consigo informar ao browser o que eu estou retornando, e isso me permite eu retornar por exemplo XML, Imagens, Documentos, o céu (e a String AdvPL) são o limite!

Agradeço novamente a audiência, e desejo a todos TERABYTES DE SUCESSO !!! 

Referências