Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nova funcionalidade ETagMatch #382

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

antoniojmsjr
Copy link
Contributor

@antoniojmsjr antoniojmsjr commented Mar 27, 2024

Motivação

A criação dessa funcionalidade é decorrente do uso do middleware Horse-ETag no qual só da suporte ao tipo JSON, e não permitindo usar outros tipos, como XML, arquivos PDF, imagens e etc.

Objetivo

A função ETagMatch tem como objetivo retornar no header o valor para o campo ETag e testar numa futura requisição se o conteúdo da resposta é o mesmo que está no cliente, comparando o campo if-None-Match com o campo ETag.

Se ETagMatch for verdadeiro a resposta pode ser ignora, assim evitando trafegar dados iguais, pois o conteúdo que está no cliente é igual ao conteúdo da resposta.

Por exemplo:

THorse.Get('ping',
    procedure(Req: THorseRequest; Res: THorseResponse)
    begin
      
      if Res.ETagMatch('Pong') then
        Exit;

      Res.Send('pong');
    end);

image

Validação

Verificação de Hint: ✅
Verificação de Warning: ✅
Compilação Delphi: ✅
Compilação Lazarus: ✅

@viniciussanchez
Copy link
Member

@antoniojmsjr o ideal não seria o ETagMatch estar na requisição, já que é ela que recebe o Header If-None-Match?
Uma outra curiosidade também, não seria interessante esse recurso estar dentro do middleware de Etag? Ou então criar um mais completo com suporte a XML, etc...

@antoniojmsjr
Copy link
Contributor Author

antoniojmsjr commented Mar 28, 2024

Blz @viniciussanchez, tudo certo?

  • Sobre o ETagMatch no request não faz sentido, por quê?

1º É informado o hash do campo ETag do header do response;

FWebResponse.SetCustomHeader('ETag', lETagContent);

2º Quando o hash do body que vai ser enviado for igual ao hash do If-None-Match recebido, internamente é enviado um response com statuscode 304 sem a necessidade de intervenção do desenvolvedor, é tudo feito internamente pela função;

if (lETagRequest = lETagContent) then
  begin
    Result := True;
    FWebResponse.ContentType := '';
    FWebResponse.Content := '';
    {$IF DEFINED(FPC)}
    FWebResponse.Code := THTTPStatus.NotModified.Tointeger; //304
    FWebResponse.SendContent;
    {$ELSE}
    FWebResponse.StatusCode := THTTPStatus.NotModified.ToInteger; //304
    FWebResponse.SendResponse;
    {$ENDIF}
  end;

3º Como tudo que é tratado pela função ETagMatch é referente a uma responsta, achei necessário que fosse implmentado no response.

  • Sobre modificar o middleware de Etag:

Tudo começou quando fui usar middleware Etag com XML e o mesmo não funcionou, tudo bem, fiz uma modificação para aceitar qualquer tipo, blz, mas quando fui usar a função Res.SendFile o middleware Etag não funcionou tb, pois a função SendFile fica responsável por gerar e enviar um response, e quando chega no middleware Etag o arquivo já foi enviado e a validação(comparação) não faz mais sentido, pois deveria acontecer antes do envio, por isso eu criei essa funcionalidade.

Por Exemplo:

THorse.Get('relatorio',
  procedure(Req: THorseRequest; Res: THorseResponse)
  var
    lRelatorio: TStream;
  begin
  
    if Res.ETagMatch(lRelatorio) then
      Exit;

    Res.SendFile(lRelatorio);
    
  end);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants