Ola pessoALL,

Estamos implantando o Azure Front Door em um cliente junto do WAF o que até então seria uma tarefa normal acabou se desdobrando em uma longa sessão de troubleshooting comigo quase perdendo as esperanças por um simples detalhe.

Para o Azure Front Door a diretiva Cache-Control: no-cache significa cache.

Para termos um pouco mais de contexto, estamos falando de uma aplicação legada escrita há +/- 20 anos, e roda bem até hoje. Ela está em fase de atualização, mas boa parte do sistema ainda roda no legado e por ser escrita em ASP Clássico temos uma hard rule que as requisições uma vez estabelecidas precisam ficar sempre no mesmo servidor, o que é tarefa simples para qualquer load balancer.

Gravei até um vídeo para explicar em mais detalhes o problema e a solução caso voce prefira uma explicação mais detalhada.

Uma nota, para mim mesmo, tudo isso teria sido facilmente resolvido se ao invés de confiar na experiência eu tivesse lido a documentação com mais cuidado!

Como falei anteriormente, a aplicação necessita de um cookie para manter a afinidade da sessão, garantindo que uma vez que minha requisição seja respondida por um servidor, todas as próximas requisições ficarão sempre no mesmo servidor.

No Azure Front Door isso é definido pela propriedade "Session Affinity" nos grupos de Origem.

Como podemos observar na imagem anterior, a propriedade está corretamente configurada, mas, na prática, a configuração não estava sendo respeitada.

Após bater um pouco a cabeça entre habilitar e desabilitar algumas configurações, recorri à documentação que é clara em dizer que os cookies precisam estar presentes para que a configuração funcione e para minha surpresa em alguns casos eu via o cookie presente e em outros não.

To protect against this, session affinity will not be established if the origin sends a cacheable response when this is attempted. If the session has already been established, it does not matter if the response from the origin is cacheable.
Traffic routing methods to origin - Azure Front Door
This article explains the four different traffic routing methods used by Azure Front Door to origin.

Ok, aqui eu pensei deixa eu validar se a requisição está retornando algum header Cache-Control e após validar estava sendo retornado "Cache-Control: no-cache". Esse ponto em particular que me quebrou, a princípio você imagina que a instrução seja justamente para a requisição não ser "cacheada". O que na minha cabeça se encaixa nessa parte da documentação:

Session affinity will be established in the following circumstances beyond the standard non-cacheable scenarios.

Depois de muito quebrar a cabeça achei um artigo que relatava um problema parecido

When No Cache means Cache - Fun with Azure Front Door :: Doodle Blog & Development Diary :: Doodle Graphics

No artigo, o autor pontua que a especificação HTTP define que a diretiva no-cache não deve ser usada para cache, mas sim como indicativo que uma revalidação deve ser feita.

The "no-cache" response directive indicates that the response MUST NOT be used to satisfy a subsequent request without successful validation on the origin server
RFC 7234: Hypertext Transfer Protocol (HTTP/1.1): Caching
The Hypertext Transfer Protocol (HTTP) is a stateless \%application- level protocol for distributed, collaborative, hypertext information systems. This document defines HTTP caches and the associated header fields that control cache behavior or indicate cacheable response messages.
no-cache The response may be stored by any cache, even if the response is normally non-cacheable. However, the stored response MUST always go through validation with the origin server first before using it.
Cache-Control - HTTP | MDN
The Cache-Control HTTP header field holds directives (instructions) — in both requests and responses — that control caching in browsers and shared caches (e.g. Proxies, CDNs).

Após entendido e voltando na documentação do Front Door, trocamos a diretiva de cache de "no-cache" para no-store e tudo funcionou como esperado.

app.MapGet("/ping", () => Environment.MachineName);

app.MapGet("/no-cache", (HttpContext context) =>
{
    context.Response.Headers.CacheControl = "no-cache";
    return Environment.MachineName;
});

app.MapGet("/no-store", (HttpContext context) =>
{
    context.Response.Headers.CacheControl = "no-store";
    return Environment.MachineName;
});

Pronto, com o cabeçalho correto, as configurações de sessão são respeitadas e o sistema funciona como esperado.

Espero que vocês tenham gostado desse relato e deixem nos comentários se vocês já se depararam com situações parecidas lidando com aplicações legadas.

💡
Podemos te ajudar com uma revisão 100% gratuita do seu ambiente cloud.
Share this post