# HTTP

> Referência do driver HTTP: ler ciclicamente endpoints HTTP e HTTPS como tags, credenciais, mapeamento de caminho, interpretação do corpo, escritas por PUT e tipos.

O driver HTTP lê ciclicamente **endpoints HTTP genéricos** como tags: um sensor de LAN com um
servidor web minúsculo, um gateway que publica leituras em URLs fixas, um serviço seu.
É o driver em modo cliente mais simples do produto: **o Ganter Lab conecta ao
equipamento** com requisições GET simples e lê o corpo de cada resposta como um valor.

Duas propriedades traçam o limite do que ele serve:

- O transporte é **a escolha do próprio dispositivo**. Um dispositivo alcança o serviço
  dele por TLS até a marcação **Enviar por HTTP simples** dizer outra coisa, e um host
  escrito com `http://` ou `https://` na frente move essa marcação e fica guardado como o
  host puro, então os dois nunca se contradizem.
  De um jeito ou de outro o driver envia a credencial do dispositivo, um
  usuário e uma senha como HTTP Basic ou um token bearer, em toda requisição. O que
  os drivers [AVEVA PI](driver-aveva-pi) e [Redfish](driver-redfish) ainda acrescentam
  para esses dois serviços é o vocabulário deles: caminhos PI e WebIds, árvores de
  recursos do Redfish, que este driver desconhece.
- O **corpo inteiro da resposta é o valor**. O driver não é um extrator de campo
  JSON: uma tag numérica espera que o corpo seja o número puro.

## Campos de conexão {#connection-fields}

| Campo | O que é | Formato | Padrão |
|---|---|---|---|
| Host | O nome de host ou endereço IP do endpoint. Um host escrito com `http://` ou `https://` na frente move a marcação de transporte abaixo para combinar e fica guardado sem ela. Uma porta escrita depois do host (`:8080`) vai para o campo Porta e um caminho depois dele (`/api`) vai para o caminho do recurso, então dá para colar aqui um endereço inteiro como `http://192.168.0.5:8080/api`. Um endereço IPv6 mantém os colchetes. | Nome de host, IP, ou qualquer um dos dois com `http://` ou `https://` na frente | vazio |
| Porta | A porta TCP. Um dispositivo novo a deixa vazia, e um campo vazio significa a porta em que o transporte escolhido responde, 443 por HTTPS e 80 em claro: o campo mostra essa porta em cinza e acompanha a escolha do transporte, que é também como se lê um dispositivo salvo com 0. | 1 a 65535, ou vazio | vazio |
| Caminho do recurso | Um prefixo de caminho opcional posto na frente do caminho de **toda** tag, por exemplo `api/v2`. Em branco não prefixa nada. | texto de caminho | em branco |
| Enviar por HTTP simples | Rebaixa este dispositivo de HTTPS para HTTP em claro. Desmarcado significa HTTPS, que é o que mantém uma credencial fora do cabo. O painel declara a consequência: em HTTP simples as requisições, e qualquer credencial que o dispositivo carregue, viajam sem criptografia. Use isso para um endpoint que não responde em nenhum outro transporte. | ligado / desligado | desligado |
| Usuário | Conta para autenticação **HTTP Basic**, usada só quando nenhum token bearer está definido. Vazio (e sem token) deixa as requisições anônimas. | Texto livre | vazio |
| Senha | A senha que acompanha o usuário. Protegida em repouso por usuário do Windows; um segredo digitado sob outra conta do Windows aparece como ilegível e precisa ser digitado de novo. | Texto livre | vazio |
| Token bearer | Um token enviado como `Authorization: Bearer …` em toda requisição. Quando definido, ele **prevalece sobre** o par usuário e senha. Protegido em repouso do mesmo jeito. | Texto do token | vazio |

