Skip to content
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

WebClient and RestClient's defaultRequest(..) is not invoked early enough #32053

Closed
injae-kim opened this issue Jan 18, 2024 · 4 comments
Closed
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: bug A general bug
Milestone

Comments

@injae-kim
Copy link
Contributor

Background

/**
 * Global option to specify a header to be added to every request,
 * if the request does not already contain such a header.
 */
Builder defaultHeader(String header, String... values);

WebClient and RestClient have default[Header|Cookie|Request|..] that useful to set default value on request.

private void initHeaders(HttpHeaders out) {
if (!CollectionUtils.isEmpty(defaultHeaders)) {
out.putAll(defaultHeaders);
}
if (!CollectionUtils.isEmpty(this.headers)) {
out.putAll(this.headers);
}

As you can see above code, defaultHeader value is set only when it's not contained in headers.

Question

/**
 * Provide a consumer to customize every request being built.
 * @param defaultRequest the consumer to use for modifying requests
 */
Builder defaultRequest(Consumer<RequestHeadersSpec<?>> defaultRequest);

private ClientRequest.Builder initRequestBuilder() {
if (defaultRequest != null) {
defaultRequest.accept(this);
}

But on defaultRequest(..), it can override request's values unlike defaultHeader cause it's called on every request being built.

Reproduce

// DefaultWebClientTests.java
@Test
void defaultRequest_override() {
	ThreadLocal<String> context = new NamedThreadLocal<>("foo");

	WebClient client = this.builder
			.defaultRequest(spec -> spec.accept(MediaType.APPLICATION_JSON)) // default
			.build();

	client.get().uri("/path")
			.accept(MediaType.IMAGE_PNG) // set
			.retrieve().bodyToMono(Void.class).block(Duration.ofSeconds(10));

	ClientRequest request = verifyAndGetRequest();
	assertThat(request.headers().getAccept()).isEqualTo(MediaType.IMAGE_PNG); // ❌Expected: <image/png> but actual: <application/json>
}

image

I think defaultRequest(spec -> spec.accept(MEDIA_TYPE)) will override all media types that set by accept(..) on this request.

Q. is above behavior of defaultRequest(..) is intended? thanks!

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jan 18, 2024
@injae-kim
Copy link
Contributor Author

injae-kim commented Jan 18, 2024

FYI, I found this issue while investigating #32028 😃

If this behavior of defaultRequest(..) is intended, feel free to close this issue~!
(I simply think that defaultRequest works similarly with defaultHeader, setting default value)

@snicoll snicoll changed the title [Question] WebClient and RestClient's defaultRequest(..) behavior about setting default values WebClient and RestClient's defaultRequest(..) behavior about setting default values Jan 18, 2024
@jhoeller jhoeller added the in: web Issues in web modules (web, webmvc, webflux, websocket) label Jan 24, 2024
@poutsma
Copy link
Contributor

poutsma commented Jan 25, 2024

Thanks for spotting this odd behavior, which is indeed not intentional. However, the fact remains that the current behavior has been present since 5.0, and changing it, to do effectively the opposite of what it is currently doing, can affect many users.

Fixing this issue is trivial—I have a fix locally—but that fix won't be merged until 6.2.

@poutsma poutsma added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Jan 25, 2024
@poutsma poutsma added this to the 6.2.0-M1 milestone Jan 25, 2024
@poutsma poutsma self-assigned this Jan 25, 2024
@poutsma
Copy link
Contributor

poutsma commented Jan 25, 2024

Note that—even though this is a bug—it will not be backported to the 6.1, 6.0, or 5.3 branches, as it fixing it will break backward compatibility.

@injae-kim
Copy link
Contributor Author

even though this is a bug—it will not be backported to the 6.1, 6.0, or 5.3 branches, as it fixing it will break backward compatibility.

Aha I understood! I agree with your opinion. I just wondered it's bug or intended behavior.

Anyway I'm glad to found this trivial bug, and please share if there's something I can help~ thanks! 🙇

@rstoyanchev rstoyanchev changed the title WebClient and RestClient's defaultRequest(..) behavior about setting default values WebClient and RestClient's defaultRequest(..) is not invoked early enough Jan 25, 2024
@bclozel bclozel changed the title WebClient and RestClient's defaultRequest(..) is not invoked early enough WebClient and RestClient's defaultRequest(..) is not invoked early enough Feb 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: bug A general bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants