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

WIP: add session middleware with pluggable backing #266

Conversation

chrisdickinson
Copy link

WIP: Add pluggable session middleware

Per #9 – I had some rough session middleware I was working on in support of building a blog in Tide. It's patterned off other session middleware I've worked with in the past (e.g., in Django) & is similar to what powers www.npmjs.com.

Including this middleware in an application gives handlers the ability to access and modify a long-lived session object via a SessionExt trait:

    app.at("/").get(async move |ctx: Context<()>| {
        // SessionMap implements Deref<HashMap<String, String>>
        // If this happens during a request a session will be created and
        // a session id sent to the user in a cookie.
        sess.insert(String::from("username"), String::from("chris"));

        // Or: rotate the session without making any changes
        let mut sess = ctx.session_mut();
        SessionMap::rotate(&mut sess);

        "Hello, world!"
    });

    app.at("/ronly").get(async move |ctx: Context<()>| {
        // or fetch the session in a read-only way, guaranteed to not create new sessions
        let sess = ctx.session();

        "Hello, world!"
    });

Users are able to provide their own backing store:

struct InMemorySessionStore;

impl SessionStore for InMemorySessionStore {
    fn load_session(&self, key: &str) -> SessionMap {
        SessionMap::new()
    }

    fn commit(&self, key: Option<&str>, session: Ref<Box<SessionMap>>) -> Result<HeaderValue, std::io::Error> {
        Ok(HeaderValue::from_static("<a cryptographically secure session token>"))
    }
}

(Tide would ideally provide a memory store & possibly a redis- or memcache-backed store?)

Motivation and Context

I am coming from Node, where (until recently!) I used to work on the npm registry & website. At my new day job, we're moving from Node to Go, and I'm trying to get a feel for how Tide and Rust might fit into that same space. Also – I have the cycles to contribute back to open source now, and I'd really like to invest as much of that time as possible back into Rust!

As a result, I picked the goal of building a blog + management system for my personal site. One of my requirements is that I be able to log in to manage posts, so I needed session middleware.

This is a draft PR to start a conversation about how to accomplish that task: I'm happy to continue working on it, pair with someone else, go back to the drawing board entirely, or buzz off for now if this takes more cycles from maintainers than it returns! (Y'all have been doing great work 💞)

How Has This Been Tested?

This has been manually tested in a local application. I'm planning on patterning the tests after the other middleware in this repo.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

prasannavl and others added 30 commits May 15, 2019 06:51
fix cargo fmt

loosen up clippy to warnings on examples

snipe dev deps from core

eliminate some clippy warnings for examples

add publish false, and remove publish requirements

rename tide-examples to just examples
Rename `serve` to `run`, add asynchronous `serve`
Co-Authored-By: Wonwoo Choi <chwo9843@gmail.com>
Check example in readme compiles during testing
Remove #[allow(unused_mut)]
Middleware-based compression and decompression
Improve curl command consistency
* Move core traits and types to tide-core

* Move cookies middleware to tide-cookies

* Remove unncessary dependencies and use relative paths in README
* Update travis config

 * Separate out individual build jobs for faster wall-clock testing

 * Fix clippy not actually denying warnings (excluded examples because
   these are currently failing and have non-trivial fixes)

 * Add build job that checks --no-default-features works

 * Add build job that checks for intra-doc-resolution failures (excluded
   tide because of bugs in re-exports with the intra-doc feature)

* Fix warnings

* Fix doc-link in tide-cookies
Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com>
Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com>
fairingrey and others added 25 commits May 21, 2019 07:43
add newline before EOF
pub use ResultDynErrExt in tide::error
…lementation

Also add a bunch of tests that demonstrate the implemented behavior
Rename Context<Data> to Context<State>
Fix the documentation for wildcards for path definitions to match implementation
* doc: Add doc comment to tide-core

* doc: Add documantation to tide-cookie

* doc: Add doc to tide-compression

* doc: Add doc comment

* fix doc links

* fix path

* doc: Add doc comment
@yoshuawuyts
Copy link
Member

@chrisdickinson thanks so much for starting work on this! -- The general direction here seems very promising -- also the conversation in #9 seems great.

Regarding this implementation, probably the only comment I'd make is that I'd expect the load_session and commit trait functions to be async. If they're making requests to external databases we'd likely not want to block while the results are being fetched.

However async fn in traits is currently not supported yet. So in order to make these work asynchronously, workarounds would need to be applied which are similar to http_service::HttpService. (Which is to say: define associated Future types).

Very excited for this!

@yoshuawuyts
Copy link
Member

Published https://crates.io/crates/async-session which is a continuation of the work done in this patch. Next step would be to build a middleware that can use that to integrate with Tide.

Going to go ahead and close this PR for now. Thanks so much @chrisdickinson!

@yoshuawuyts yoshuawuyts closed this Feb 6, 2020
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.

None yet