Hi ,
Thank you for your reply. Request chain: Client → springcloud gateway(12.52.41.10:8080) → Tomcat (127.0.0.1:8001) The springcloud gateway configuration has added the X-Forwarded-* series of headers. 2. Regarding the format: The original request is a string dumped from the inputBuffer of Tomcat. There may be issues with line breaks when pasting, but in the actual request, each header is on a separate line. 3. Version Information: - Spring Boot: 2.3.2.RELEASE - Embedded Tomcat: 9.0.37 - JDK: 1.8 Regarding the upgrade: Due to the constraints of the production environment, an upgrade cannot be carried out in the short term. I would like to first confirm if this is a known issue or if there is a workaround? Supplementary phenomena: - The issue occurs sporadically and not with every request. - When the X-Forwarded-For header is missing, it is always accompanied by a repeated Host field. - It is suspected that the problem lies in the header boundary judgment during the parsing of Http11InputBuffer. Could you guide me on how to further debug or provide the relevant issue link? Thank you! 扛起一片天!✨ [email protected] 原始邮件 发件人:Christopher Schultz <[email protected]> 发件时间:2026年4月1日 21:20 收件人:users <[email protected]> 主题:Re: Tomcat 9.0.37 - Request Header Parsing Exception: X-Forwarded-For Lost and Host Field Duplicated Resulting in 400 Bad Request 扛起一片天!✨, On 4/1/26 5:33 AM, 扛起一片天!✨ wrote: > Tomcat version: 9.0.37 > Operating system: windows 11&nbsp; > JDK version: OpenJDK 1.8 > Problem Description: > During the debugging process, it was found that in the prepareRequest stage when Tomcat parses the HTTP request headers, the X-Forwarded-For field is lost, and at the same time, there are duplicate Host fields.&nbsp; > The original request stream (from inputBuffer): -------------------------------------------------- > GET /v1/webapi/server/current_time? t=1774661427160 HTTP/1.1 isdisplaypage:true > tenantid: > groupid: > unity-access-token:f7e20127-1b55-4e1e-a0e2-d15b2caa112ee > devicetype: > user-agent:HolliView > accept:application/json, text/plain, */* > content-type:application/json > token:f7e20127-1b55-4e1e-a0e2-d15b2caa112e > projectid: > Referer: http://12.52.41.10:8080/hv-visio/display.html? ... > accept-encoding:gzip, deflate > accept-language:zh-CN > forwarded:proto=http; host="12.52.41.10:8080"; for="12.52.41.20:56611" > x-forwarded-for: 12.52.41.200 x-forwarded-proto:http > x-forwarded-prefix:/hv-data > x-forwarded-port:8080 > x-forwarded-host: 12.52.41.10:8080 > host: 127.0.0.1:80011 content-length:0 > -------------------------------------------------- > > > Actual parsing result (MimeHeaders): > - X-Forwarded-For field: Missing (does not exist) > - Host field: Appears twice (repeated)&nbsp; > headers=@MimeHeaderField[][ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[isdisplaypage], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[true], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[tenantid], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[accept], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[application/json, text/plain, */*], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[unity-access-token], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[f7e20127-1b55-4e1e-a0e2-d15b2caa112e], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[devicetype], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[user-agent], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[HolliView], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[accept], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[application/json, text/plain, */*], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[content-type], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[application/json], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[token], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[f7e20127-1b55-4e1e-a0e2-d15b2caa112e], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[projectid], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[referer], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[http://12.52.41.10:8080/hv-visio/display.html?tag=displays/%E7%AC%AC%E5%9B%9B%E5%87%80%E5%8C%96%E5%8E%82%E6%B5%81%E7%A8%8B%E5%9B%BE/%E8%84%B1%E7%A1%AB%E8%84%B1%E6%B0%B4%E8%A3%85%E7%BD%AE2/%E8%84%B1%E6%B0%B4%E8%A3%85%E7%BD%AE.json], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[accept-encoding], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[gzip, deflate], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[accept-language], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[zh-CN], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[forwarded], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[proto=http;host="12.52.41.10:8080";for="12.52.41.20:56611"], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[host], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[127.0.0.1:8001], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[x-forwarded-proto], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[http], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[x-forwarded-prefix], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[/hv-data], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[x-forwarded-port], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[8080], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[x-forwarded-host], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[12.52.41.10:8080], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[host], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[127.0.0.1:8001], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @MimeHeaderField[ > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nameB=@MessageBytes[content-length], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valueB=@MessageBytes[0], > &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ] > &nbsp; &nbsp; &nbsp; &nbsp; ], > > > > > Key observations: > 1. The original request contains x-forwarded-for: 12.52.41.200. > 2. The original request has host: 127.0.0.1:8001 only once. > 3. However, after parsing, X-Forwarded-For is lost and Host becomes two.&nbsp; > 4. It doesn't occur every time. > 5.The Tomcat that is embedded within the Spring Boot > 6. Trigger badRequest("http11processor.request.multipleHosts"); > 7.There are no other additional configurations. > > > Investigations completed: > - Confirmed that the header is included in the request flow before it reaches Tomcat. > - Configured with RemoteIpValve, but the issue occurred during the parsing stage.&nbsp; What components are in the mix before the request reaches Tomcat? The formatting is a little odd in your original posting (e.g. the X-Forwarded-For and X-Forwarded-Proto headers appear to be on the same line). > 1. Is this a known parsing issue? > 2. Are there any configuration items that would affect the header parsing behavior? > 3. How can we further determine whether it is a parsing logic issue or caused by pre-processing?&nbsp; This is a really old version of Tomcat. Can you... a. Upgrade to a later version of Spring Boot b. Upgrade the Tomcat used by Spring Boot ? -chris --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
