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

MockServerWebExchange should allow setting a WebSession [SPR-16772] #21312

Closed
spring-projects-issues opened this issue Apr 25, 2018 · 8 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

Rob Winch opened SPR-16772 and commented

I've run into a few testing situations that involve saving something in the WebSession and then trying to retrieve it. This is more complicated than necessary at the moment because MockServerWebExchange does not allow setting the WebSession It would be nice if the WebSession could just be set so that these scenarios could easily be tested.


Affects: 5.0.5

Referenced from: commits 15182b2, eef592d

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

By more complicated you mean accessing the session and adding attributes to it? Do you have an example of this somewhere?

So far we've avoided the need for a builder in MockServerWebExchange somehow. By comparison the HttpWebHandlerAdapter which creates exchange instances at runtime has a number of properties. Potentially all of those could end up on such a builder.

@spring-projects-issues
Copy link
Collaborator Author

Rob Winch commented

The general problem is that Spring Security has an API that uses a MockServerWebExchange tries to save something in the WebSession. It then tries to save something else in the WebSession thus needs a new MockServerWebExchange but the same WebSession. An example based on my local code of how I am needing to work around the problem:

 

@Test
public void loadAuthorizationRequestWhenMultipleSavedThenAuthorizationRequest() {
	String oldState = "state0";
	MockServerHttpRequest oldRequest = MockServerHttpRequest.get("/")
			.queryParam(OAuth2ParameterNames.STATE, oldState).build();

	OAuth2AuthorizationRequest oldAuthorizationRequest = OAuth2AuthorizationRequest.authorizationCode()
			.authorizationUri("https://example.com/oauth2/authorize")
			.clientId("client-id")
			.redirectUri("http://localhost/client-1")
			.state(oldState)
			.build();

	WebSessionManager sessionManager = e -> this.exchange.getSession();

	this.exchange = new DefaultServerWebExchange(this.exchange.getRequest(), new MockServerHttpResponse(), sessionManager,
			ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver());
	ServerWebExchange oldExchange = new DefaultServerWebExchange(oldRequest, new MockServerHttpResponse(), sessionManager,
			ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver());

	Mono<OAuth2AuthorizationRequest> saveAndSaveAndLoad = this.repository.saveAuthorizationRequest(oldAuthorizationRequest, oldExchange)
			.then(this.repository.saveAuthorizationRequest(this.authorizationRequest, this.exchange))
			.then(this.repository.loadAuthorizationRequest(oldExchange));

	StepVerifier.create(saveAndSaveAndLoad)
			.expectNext(oldAuthorizationRequest)
			.verifyComplete();

	StepVerifier.create(this.repository.loadAuthorizationRequest(this.exchange))
			.expectNext(this.authorizationRequest)
			.verifyComplete();
}
 

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

Okay, I was thinking a builder method that takes a WebSessionManager, but it sounds like providing a WebSession is all that you need?

@spring-projects-issues
Copy link
Collaborator Author

Rob Winch commented

  but it sounds like providing a WebSession is all that you need?

 

Being able to provide the WebSession and an easy way to create an instance of a WebSession (InMemoryWebSession is currently private) would be great!

@spring-projects-issues
Copy link
Collaborator Author

Rob Winch commented

Rossen Stoyanchev Thanks for adding the builder. Looking at the commit I didn't see any changes for how to create the WebSession. Is the preferred way to create a WebSession to inject into the builder using new InMemoryWebSessionStore().createWebSession() or is there a better way of doing it that I missed?

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

Indeed, I forgot to comment on that part. InMemoryWebSession is private and depends on an instance of InMemoryWebSessionStore. I see no easy path to changing that arrangement.

If anything, for cases when WebSessionStore is stubbed, I considered a MockWebSession, but I'm not sure it's worth replicating the logic in InMemoryWebSession. In the end though using the factory method on InMemoryWebSessionStore like we do here doesn't seem so bad.

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented May 11, 2018

Rob Winch commented

Rossen Stoyanchev It seems pretty difficult to find this mechanism for an average user. Perhaps the builder could be refactored a little to make it easier to use? Once idea is that the builder could have a factory method that delegates to new InMemoryWebSessionStore().createWebSession().

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

I've added a MockWebSession which uses InMemoryWebSessionStore().createWebSession() internally.

@spring-projects-issues spring-projects-issues added type: enhancement A general enhancement in: web Issues in web modules (web, webmvc, webflux, websocket) labels Jan 11, 2019
@spring-projects-issues spring-projects-issues added this to the 5.1 RC1 milestone Jan 11, 2019
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: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants