-
Notifications
You must be signed in to change notification settings - Fork 38.9k
Avoid redundant URI object creation in WebClientUtils #36641
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: main
Are you sure you want to change the base?
Changes from all commits
5c747a4
3d21e39
488ad3d
b04bf0c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| /* | ||
| * Copyright 2002-present the original author or authors. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * https://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| package org.springframework.web.reactive.function.client; | ||
|
|
||
| import java.net.URI; | ||
|
|
||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| import org.springframework.http.HttpMethod; | ||
|
|
||
| import static org.assertj.core.api.Assertions.assertThat; | ||
|
|
||
| /** | ||
| * Tests for {@link WebClientUtils#getRequestDescription}. | ||
| * | ||
| * @author Park Dong-Yun | ||
| */ | ||
| class WebClientUtilsTests { | ||
|
|
||
| @Test | ||
| void stripsQueryParams() { | ||
| URI uri = URI.create("https://api.example.com/search?q=test&page=1"); | ||
| assertThat(WebClientUtils.getRequestDescription(HttpMethod.GET, uri)) | ||
| .isEqualTo("GET https://api.example.com/search"); | ||
| } | ||
|
|
||
| @Test | ||
| void noQueryReturnsAsIs() { | ||
| URI uri = URI.create("https://api.example.com/health"); | ||
| assertThat(WebClientUtils.getRequestDescription(HttpMethod.GET, uri)) | ||
| .isEqualTo("GET https://api.example.com/health"); | ||
| } | ||
|
|
||
| @Test | ||
| void preservesPort() { | ||
| URI uri = URI.create("https://api.example.com:8443/path?q=1"); | ||
| assertThat(WebClientUtils.getRequestDescription(HttpMethod.GET, uri)) | ||
| .isEqualTo("GET https://api.example.com:8443/path"); | ||
| } | ||
|
|
||
| @Test | ||
| void remainsPathEncodedWhenStrippingQuery() { | ||
| URI uri = URI.create("https://host/hello%20world?q=1"); | ||
| assertThat(WebClientUtils.getRequestDescription(HttpMethod.GET, uri)) | ||
| .isEqualTo("GET https://host/hello%20world"); | ||
| } | ||
|
|
||
| @Test | ||
| void stripsUserInfoWithQuery() { | ||
| URI uri = URI.create("https://admin:secret@host/api?token=abc"); | ||
| assertThat(WebClientUtils.getRequestDescription(HttpMethod.GET, uri)) | ||
| .isEqualTo("GET https://host/api"); | ||
| } | ||
|
|
||
| @Test | ||
| void stripsUserInfoWithoutQuery() { | ||
| URI uri = URI.create("https://admin:secret@host/api"); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in the original issue, you added a comment about this: I think we should indeed strip the user info from the logged URI. Can you update the implementation to check for the presence of raw user info?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should I strip the fragment too when only the fragment is in presence for the URI? I guess we should, since this is more consistent with existing API, and the purpose of the method is purely for logging.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes please, let's remove the user info, query and fragment if any of them are present. Thanks! |
||
| assertThat(WebClientUtils.getRequestDescription(HttpMethod.GET, uri)) | ||
| .isEqualTo("GET https://host/api"); | ||
| } | ||
|
|
||
| @Test | ||
| void stripsFragmentWithQuery() { | ||
| URI uri = URI.create("https://host/page?q=1#section"); | ||
| assertThat(WebClientUtils.getRequestDescription(HttpMethod.GET, uri)) | ||
| .isEqualTo("GET https://host/page"); | ||
| } | ||
|
|
||
| @Test | ||
| void stripsFragmentWithoutQuery() { | ||
| URI uri = URI.create("https://host/page#section"); | ||
| assertThat(WebClientUtils.getRequestDescription(HttpMethod.GET, uri)) | ||
| .isEqualTo("GET https://host/page"); | ||
| } | ||
|
|
||
| @Test | ||
| void questionMarkInFragmentNotTreatedAsQuery() { | ||
| URI uri = URI.create("https://host/page#frag?param=value"); | ||
| assertThat(WebClientUtils.getRequestDescription(HttpMethod.GET, uri)) | ||
| .isEqualTo("GET https://host/page"); | ||
| } | ||
|
|
||
| @Test | ||
| void ipv6Host() { | ||
| URI uri = URI.create("http://[::1]:8080/path?q=1"); | ||
| assertThat(WebClientUtils.getRequestDescription(HttpMethod.GET, uri)) | ||
| .isEqualTo("GET http://[::1]:8080/path"); | ||
| } | ||
|
|
||
| @Test | ||
| void opaqueUriUnchanged() { | ||
| URI uri = URI.create("mailto:user@example.com?subject=hello"); | ||
| assertThat(WebClientUtils.getRequestDescription(HttpMethod.GET, uri)) | ||
| .isEqualTo("GET mailto:user@example.com?subject=hello"); | ||
| } | ||
|
|
||
| @Test | ||
| void relativeUri() { | ||
| URI uri = URI.create("/api/search?q=test"); | ||
| assertThat(WebClientUtils.getRequestDescription(HttpMethod.GET, uri)) | ||
| .isEqualTo("GET /api/search"); | ||
| } | ||
|
|
||
| @Test | ||
| void prefixesHttpMethod() { | ||
| URI uri = URI.create("https://host/resource?v=1"); | ||
| assertThat(WebClientUtils.getRequestDescription(HttpMethod.POST, uri)) | ||
| .startsWith("POST "); | ||
| assertThat(WebClientUtils.getRequestDescription(HttpMethod.DELETE, uri)) | ||
| .startsWith("DELETE "); | ||
| } | ||
|
|
||
| } | ||
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.
Could explain why the path needs decoding? I think using the raw path would be consistent with URI#toString().
Uh oh!
There was an error while loading. Please reload this page.
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.
There were two reasons.
I should've made a comment about it. I was too focused on only describing the performance parts. Thanks for pointing that @bclozel
Should I rollback and return the encoded string?
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.
Yes please, let's use the encoded form. It will be consistent with the URI toString and will avoid log injection / log forging vulnerabilities.
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.
Resolved all what you have said @bclozel. Thanks for helping me a lot! Really appreciate it.