-
Notifications
You must be signed in to change notification settings - Fork 1
bugfix: encoded query parameter (web) #18
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
Conversation
@@ -1,4 +1,4 @@ | |||
openapi.validation.sample-rate=0.5 | |||
openapi.validation.sample-rate=1 |
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.
ℹ️ Unrelated to fix. Increasing to 1 for better example.
@@ -79,14 +81,22 @@ public ValidationResult validateRequestObject(final RequestMetaData request, Str | |||
private static SimpleRequest buildSimpleRequest(RequestMetaData request, String requestBody) { | |||
var requestBuilder = new SimpleRequest.Builder(request.getMethod(), request.getUri().getPath()); | |||
URLEncodedUtils.parse(request.getUri(), StandardCharsets.UTF_8) | |||
.forEach(p -> requestBuilder.withQueryParam(p.getName(), p.getValue())); | |||
.forEach(p -> requestBuilder.withQueryParam(p.getName(), getQueryParameterValueWithOptionalDecode(p))); |
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 is the actual fix. All the rest is just other small improvements.
@@ -13,7 +12,7 @@ public class ServletMetaDataFactory { | |||
public static final String HEADER_CONTENT_TYPE = "Content-Type"; | |||
|
|||
public RequestMetaData buildRequestMetaData(HttpServletRequest request) { | |||
var uri = ServletUriComponentsBuilder.fromRequest(request).build(Map.of()); | |||
var uri = ServletUriComponentsBuilder.fromRequest(request).build().toUri(); |
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.
ℹ️ Unrelated to fix. Not strictly needed, but this simplifies the code as internally the old call did this + additional unnecessary logic.
@@ -22,5 +22,6 @@ dependencies { | |||
|
|||
testImplementation 'org.springframework.boot:spring-boot-starter-test' | |||
testImplementation 'org.springframework:spring-web' | |||
testImplementation 'org.springframework:spring-webmvc' |
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.
ℹ️ Unrelated to fix. Not needed right now. But this dependency is useful for writing tests in the future.
Background:
I wrote some tests that were for a previous fix of the problem, but they got reverted as I found a nicer way to fix it. When I wrote those tests this dependency was needed for the tests to run. And it took a while to find this dependency to make the tests work. So better leave them for now so we save time in the future :)
...ion-core/src/main/java/com/getyourguide/openapi/validation/core/OpenApiRequestValidator.java
Outdated
Show resolved
Hide resolved
) { | ||
this.threadPoolExecutor = threadPoolExecutor; | ||
this.validator = new OpenApiInteractionValidatorFactory().build(specificationFilePath, configuration); | ||
this.validator = validator; |
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.
ℹ️ To mock the validator this needs to be injected. So I improved the architecture here (should have done this from the beginning).
if (requestBody != null) { | ||
requestBuilder.withBody(requestBody); | ||
} | ||
request.getHeaders().forEach(requestBuilder::withHeader); | ||
return requestBuilder.build(); | ||
} | ||
|
||
private static String getQueryParameterValueWithOptionalDecode(NameValuePair p) { |
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 wonder why we pass in the NameValuePair
instead of directly the value. Why not pass in p.getValue()
and rename the method to nullSafeURLDecode
?
|
||
@Test | ||
public void testWhenEncodedQueryParamIsPassedThenValidationShouldHappenWithQueryParamDecoded() { | ||
var uri = URI.create("https://api.example.com?ids=1%2C2%2C3"); |
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.
Any other cases we should test, e.g. when &
or =
is contained encoded in the value, or when we have multiple name-value pairs being passed?
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.
So, added more tests for these cases you mentioned (and also for spaces encoded with +
). Hope happy you are 😉 .
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.
Nice. Feedback for next time: It would make sense to split up into different test cases, so that a test failure will give you more insight into the specific case that is failing. If your tests fail now, the "minimum failing example" won't be evident. Good for this PR though.
When a query parameter with a comma separated list is sent with
,
being encoded (e.g.123%2C2%2C3
vs1,2,3
) then this would be interpreted as a string instead of a list.This does a urldecode when passing the parameter to the validator.