Ao conectar, o driver verifica o endpoint com uma requisição HEAD ao **endereço
configurado**, host mais caminho do recurso, recorrendo a GET quando o HEAD não está
implementado; um endereço que responde com sucesso a qualquer um dos dois conta como alcançável.
Um serviço cuja raiz responde 404 enquanto a API dele responde normalmente está, portanto, online,
desde que o caminho do recurso aponte para a API. Em HTTPS, o certificado TLS do serviço
é aceito quando o Windows confia nele, ou quando você aprovou exatamente esse certificado em
[Acesso a equipamentos](#equipment-access), na página deste driver. Uma credencial num
dispositivo rebaixado para HTTP simples viaja sem criptografia, e a estação diz isso no
diário do conector quando o dispositivo conecta. Cada requisição recebe dez segundos:
um endpoint que aceita a conexão e depois não diz nada custa uma leitura,
não o dispositivo inteiro, porque as outras tags do dispositivo são lidas na mesma
passada. O intervalo de leitura é configurável: o padrão do dispositivo (1000 ms) vale para
toda tag que não declare o próprio.

## Endereçamento da tag {#tag-addressing}

O campo **Caminho** da tag é o caminho da URL relativo ao caminho do recurso do dispositivo:

| Campo | O que faz | Valores | Padrão |
|---|---|---|---|
| Caminho | O caminho requisitado por esta tag. A URL completa é `<transport>://<host>:<port>/<resource path>/<path>`. | Texto livre (obrigatório) | vazio |

Exemplo: host `192.168.0.40` rebaixado para HTTP simples, caminho do recurso `api`,
caminho da tag `sensors/temp` lê `http://192.168.0.40/api/sensors/temp`.

## Leituras {#reads}

Cada ciclo faz GET na URL da tag e interpreta o **corpo inteiro da resposta** pelo tipo de
dado declarado da tag:

| Tipo | Corpo aceito |
|---|---|
| Float | Um número, em formato invariante (`21.5`, ponto decimal, sem separador de milhar) |
| Int32 | Um inteiro (`42`) |
| Boolean | `true` ou `false` |
| String | Qualquer coisa; o corpo é o valor tal como está (um documento JSON chega como o texto bruto dele) |

Um corpo que o tipo declarado não consegue interpretar, ou um código de status que não é de sucesso, lê como
leitura que falhou: a tag vai a qualidade ruim e a política de falha de leitura dela decide o que é
apresentado, como descrito na página [Connector](connector). Um status que não é de sucesso é o
endpoint recusando a leitura, e o motivo da tag nomeia o status e cita o que o endpoint disse junto
(`HTTP 404 Not Found: …`), com as mesmas palavras de uma escrita ou de um comando recusados. Um
corpo que o tipo declarado não consegue interpretar dá à tag um motivo que cita o que não pôde ser
lido, e o dispositivo continua conectado. Um endpoint que não responde nada é a conexão do
dispositivo falhando: o dispositivo relata isso e reconecta, e as tags dele apontam para ele. A faixa vermelha da tag diz um status assim na língua da estação, com o que ele significa nos códigos 401, 403 e 404, e um corpo que não se interpreta como uma resposta que não é um valor do tipo da tag; a página Eventos guarda as palavras do próprio endpoint.

## Escritas {#writes}

Tags com modo de acesso gravável escrevem com **PUT** na mesma URL: o corpo é
o valor em JSON, enviado com o tipo de conteúdo `application/json`. Um número vai como
literal puro (`42.5`), um booleano como `true` ou `false`, e texto vai entre aspas
(`"automatic"`). O endpoint decide o que fazer com isso; um status que não é de sucesso é o endpoint recusando o valor: a recusa nomeia o status e cita o que o endpoint disse junto, com as mesmas palavras da recusa de um comando, e quem escreveu o valor lê o motivo. Como em todo o resto, a caixa de escrita recebe o valor de engenharia e os
estágios de conversão da tag são revertidos antes de o valor bruto ir para o barramento, como descrito
na página [Connector](connector).

## Tipos de dado suportados {#supported-data-types}

Boolean, Int32, Float e String.

## Comandos {#commands}

Uma tag lê um valor; um comando pede ao serviço que ele faça algo. Declare cada um no
dispositivo, no cartão **Comandos** da página dele: um nome, o caminho a que ele é enviado por POST (sob o
endereço do próprio dispositivo, exatamente como o caminho de uma tag) e, opcionalmente, o nome do único valor
que ele recebe. O verbo Executar da linha o envia e relata o que o serviço respondeu, e o comando
também vira um método no dispositivo, dentro do espaço de endereços OPC UA desta estação, então qualquer coisa
que consiga chamar um método consegue dispará-lo. O valor que você digita é enviado como corpo da requisição, tal como
foi escrito.

O que o serviço responde é o resultado do comando. Um status que o serviço devolve fora da faixa de
sucesso é o serviço recusando o comando, não a conexão falhando: a recusa nomeia o status
e cita o que o serviço disse junto ("HTTP 500 Internal Server Error: the burner is locked out"), e nada mais no
dispositivo é perturbado por isso.

## Descoberta {#discovery}

O driver não tem varredura de descoberta. Adicione cada endpoint por host e cada valor pelo
caminho dele; o fluxo de adicionar um dispositivo está descrito na página [Connector](connector).

## Acesso a equipamentos {#equipment-access}

Um endpoint HTTPS com um certificado autoassinado, ou emitido por uma autoridade própria, apresenta um certificado que nenhuma raiz instalada no Windows garante. Essa raiz não precisa ser instalada neste computador. A primeira conexão é recusada, o dispositivo mostra **Esperando a aprovação do certificado** na árvore e na página dele, cujo botão **Revisar o certificado** abre este cartão no certificado, e o certificado espera em **Acesso a equipamentos**, no fim da página do driver HTTP, o mesmo cartão que a página do driver OPC UA traz, até você decidir:

| Grupo | O que lista | O que você pode fazer |
|---|---|---|
| Esperando aprovação | Cada certificado recusado, sob o nome que ele declara: a impressão digital SHA-256, o endereço em que foi encontrado, quando tentou pela última vez e quantas vezes, e os detalhes (titular, emissor, nomes de domínio, datas de validade). O que o **Revisar o certificado** de um dispositivo abriu fica marcado como Selecionado para revisão. | **Aprovar** aceita o certificado a partir da próxima tentativa de conexão. **Bloquear** continua recusando-o sem listá-lo aqui de novo. **Descartar todos os certificados pendentes** esvazia a lista sem aprovar nem bloquear nada. |
| Equipamentos aprovados | Os certificados que você aprovou ou importou, com quem decidiu e quando, e o endereço em que cada um foi encontrado por último. | **Retirar a aprovação** encerra a conexão e devolve o certificado à lista. **Importar certificado** aprova um arquivo de certificado público que você já tem (.der, .cer, .crt ou .pem) antes da primeira conexão. |
| Equipamentos bloqueados | Os certificados que você bloqueou. Um certificado bloqueado é recusado mesmo que o Windows confie nele. | **Desbloquear** devolve o certificado à lista, sem aprová-lo. |

Confira a impressão digital com quem administra o equipamento antes de aprovar o certificado. Uma aprovação aceita aquele certificado e nenhum outro, e só dentro das datas de validade dele; ela substitui a raiz que falta no Windows e o nome que o certificado traz, então um endpoint chamado pelo endereço IP conecta mesmo que o certificado dele traga outro nome, e nada mais do certificado é afrouxado. Quando o equipamento responde num endereço cujo certificado você aprovou com outro (um certificado renovado), a leitura para, o novo espera aqui e a estação avisa "Certificado mudou: `<nome>`" com um botão **Revisar**. Um certificado em que o Windows já confia é aceito como antes e nunca aparece aqui; nada é aprovado automaticamente.

A própria falha do driver diz o motivo em vez de um erro de TLS sem nome: "O certificado deste equipamento (os primeiros 16 caracteres da impressão digital) espera a sua aprovação em Acesso a equipamentos, na página do driver HTTP. A leitura começa assim que você aprová-lo." Um bloqueado diz "…está bloqueado nesta estação. Revise-o em Acesso a equipamentos, na página do driver HTTP." Um certificado fora das datas de validade, revogado ou com a assinatura quebrada é recusado com esse motivo e nunca é listado, porque nenhuma aprovação o torna válido.

As decisões ficam na pasta de dados da estação, em `ua\pki\http`, e sobrevivem a um reinício. Os verbos só são desenhados para um papel que pode configurar o Connector, e só agem na janela da própria estação: um navegador em outro aparelho lê o cartão sem mudá-lo, e nenhuma ferramenta de agente aprova um certificado (`connector_browse` indica o dispositivo em espera com `awaitingCertificate`). A lista guarda até 100 certificados esperando aprovação; quando está cheia, um novo continua recusado mas não é listado, e o cartão diz isso.
