Skip to content

Fixes #13098 - HTTP2 Server Error Handling is different than HTTP1 #13141

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jun 2, 2025

Conversation

sbordet
Copy link
Contributor

@sbordet sbordet commented May 16, 2025

Errors happening before the request is handled are now handled similarly to HTTP/1.1, and are now hitting the ErrorHandler, so that a 400 response can be generated.

joakime and others added 5 commits May 6, 2025 09:03
TODO:
* Restore use of HttpURI.build() in HttpSenderOverHTTP2.
* Use HttpURI.Unsafe to write a test case.
* HttpURI.Unsafe javadocs.

Signed-off-by: Simone Bordet <[email protected]>
Signed-off-by: Simone Bordet <[email protected]>
Signed-off-by: Simone Bordet <[email protected]>
Signed-off-by: Simone Bordet <[email protected]>
@sbordet sbordet linked an issue May 17, 2025 that may be closed by this pull request
@sbordet sbordet marked this pull request as ready for review May 17, 2025 17:39
@sbordet sbordet requested review from gregw and joakime May 17, 2025 17:39
@sbordet sbordet changed the title Fix/12.0.x/http2 badmessage errorhandler Fixes #13098 - HTTP2 Server Error Handling is different than HTTP1 May 17, 2025
@sbordet sbordet moved this to 👀 In review in Jetty 12.0.22 - FROZEN May 17, 2025
@sbordet sbordet self-assigned this May 17, 2025
@gregw
Copy link
Contributor

gregw commented May 18, 2025

@lorban will h3 need similar changes?

Copy link
Contributor

@gregw gregw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI is badly broken as well.

@@ -135,4 +139,68 @@ public MetaData parse(ByteBuffer buffer, int blockLength)
}
}
}

public static class SessionFailureMetaData extends MetaData
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

javadoc

}
}

public interface StreamFailureMetaData
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

javadoc

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is both a session and stream failure needed? Can't a session failure be detected by the fact that it has a failed stream?

Or perhaps it could just be a FailureMetaData with reason in the getFailure?

@lorban
Copy link
Contributor

lorban commented May 20, 2025

@gregw yes, H3 probably suffers from the same problem.

@sbordet
Copy link
Contributor Author

sbordet commented May 20, 2025

@gregw @lorban I have implemented also for HTTP/3.

@sbordet sbordet requested review from gregw and lorban May 20, 2025 12:03
Signed-off-by: Simone Bordet <[email protected]>
@sbordet sbordet requested a review from lorban May 20, 2025 14:01
* Fixed HTTP2Stream.reset() logic.

Signed-off-by: Simone Bordet <[email protected]>
@@ -506,6 +507,27 @@ public String toString()
}
}

/**
* <p>An unsafe {@link HttpURI} that accepts URI parts without checking whether they are valid.</p>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* <p>An unsafe {@link HttpURI} that accepts URI parts without checking whether they are valid.</p>
* <p>An unsafe {@link HttpURI} that accepts URI parts without checking whether they are valid.
* Primarily intended for testing, as un-validated may break arbitrary code.</p>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also used by Jetty HttpClient to allow it to make requests that other servers would allow, but we don't.

An example would be using the %00 in the request path.
In jetty-12.0.x HEAD our HttpURI and MetaData classes both reject that pct-encoding, but it's 100% allowed to be sent from a user-agent.

.scheme(_scheme)
.host(_authority == null ? null : _authority.getHost())
.port(_authority == null ? -1 : _authority.getPort())
.pathQuery(_path);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need?

Suggested change
.pathQuery(_path);
.pathQuery(_path)
.asImmutable();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It creates another object in the hot path, and the return type is already just HttpURI, not its Mutable subclass.

private final boolean request;
private final boolean response;

public StreamException(boolean request, boolean response, String messageFormat, Object... args)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these exceptions taking format + args instead of a pre-formatted string?

.path(path)
.query(request.getQuery());
// URI validations already performed by using the java.net.URI class.
HttpURI uri = new HttpURI.Unsafe(request.getScheme(), request.getHost(), request.getPort(), path, request.getQuery(), null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A side-effect of this change makes the HttpURI immutable.

I wonder if the MetaData.Request constructors shouldn't always call immutable() on the HttpURI parameter they are given?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be another allocation in the hot path, and the signature returns the immutable HttpURI type.

.scheme(_scheme)
.host(_authority == null ? null : _authority.getHost())
.port(_authority == null ? -1 : _authority.getPort())
.pathQuery(_path);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

immutable()?

Signed-off-by: Simone Bordet <[email protected]>
@sbordet sbordet requested review from gregw and lorban May 29, 2025 10:29
@joakime joakime added the Sponsored This issue affects a user with a commercial support agreement label May 29, 2025
Copy link
Contributor

@lorban lorban left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is still the oddity of StreamException and HpackException taking format + args, otherwise LGTM.

@joakime
Copy link
Contributor

joakime commented May 30, 2025

Can this be merged ?

@sbordet sbordet merged commit 0b3adca into jetty-12.0.x Jun 2, 2025
10 checks passed
@github-project-automation github-project-automation bot moved this from 👀 In review to ✅ Done in Jetty 12.0.22 - FROZEN Jun 2, 2025
@sbordet sbordet deleted the fix/12.0.x/http2-badmessage-errorhandler branch June 2, 2025 13:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
build-all-tests Sponsored This issue affects a user with a commercial support agreement
Projects
Status: ✅ Done
Development

Successfully merging this pull request may close these issues.

HTTP2 Server Error Handling is different than HTTP1
4 participants