2024-04-29 10:48:50
Il existe 3 services Spring Boot (client, proxy, API) – Le client appelle l’API et la demande est envoyée vers/retour via le proxy, environ 1% des réponses sont corrompues et le client ne peut pas la lire – lançant java.io.IOException : illégal caractère en taille de bloc : 123.
Cela signifie que la réponse est fragmentée et que chaque fragment a une taille. Étant donné que la représentation hexadécimale du caractère “{” est “123”, cela signifie que dans la réponse, la valeur de la taille du morceau est manquante et que les données commencent par “{” qui est le début de l’objet JSON. Le client reçoit l’en-tête « Transfer-Encoding » : chunked – qui est une instruction pour lire la réponse par morceaux, mais comme la taille du morceau/taille de la partition est manquante, le client ne peut pas lire la réponse et lève une exception.
En regardant les en-têtes de réponse de l’API, qui vient du proxy, je peux y voir l’en-tête en double « Transfer-Encoding ». Il a été constaté que l’API elle-même ajoutait à l’origine un tel en-tête UNE FOIS, ce qui est un comportement normal lorsque la réponse est dynamique (à partir de la base de données). Spring/Tomcat ne connaît pas la longueur du contenu et fragmente la réponse. Mais aussi lorsque la réponse passe par le proxy, le proxy ajoute un en-tête « Transfer-Encoding » supplémentaire. Recherche dans le code proxy – il convertit les en-têtes reçus de l’API et les transmet (tous les en-têtes sont uniques, pas de duplication). Mais le proxy interne Tomcat ajoute en plus l’en-tête « Transfer-Encoding » à la réponse. Cela ressemble à un bug de Tomcat. La mise à niveau de la version Spring Boot/Tomcat vers la dernière version n’a pas aidé.
Ce problème ne peut être reproduit que pendant le chargement – par exemple, 300 requêtes donneront environ 3 à 4 erreurs. La suppression manuelle de l’en-tête « Transfer-Encoding » (Content-Length sera ajoutée automatiquement) côté API résout le problème, mais cela ne semble pas être la bonne solution.
Veuillez partager votre expérience/suggérer une solution.
Le proxy dispose d’une méthode à l’intérieur de laquelle il décide où transmettre la demande. Il utilise OkHttpClient pour cela. Voici un morceau de code qui gère les requêtes et convertit les en-têtes reçus. (okttp3Headers.names() – est SET, donc la duplication n’est pas possible)
… renvoie un nouveau ResponseEntity<>( ResponseBodyString, convertHeaders(forwarderRequestResponse.headers()), Objects.requireNonNull(HttpStatus.resolve(forwarderRequestResponse.code()))); } public HttpHeaders convertHeaders(En-têtes okttp3Headers) { var en-têtes = new HttpHeaders(); for (String headerName : okttp3Headers.names()) { for (String headerValue : okttp3Headers.values(headerName)) { headers.add(headerName, headerValue); } } renvoie les en-têtes ; }
#spring #boot #Lentête #TransferEncoding #double #dans #réponse #provoque #une #exception #client #java.io.IOException #caractère #illégal #dans #taille #bloc
1714388949