Fábio, boa noite.
Para entender o problema, primeiro precisamos falar sobre Etags.
Existem dois tipos de Etags, Strong Etag e Weak Etag.
Strong ETag:
Essa é a tag gerada por padrão (e está sendo implementada hoje no projeto do curso) e, nela, qualquer mínima alteração no recurso que está sendo enviado, ou seja, qualquer alteração que troque os bytes do recurso devolvido será considerado como se houvesse uma mudança no recurso.
Weak ETag:
Diferente da Strong Etag, nela, não necessariamente o fato dos bytes do recurso terem sido alterados significa que o recurso foi modificado. Nesse caso, quem decide se o recurso foi modificado é quem está implementando a devolução do recurso, pois, segundo a própria documentação da IETF, a mudança é semântica em relação ao negócio, logo, o que diz respeito ao negócio deve ser decidido por quem implementa, deixando de ser uma comparação byte-por-byte.
https://datatracker.ietf.org/doc/html/rfc2616#section-13.3.3
Fizemos algo semelhante no método buscar() no endpoint formas-pagamento/{formaPagamentoId}, onde nele, só geramos o etag caso as datas de atualização sejam diferentes.
Usando Weak Etag, devemos decidir, em relação ao negócio, como e quando uma ETag será considerada stale e um novo valor deverá ser devolvido.
Agora, já sabendo do que se tratam os dois tipos de ETag, o problema que estamos enfrentando acontece em versões iguais ou posteriores à 2.2.3.RELEASE (versão da aula, sem atualização é 2.2.2.RELEASE).
Na versão 2.2.3.RELEASE, o Tomcat embutido no spring-boot-starter-tomcat é o 9.0.30, invés de 9.0.29 da versão 2.2.2.RELEASE. Nessa nova versão, os recursos não são mais comprimidos quando usados em conjunto com Strong Etag. Muitas vezes pode não ser percebido isso, pois, não é lançado nenhum WARNING ou ERROR alertando que os recursos não estão sendo comprimidos, só pode ser notado caso façamos especificamente o teste de tamanho de retorno da resposta.
Esse é um problema muito comum que muitas implementações de servidores sofrem, esse não é um problema exclusivamente relacionado ao Spring e ao Tomcat, inclusive, o uso mais comum de Weak Etags acaba sendo justamente por sua imcompatibilidade com a compressão da resposta da requisição com GZip.
Temos dois caminhos a seguir. Podemos tornar nossa ETag em Weak, porém, em todos lugares onde temos essa implementação precisaríamos controlar quando uma ETag será conseiderada stale, ou, podemos utilizar uma biblioteca de terceiro que faça essa compressão para nós, mesmo utilizando a Strong Etag, porém, temos a desvantagem de que a compressão não é tão grande como a nativa do Spring, justamente por ele contornar algumas incompatibilidades e acabar mantendo alguns atributos para que seja possível controlar se o recurso mudou ou não, sem contar, é claro, o fato de estarmos adicionando uma biblioteca de terceiro que, embora, para esse caso, seja de uma grande empresa (GitHub), ainda assim não deixa de ser uma dependência não gerenciada juntamente aos starters do Spring.
Caso queira seguir pela primeira opção, basta apenas no Bean do shallowEtagHeaderFilter dizer que o mesmo será escrito em formato Weak (lembrando que será necessário tratar os casos em que o ETag está sendo usado para gerenciar sua validade):
@Bean
public Filter shallowEtagHeaderFilter() {
ShallowEtagHeaderFilter shallowEtagHeaderFilter = new ShallowEtagHeaderFilter();
shallowEtagHeaderFilter.setWriteWeakETag(true);
return shallowEtagHeaderFilter;
}
Para usar a segunda opção encontrada, devemos adicionar a seguinte biblioteca no pom.xml:
Estamos excluindo dela o uso transiente das bibliotecas de logging e do javax.servlet, pois, não usaremos tais dependências em nosso projeto e, assim, evitaremos possíveis conflitos.
Além de colocar tal dependência, devemos agora criar um novo Bean na classe WebConfig:
@Bean
public Filter compressingFilter() {
return new CompressingFilter();
}
Com isso, já podemos realizar as chamadas e verificar os resultados via Wireshark.
Como dito anteriormente, usando a compressão nativa do Spring podemos ver que reduzimos cerca de 78% do tamanho (de 3458 bytes para 766 bytes) enquanto que usando a biblioteca de terceiro, cerca de 66% (de 3458 bytes para 1182 bytes).
Para fins didáticos, recomendo que não utilize a compressão, uma vez que você já entendeu como usá-la e, dessa forma, não precisará tratar todas as respostas com ETag e também não precisará gerenciar uma dependência de terceiro para tal.
Outras referências:
https://www.rfc-editor.org/rfc/rfc7232#section-2.1
https://stackoverflow.com/questions/56663203/etag-weak-vs-strong-example
Espero tê-lo ajudado, abraço e bons estudos.
Fábio Ferreira
Olá Alisson,
Obrigado pela excelente explicação sobre o problema. Fiz as alterações conforme você sugeriu e o cabeçalho de resposta passou a retornar com a resposta.
Agora, consigo visualizar os tamanhos da resposta comprimida e descomprimida usando o Wireshark também.
Vou remover o código da compressão para dar sequência as próximas aulas, mas foi legal ter aprendido um pouco mais sobre esse tópico.
Abraço.