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

initial sketch for session.regenerate() support #6

Merged
merged 3 commits into from
Aug 8, 2022

Conversation

maxcountryman
Copy link
Owner

This changes how sessions are provided by the middleware in order to
support the ability to use session methods, like regenerate. Crucially
sessions are no longer cloned and instead are stored via a handle. This
handle is defined as Arc<RwLock<async_session::Session>> which allows
us to clone the Arc without cloning the contained session directly.

In order to support better ergonomics we also introduce two new
extractors: ReadableSession and WritableSession. These respectively
enable reading and writing of sessions. Internally they acquire the lock
and expose the session for manipulation.

One downside to this approach is that library consumers now need to use
two separate types as opposed to using async_session::Session via
Extension directly. However the API here now no longer requires
Extension and enforces explicit usage of reading and writing via the
public type interface.

Fixes: #5.

This changes how sessions are provided by the middleware in order to
support the ability to use session methods, like `regenerate`. Crucially
sessions are no longer cloned and instead are stored via a handle. This
handle is defined as `Arc<RwLock<async_session::Session>>` which allows
us to clone the `Arc` without cloning the contained session directly.

In order to support better ergonomics we also introduce two new
extractors: `ReadableSession` and `WritableSession`. These respectively
enable reading and writing of sessions. Internally they acquire the lock
and expose the session for manipulation.

One downside to this approach is that library consumers now need to use
two separate types as opposed to using `async_session::Session` via
`Extension` directly. However the API here now no longer requires
`Extension` and enforces explicit usage of reading and writing via the
public type interface.

Fixes: #5.
@maxcountryman
Copy link
Owner Author

@Ptrskay3 here's what I've put together pursuing the interior mutability option. I'd love your feedback.

Copy link
Contributor

@Ptrskay3 Ptrskay3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall it seems very nice, thank you for putting this together. I haven't tested this very extensively yet, but I definitely will in the near future.

Comment on lines +16 to +17
// NB: This DOES NOT update the store, meaning that both sessions will still be
// found.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Technically, async_session doesn't promise to purge the old session from the storage. In most applications it's probably fine, but depends on what type of data you store.

I tried to add the purging functionality to this implementation, but unfortunately the destroy_session expects an async_session::Session as argument, so even though in the middleware we are able to inspect and compare the id of the session before and after the handler is called, there's no easy way to purge it.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a little orthogonal to our patch here, but perhaps there's a missing "refresh" method from async_sessions itself? I think I may have seen something about that browsing through their repo issues.

where
B: Send,
{
type Rejection = http::StatusCode;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no way to return http::StatusCode (or any other type of rejection) from the implementation, so I think this should be std::convert::Infallible. If the session layer is not added, let the thread panic, that's definitely a bug, so I think we can leave the expect.

src/session.rs Outdated
Ok(None) => {}

Ok(None) => {
tracing::warn!("The cookie value is missing; no cookie will be set!");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my experience, this makes a lot of unnecessary noise in the logs. If you insist on keeping this, I think this should be info level at max.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for calling this out. I was initially assuming this was a case that we'd not really hit, but in practice you're absolutely right. I'll take it out for the time being.

@maxcountryman maxcountryman force-pushed the feat/support-regenerate branch from c3dfb41 to c22f22d Compare August 8, 2022 14:22
@maxcountryman
Copy link
Owner Author

I'll go ahead and merge this. Thank you for your great feedback!

@maxcountryman maxcountryman merged commit 4948e30 into main Aug 8, 2022
@maxcountryman maxcountryman deleted the feat/support-regenerate branch August 8, 2022 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Regenerating session from request handler doesn't work
2 participants