Tomcat version: 9.0.37
Operating system: windows 11 
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. 
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) 
headers=@MimeHeaderField[][
            @MimeHeaderField[
                
nameB=@MessageBytes[isdisplaypage],
                
valueB=@MessageBytes[true],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[tenantid],
                valueB=@MessageBytes[],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[accept],
                
valueB=@MessageBytes[application/json, text/plain, */*],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[unity-access-token],
                
valueB=@MessageBytes[f7e20127-1b55-4e1e-a0e2-d15b2caa112e],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[devicetype],
                valueB=@MessageBytes[],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[user-agent],
                
valueB=@MessageBytes[HolliView],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[accept],
                
valueB=@MessageBytes[application/json, text/plain, */*],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[content-type],
                
valueB=@MessageBytes[application/json],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[token],
                
valueB=@MessageBytes[f7e20127-1b55-4e1e-a0e2-d15b2caa112e],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[projectid],
                valueB=@MessageBytes[],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[referer],
                
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],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[accept-encoding],
                
valueB=@MessageBytes[gzip, deflate],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[accept-language],
                
valueB=@MessageBytes[zh-CN],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[forwarded],
                
valueB=@MessageBytes[proto=http;host="12.52.41.10:8080";for="12.52.41.20:56611"],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[host],
                
valueB=@MessageBytes[127.0.0.1:8001],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[x-forwarded-proto],
                
valueB=@MessageBytes[http],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[x-forwarded-prefix],
                
valueB=@MessageBytes[/hv-data],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[x-forwarded-port],
                
valueB=@MessageBytes[8080],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[x-forwarded-host],
                
valueB=@MessageBytes[12.52.41.10:8080],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[host],
                
valueB=@MessageBytes[127.0.0.1:8001],
            ],
            @MimeHeaderField[
                
nameB=@MessageBytes[content-length],
                valueB=@MessageBytes[0],
            ]
        ],




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. 
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. 


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? 






Thank you!


扛起一片天!✨
[email protected]

Reply via email to