Skip to content

context: handle IPv6 addresses in getHost() and getPort() - #4030

Merged
jknack merged 1 commit into
jooby-project:mainfrom
wleeaf:host-ipv6-literal
Oct 26, 2026
Merged

jknack merged 1 commit into
jooby-project:mainfrom
wleeaf:host-ipv6-literal

Conversation

@wleeaf

@wleeaf wleeaf commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

DefaultContext.getHost() and getPort() split the host-and-port value at its first :. With an IPv6 address in the Host header (a browser sends Host: [::1]:8080 for http://[::1]:8080/), that gives:

Host getHost() getPort() getRequestURL()
[::1]:8080 [ NumberFormatException NumberFormatException
[2001:db8::1] 2001 NumberFormatException NumberFormatException
[::1] ::1 80 http://::1/path

so a handler that calls getPort() or getRequestURL() responds with 400 on every server.

The port of an IPv6 address is now taken after the closing bracket, and an address without brackets (getHostAndPort() returns [::1] as ::1) has no port. getHost() returns the address in brackets, as it appears in the Host header and as ProxyPeerAddress already sets it for X-Forwarded-Host. With that, getRequestURL() builds http://[::1]:8080/path. getHostAndPort() and the results for host names and IPv4 addresses don't change.

Tests: DefaultContextTest has new cases for [2001:db8::1]:8080, for [2001:db8::1] with the default port, for getRequestURL() with [::1]:8080, and an extra getHost() assertion in hostAndPortIPv6. All four fail without the change. mvn test passes in the jooby module (1310 tests), and google-java-format reports nothing on the changed lines.

getHost() and getPort() split the Host header at its first colon, so
an IPv6 literal such as [::1]:8080 or [2001:db8::1] gave the host "["
or "2001" and made getPort(), and with it getRequestURL(), throw a
NumberFormatException (400). The port of an IPv6 address now comes
after the closing bracket, and getHost() returns the address in
brackets, as in the Host header.
@jknack jknack added this to the 4.5.5 milestone Oct 26, 2026
@codecov

codecov Bot commented Oct 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.33333% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.19%. Comparing base (3a1ee0b) to head (d55d4e7).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
jooby/src/main/java/io/jooby/DefaultContext.java 83.33% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #4030      +/-   ##
============================================
+ Coverage     94.17%   94.19%   +0.01%     
- Complexity     6667     6674       +7     
============================================
  Files           432      432              
  Lines         20914    20923       +9     
  Branches       2102     2106       +4     
============================================
+ Hits          19696    19708      +12     
+ Misses          764      760       -4     
- Partials        454      455       +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jknack
jknack merged commit 94d2244 into jooby-project:main Oct 26, 2026
5 of 6 checks passed
jknack added a commit that referenced this pull request Oct 26, 2026
fixes #4030

- handle `::1` or `::` IPv6
- add more tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants