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.Builder option to customize every request [SPR-16873] #21412

Closed
spring-issuemaster opened this issue May 25, 2018 · 4 comments
Closed

WebClient.Builder option to customize every request [SPR-16873] #21412

spring-issuemaster opened this issue May 25, 2018 · 4 comments
Assignees
Milestone

Comments

@spring-issuemaster
Copy link
Collaborator

@spring-issuemaster spring-issuemaster commented May 25, 2018

Rob Winch opened SPR-16873 and commented

Similar to how there are defaultCookies and defaultHeaders it would be nice if there were support for defaultAttributes(Consumer<Map<String, Object>>)

The execution the Consumer should be delayed until the request is created so that the Consumer can rely on external factors. For example, when using WebClient in a Servlet environment Spring Security's SecurityContext is stored on a ThreadLocal and could be populated as a default attribute.

It is important to note that we cannot rely on an ExchangeFilterFunction to populate the attribute because this may happen on another Thread.


Affects: 5.0.6

Referenced from: commits 8bffb6a

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented May 29, 2018

Rossen Stoyanchev commented

After taking a closer look, the WebClient.Builder consumers for headers and cookies simply modify the map in the builder, i.e. they're not used at request time. I don't think we want a consumer for attributes that is inconsistent with that behavior.

I guess we'd have to with something like:

Builder attributeSupplier(Supplier<Map<String, Object>> supplier);

That would be explicitly documented as being invoked at request building time, with the suggestion that it can be used, for example, to transfer ThreadLocal context to the request.

Such a Supplier can be used more generally to pass any information to a filter, which includes default attributes, and/or other information that can be used to add headers and cookies from a filter. In other words we shouldn't have to also add defaultAttributes to the builder, nor Supplier methods for headers and cookies.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Jun 4, 2018

Rob Winch commented

This seems less powerful than the original proposal. How would the user be able to remove attributes that might have been added?

Another alternative would be to switch the cookies, headers, etc to be at request time to better align them. I suppose this might not be as desirable as it could be a breaking change. However, the fact that this happens at build time is a bit surprising given it is a Consumer which is typically indicates it is delayed.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Jun 5, 2018

Rossen Stoyanchev commented

Consumer in this case is about getting access to the headers/cookies initialized so far (e.g. multiple parties via Boot's WebClientCustomizer checking what's already set). It's similar to other parts of the API (e.g. when building the request) where existing headers, cookies, attributes are exposed this way. So it's not about being deferred and I don't think Consumer implies that.

We could change how default headers are implemented from a Map to one or more Consumer's and invoke those in the same order at the beginning of every request, and it shouldn't matter, as long as repeated invocation doesn't have any side effect, which is theoretically possible, or otherwise is computationally expensive. That said I think it's important to keep a distinction between values provided once on initializaiton vs values re-obtained on every request.

How about a method on WebClient.Builder with a Consumer for a request being built. That would let you customize any request, in any way you see fit:

 
Builder defaultRequest(Consumer<RequestHeadersSpec<?>> requestConsumer);
@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Jul 3, 2018

Rossen Stoyanchev commented

There is now a defaultRequest option on WebClient.Builder.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.