Repository navigation
pedido resposta
Home > Ler o pedido e responder
Vale para a 1.1 em diante · Delphi e Lazarus · Nível: iniciante
Em uma frase: dentro da rota, ARequest é o que chegou e AResponse é o que
você devolve.
Você vai precisar: uma rota funcionando (Rotas e parâmetros).
Units: RALRequest, RALResponse, RALParams, RALTypes, RALConsts,
RALMIMETypes.
| Quero ler | Como | Exemplo do que chega |
|---|---|---|
| parâmetro da URL | ARequest.GetQuery('cidade') |
/clientes?cidade=Recife |
| parâmetro do caminho | ARequest.ParamByName('id').AsInteger |
/clientes/:id → /clientes/7
|
| campo de formulário | ARequest.GetField('nome') |
nome=Ana (form ou multipart) |
| cabeçalho | ARequest.GetHeader('X-Empresa') |
X-Empresa: 12 |
| cookie | ARequest.ParamByName('sessao').AsString |
Cookie: sessao=abc |
| o corpo inteiro como texto (JSON, XML) | ARequest.RequestText |
{"nome":"Ana"} |
| qualquer um, pelo nome | ARequest.ParamByName('x') |
o primeiro com esse nome, de qualquer tipo |
| o método | ARequest.Method |
amGET, amPOST... |
| quem chamou | ARequest.ClientInfo.IP |
192.168.0.20 |
| o usuário logado | ARequest.Authorization |
ver Autenticação |
Os Get... devolvem texto vazio quando o item não veio. ParamByName devolve
nil: teste antes (if ARequest.ParamByName('x') <> nil then).
Converter um parâmetro (TRALParam):
| Propriedade | Lê como |
|---|---|
AsString |
texto |
AsInteger, AsInt64
|
número inteiro |
AsDouble, AsCurrency
|
número com casas (aceita 2.5 e 2,5) |
AsBoolean |
verdadeiro/falso |
AsDateTime |
data e hora |
FileName + SaveToFile(pasta, nome)
|
arquivo enviado (upload) |
procedure TForm1.Upload(ARequest: TRALRequest; AResponse: TRALResponse);
var
vArq: TRALParam;
begin
vArq := ARequest.ParamByName('arquivo'); // o nome do campo no formulário
if (vArq = nil) or (vArq.FileName = '') then
begin
AResponse.Answer(HTTP_BadRequest, '{"erro":"envie o campo arquivo"}');
Exit;
end;
vArq.SaveToFile('C:\uploads', vArq.FileName); // só o nome é usado: não sai da pasta
AResponse.Answer(HTTP_OK, '{"ok":true}');
end;| Quero responder | Como |
|---|---|
| JSON |
AResponse.Answer(HTTP_OK, '{"id":7}') (JSON é o tipo padrão) |
| texto | AResponse.Answer(HTTP_OK, 'pong', rctTEXTPLAIN) |
| HTML | AResponse.Answer(HTTP_OK, '<h1>Oi</h1>', rctTEXTHTML) |
| só o status | AResponse.Answer(HTTP_NoContent) |
| um arquivo do disco |
AResponse.Answer('C:\relatorios\mes.pdf') (abre no navegador; False no 2º parâmetro baixa) |
| um stream que você criou |
AResponse.Answer(HTTP_OK, vStream, 'application/pdf'): o RAL copia, você libera o seu |
| um stream, sem cópia |
AResponse.Answer(HTTP_OK, vStream, 'application/pdf', True): o RAL fica com ele e libera (1.3 🚧) |
| um cabeçalho a mais | AResponse.AddHeader('X-Total', '42') |
| um cookie | ver abaixo |
Status mais usados (constantes de RALConsts):
| Constante | Número | Quando |
|---|---|---|
HTTP_OK |
200 | deu certo |
HTTP_Created |
201 | criou um registro |
HTTP_NoContent |
204 | deu certo, nada para devolver |
HTTP_BadRequest |
400 | o pedido veio errado |
HTTP_Unauthorized |
401 | falta login |
HTTP_Forbidden |
403 | logado, mas sem permissão |
HTTP_NotFound |
404 | não existe |
HTTP_InternalError |
500 | erro no servidor |
var
vCookie: TRALCookie;
begin
FillChar(vCookie, SizeOf(vCookie), 0); // no Delphi novo: vCookie := Default(TRALCookie)
vCookie.Name := 'tema';
vCookie.Value := 'escuro';
vCookie.Path := '/';
vCookie.MaxAge := 3600; // segundos
vCookie.HttpOnly := True; // o JavaScript da página não lê
AResponse.AddCookie(vCookie);
end;Uma exceção não tratada vira 500 com o texto da exceção, e dispara o evento
OnServerError do servidor (bom lugar para gravar log). Para não mostrar o texto
ao cliente (que pode ter nome de tabela e SQL), ligue HideErrorDetails no
servidor (1.2 🚧). Ver Segurança.
Prefira responder o erro você mesmo, com o status certo:
if vCliente = nil then
begin
AResponse.Answer(HTTP_NotFound, '{"erro":"cliente não encontrado"}');
Exit;
end;Use a biblioteca de JSON que já conhece (System.JSON no Delphi, fpjson no
Lazarus) e responda o texto. Para um dataset inteiro, o RAL tem ToJSON/
DataSetToJSON (unit RALStorageJSON).
| O que acontece | Causa | O que fazer |
|---|---|---|
| Access violation ao ler um parâmetro |
ParamByName devolveu nil
|
teste antes, ou use GetQuery/GetField/GetHeader
|
acentos chegam trocados (ç) |
o cliente mandou sem UTF-8 | envie com charset=utf-8; o RAL responde texto em UTF-8 |
| o corpo vem vazio num GET | GET não costuma levar corpo | use POST, ou parâmetros na URL |
o campo do formulário não aparece em RequestText
|
formulário vira campos, não corpo | GetField('nome') |
| o JSON do corpo não vira parâmetros | é assim por padrão | leia RequestText; ou ligue JSONBodyToParams no servidor (1.2 🚧), que na 1.3 🚧 virou o TRALJSONBodyPlugin (Plugins) |
As propriedades que valem para todo motor (cada motor acrescenta as suas):
| Propriedade | Padrão | O que faz |
|---|---|---|
Active |
desligado | liga e desliga. Gravado ligado num form, só liga depois de lidas as outras propriedades |
Port |
8000 | porta |
IPConfig |
todos os IPv4 |
IPv4Bind, IPv6Bind, IPv6Enabled: em que endereços ouvir |
Routes |
as rotas (Rotas e parâmetros) | |
Authentication |
vazio | login (Autenticação) |
ShowServerStatus |
ligado | responde / com o texto de ServerStatus quando nenhuma rota responde |
ResponsePages |
a página HTML de cada status de erro | |
CookieLife |
30 | minutos que um cookie enviado pelo servidor dura no navegador |
HideErrorDetails |
desligado (1.2 🚧) |
o 500 diz só Internal Server Error
|
RaiseError |
desligado | sem OnServerError, deixa a exceção da rota subir |
SessionTimeout |
30000 | ms que uma conexão keep-alive parada fica aberta (mORMot2, fpHTTP). Não é a sessão do WebModule |
| Evento | Quando |
|---|---|
OnRequest |
todo pedido, depois de achar a rota e antes dos plugins |
OnResponse |
todo pedido já respondido, antes de a resposta sair |
OnServerError |
uma exceção que o servidor pegou |
OnClientBlock |
um plugin bloqueou um endereço (Segurança) |
- Rotas e parâmetros
-
Corpo sem cópias: corpos grandes, streams (avançado,
1.3 🚧)
Começar
Servidor
- Rotas e parâmetros
- Ler o pedido e responder
- Plugins 🚧
- Autenticação
- Banco de dados (DBWare)
- Servir site e arquivos
- Swagger e Postman
- HTTPS
- Criptografia ponto a ponto
- Segurança para produção
- Colocar no ar
- Desempenho
Cliente
Motores
Avançado
Ajuda
- Problemas comuns
- Atualizar o Indy
- Várias versões do Delphi
- Vídeos e guias
- Módulos de terceiros
- Licenças
- Contribuir
- Roadmap e changelog
🚧 = em desenvolvimento, pode mudar