Repository navigation
HDDS-16683. Upgrade Jetty from 12.0.38 to 12.1.14 - #11424
Merged
Merged
Conversation
Contributor
Author
|
@adoroszlai @jojochuang Please take a look |
adoroszlai
approved these changes
Oct 7, 2026
Contributor
|
Thanks @yandrey321 for the patch. Please write shorter PR summaries, output from Claude seems to be overly verbose. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changes were proposed in this pull request?
This upgrades Jetty from
12.0.38to12.1.14, moving Ozone onto the Jetty 12.1 line.Ozone stays on the EE8 environment:
servlet-api.versionremains4.0.9and no module migrates toEE10 or EE11. Jetty publishes EE8 artifacts for every
12.1.xrelease, so there is no version floor toclear. The property
12.0.38occurred exactly once in the repository, so the upgrade itself is aone-line change to the root
pom.xml. The three remaining changes are fallout the upgrade produces,each described below.
1. Dist license files — Jetty 12.1 splits the
jetty-eemoduleJetty 12.1 splits
jetty-ee, so the jar set undershare/ozone/libchanges even though Ozone declaresno new dependency:
org.eclipse.jetty:jetty-eeorg.eclipse.jetty:jetty-annotationsorg.eclipse.jetty.ee:jetty-ee-webappjetty-ee-webappcarries a new groupId,org.eclipse.jetty.ee, which did not exist in12.0.38.Neither BOM that Ozone imports manages it —
jetty-ee8-bomcontains noorg.eclipse.jetty.eeentry atall. It arrives transitively because
jetty-ee8-webappdeclares it without a version, so it followsjetty.versionthrough the pinnedjetty-ee8-webapppom. It resolves to a single version,12.1.14,with no conflict.
Two license files therefore need updating, which is what
dependency.shexists to force:hadoop-ozone/dist/src/main/license/jar-report.txt— one entry becomes two.hadoop-ozone/dist/src/main/license/bin/LICENSE.txt—jetty-eebecomesjetty-annotations, andorg.eclipse.jetty.ee:jetty-ee-webappis inserted between theorg.eclipse.jettyandorg.eclipse.jetty.ee8blocks, following that file's existing ordering by groupId segment ratherthan byte order.
Both new artifacts are
Apache-2.0/EPL-2.0, solicense.shstays clean and no new license categoryis introduced.
A caution for anyone re-checking this: a
dependency:tree -Dincludes=...filter built from the oldcoordinates is structurally blind to a groupId the upgrade introduces. Enumerating the jars the build
actually ships (
find <dist> -name '*.jar') and diffing that is what surfaced it.2.
UriCompliance.Violation.FRAGMENT— the one behavior change that reaches OzoneThe
UriComplianceAPI delta is otherwise purely additive (Violation.FRAGMENTandUriCompliance.DEFAULT_REDIRECT), andUriCompliance.DEFAULT.getAllowed()is empty in both versions.The one measured behavior change is an improvement:
/bucket/my#keymy/bucket/my%23keymy#keymy#key/bucket//keyBefore
FRAGMENTexisted, Jetty split such a target and handed the servlet only the part before the#, so an S3 request for the keymy#keysilently operated onmyinstead. Rejecting the malformedtarget is the safer behavior, so Ozone's relaxed compliance modes deliberately do not allow
FRAGMENT; relaxing it was tried and reproduces the truncation.TestHttpServer2gains a test pinningthis, with a raw-socket helper because
java.net.URLtreats#as a client-side fragment and neverputs it on the wire.
Six other 12.1 default flips were checked and cannot affect Ozone:
maxResponseHeaderSize,relativeRedirectAllowed,renegotiationAllowed,flushOnResponseCommit,setCompactPathandForwardedRequestCustomizerhave zero references repository-wide. Ozone's entire Jetty surface isUriCompliance,SecureRequestCustomizerandee8.nested.SessionHandler. A query-string complianceconcern was also checked and found not to exist —
%FF,%ZZand a truncateda%2are accepted byboth versions.
3.
ProxyServer— Jetty 12.1's proxy rewrites quoted response headersOn the upgrade,
TestS3SDKfails exactly one assertion:StandardObjectHeaderTests.testObjectWriteContentLanguageAndDispositionexpectsattachment; filename="test.txt"and receivesattachment;filename=test.txt. An A/B on the singlejetty.versionproperty, same tree and same command, confirms causation —12.0.38gives 232/232,12.1.14gives 232 run with 1 failure.The S3 Gateway is not involved. The endpoint those tests talk to is not a gateway:
OzoneS3SDKTestsbuilds its cluster with
MultiS3GatewayService(5), which hides the five gateways behind the test-onlyProxyServer, anorg.eclipse.jetty.ee8.proxy.ProxyServlet. The gateway's own response is verbatim on12.1.14, measured at three layers — the valueObjectEndpointreads back from key metadata and thevalue it writes out, the value Jersey hands
addHeader, and the container's ownHttpFieldsafter thefilter chain returns. A standalone
HttpServer2plus servlet is verbatim too, on both GET and HEAD.Only the hop through the proxy rewrites the value:
12.0.38attachment; filename="test.txt"attachment; filename="test.txt"12.1.14attachment; filename="test.txt"attachment;filename=test.txtThe mechanism is in
AbstractProxyServlet.onServerResponseHeaders.12.0.38copies each header withfield.getValue().12.1.14adds afilterServerResponseHeader(.., HttpField)overload and forwardsfield.getValueList()joined with",".HttpField.getValueList()is a QuotedCSV parse, which dropsoptional whitespace and quoting while keeping
;param=value— exactly the observed transformation. Itis lossy for any non-CSV header carrying a quoted-string, so
Content-Disposition,WWW-AuthenticateandLinkare all affected. This appears to be an upstream Jetty defect and isworth reporting there separately.
The change here is scoped to the harness:
ProxyServer.ProxyHandleroverridesonServerResponseHeadersto copy withfield.getValue(), restoring the12.0.38copy so the proxystops rewriting values the S3 Gateway already returns correctly. This keeps the assertion meaningful
rather than relaxing it.
Scope
Included: the version upgrade, the dist license fallout it causes, a test pinning the
FRAGMENTbehavior, and the harness fix needed to keep
TestS3SDKhonest.Out of scope, each its own Jira: migrating off EE8 to EE10 or EE11, and adopting any new 12.1 feature
(
CompressionHandler, the new deployer,MultiAuthenticator).Generated-by: Claude Code (claude-opus)
What is the link to the Apache JIRA
https://issues.apache.org/jira/browse/HDDS-16683
How was this patch tested?
CI: https://github.com/yandrey321/ozone/actions/runs/37517034864
Existing suites plus one new unit test; no new test class or cluster lifecycle was introduced.
mvn clean installfrom a clean~/.m2.dependency:treeacross everyorg.eclipse.jetty*groupId, including the neworg.eclipse.jetty.ee: all 29 Jetty artifacts resolve to12.1.14,jetty-servlet-apistays at4.0.9, and there are zeroee9/ee10/ee11artifacts. The only outliers are the pre-existingtest-scope
org.eclipse.jetty.websocket:websocket-{api,client,common}:9.4.57.v20241219pulled in byhadoop-yarn-client, whichjetty-bomdoes not manage and which this change does not touch.dependency:tree -Dincludes=javax.servlet:*,jakarta.servlet:*— unchanged.-Dmdep.analyze.skip, soanalyze-onlyexecutes atverify: 58 goals clean,no "Used undeclared dependencies".
hdds-server-framework,s3gatewayandhttpfs, including the newTestHttpServer2.testUnencodedFragmentRejectedRatherThanTruncatingKey.checkstyle.shandrat.sh— both clean.mvn -Pdist -DskipTests package, thendependency.shandlicense.sh: the jar-report diffdependency.shreports is applied in this PR, andlicense.shis clean.TestS3SDK— 232 run, 0 failures, 0 errors. Without theProxyServerfix the same suite is232 run with 1 failure.
ozonesuite —rc=0, zero failures.ProxyServerand reads both legs on a raw socket, run on12.0.38and12.1.14; the mechanism wasthen confirmed from
javap -cofAbstractProxyServlet.onServerResponseHeadersin both versions.Neither probe is part of this patch.
Not run locally, left to CI: the
ozonesecurecompose suite, which exercises the HTTPSSecureRequestCustomizerpath, and the httpfs compose suite.