-
Notifications
You must be signed in to change notification settings - Fork 2k
Issue #12806 - Overhaul ComplianceViolation.Listener reporting #14090
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
base: jetty-12.1.x
Are you sure you want to change the base?
Issue #12806 - Overhaul ComplianceViolation.Listener reporting #14090
Conversation
jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpQuotedCSV.java
Outdated
Show resolved
Hide resolved
jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpQuotedQualityCSV.java
Outdated
Show resolved
Hide resolved
jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpQuotedQualityCSV.java
Outdated
Show resolved
Hide resolved
jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpCompliance.java
Show resolved
Hide resolved
gregw
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking better, but still work to do.
|
|
||
| if (_violations != null && !_violations.isEmpty()) | ||
| { | ||
| CookieCompliance cookieCompliance = _parser.getCookieCompliance(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This variable is not used
| if (_violations != null && !_violations.isEmpty()) | ||
| { | ||
| CookieCompliance cookieCompliance = _parser.getCookieCompliance(); | ||
| _violations.forEach(complianceViolationListener::onComplianceViolation); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we assertNotNull on the cVL? or skip this line if it is null?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The expectation is that there will always be a cVL, even if its just ComplianceViolation.Listener.NOOP.
I added a requireNonNull to the start of the method anyway.
| parseField(field); | ||
| } | ||
|
|
||
| CookieCompliance getCookieCompliance(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
javadoc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Easier to just get rid of this method, it's no longer being used anyway.
| */ | ||
| void initialize(); | ||
|
|
||
| boolean complianceAllows(ComplianceViolation violation, String detail); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
never called?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
|
|
||
| boolean complianceAllows(ComplianceViolation violation, String detail); | ||
|
|
||
| <T extends Throwable> void complianceAssert(ComplianceViolation violation, String detail, Function<String, T> error) throws T; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
javadoc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, would this not be better as a method on HttpConfiguration? When would a channel ever have a different impl?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Each channel has a (potentially) unique set of cVL due cVL.initialize() requirement.
The HttpConfiguration approach is the wrong place for most use cases with cVL.
It only really fits (and barely at that) for pre-channel violations like from HttpParser (but even that isn't really a concern anymore with the channel based approach).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
javadoc added
| { | ||
| ComplianceViolation.Mode mode; | ||
|
|
||
| if (violation instanceof UriCompliance.Violation) | ||
| mode = getHttpConfiguration().getUriCompliance(); | ||
| else if (violation instanceof HttpCompliance.Violation) | ||
| mode = getHttpConfiguration().getHttpCompliance(); | ||
| else if (violation instanceof MultiPartCompliance.Violation) | ||
| mode = getHttpConfiguration().getMultiPartCompliance(); | ||
| else if (violation instanceof CookieCompliance.Violation) | ||
| mode = getHttpConfiguration().getRequestCookieCompliance(); | ||
| else | ||
| throw new UnsupportedOperationException("Unsupported ComplianceViolation type: " + violation.getClass().getName()); | ||
|
|
||
| boolean allowed = mode.allows(violation); | ||
|
|
||
| // Always report violation to listeners | ||
| _complianceViolationListener.onComplianceViolation(new ComplianceViolation.Event(mode, violation, detail, allowed)); | ||
|
|
||
| return allowed; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is substantially the same as the one above. Factor out the mode selection maybe to HttpConfiguration itself
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
| if (qualityCSV == null) | ||
| { | ||
| HttpConfiguration httpConfiguration = request.getConnectionMetaData().getHttpConfiguration(); | ||
| HttpChannel httpChannel = HttpChannel.from(request); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is more natural to report violations to the HttpConfiguration rather than the HttpChannel
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But that's the wrong place and doesn't take into account the cVL.initialize() / cVL.onRequestBegin() / cVL.onRequestEnd() requirements.
The HttpChannel is also the place where these events fire.
The individual violations (cVL.onComplianceViolation()) occur between these.
| */ | ||
| public void notifyViolation(ComplianceViolation violation, String details) | ||
| { | ||
| ComplianceViolation.Mode mode; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The mode selection code is duplicated again. Perhaps we should just have the following methods on HttpConfiguration:
public ComplianceViolation.Mode getComplianceViolationModeFor(ComplianceViolation violation)
{
if (violation instanceof UriCompliance.Violation)
return getUriCompliance();
else if (violation instanceof HttpCompliance.Violation)
return getHttpCompliance();
else if (violation instanceof MultiPartCompliance.Violation)
return getMultiPartCompliance();
else if (violation instanceof CookieCompliance.Violation)
return getRequestCookieCompliance();
else
throw new UnsupportedOperationException("Unsupported ComplianceViolation type: " + violation.getClass().getName());
}
public <T extends Throwable> void assertAllowed(ComplianceViolation violation, String detail, Function<String, T> error) throws T
{
ComplianceViolation.Mode mode = getComplianceViolationModeFor(violation);
boolean allowed = mode.allows(violation);
List<ComplianceViolation.Listener> listeners = getComplianceViolationListeners();
ComplianceViolation.Event event = new ComplianceViolation.Event(mode, violation, detail, allowed);
Throwable throwable = null;
for (ComplianceViolation.Listener listener : listeners)
{
try
{
listener.onComplianceViolation(event);
}
catch (Throwable t)
{
throwable = ExceptionUtil.combine(throwable, t);
}
}
ExceptionUtil.ifExceptionThrowUnchecked(throwable);
if (!allowed)
throw error.apply(violation.getDescription());
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed, no longer being used.
…806/compliance-violation-listener-cleanup
Cleanup all code paths that perform a ComplianceViolation check to do the following ...
HttpChannelState.getCompliaceViolationListener()in all cases (this gets the benefit of a singleComplianceViolation.Listenerto use, along with all of theinitialize(),onRequestBegin(), andonRequestEnd()techniques.HttpConfigurationnotify methodsComplianceViolation.notify()static methods.Closes #12806