How To HTTP Sessions?

Does anyone has a working example, demo, tips, docs, comments, etc about how to do HTTP Sessions for a real project not just for a helloworld (prod-ready) on Apistar???.

If im using Django ORM with Apistar can I use Djangos Session?.

Specifically this part on the docs:

It just says “implement your own”. :neutral_face:

I dont post code because I dont have any yet, and I dont know how to start implementing it.

Part of the beauty I find in the APIstar codebase is the use of all the right tools. So first I looked in apistar/ to see what a HTTPSession must provide:

class SessionStore(metaclass=abc.ABCMeta):
    def new(self) -> http.Session:
        raise NotImplementedError

    def load(self, session_id: str) -> http.Session:
        raise NotImplementedError

    def save(self, session: http.Session) -> typing.Dict[str, str]:
        raise NotImplementedError

That makes it quite clear what your obligations are.

Next I looked at apistar/components/ to see how an example implementation worked.

Interesting to note the context managed used for get_session, which shows the exact sequence your SessionStore will be invoked in:

If there is a session_id cookie, then SessionStore.load(session_id) is called, otherwise, both of which should yield a dict-like session container.

After the request, will be called, and is expected to yield headers to update the response, if needed.

Does this help answer your question?

1 Like

Yeah, I know that, I was looking for implemented code, to see what they are using as “backend” of the Sessions,

  • Can I use Postgres as Store?.
  • Redis?, Sqlite?, any other?.

IMHO your biggest problem will be supporting the types to store, as you’ll need to serialise the data somehow.

JSON is light and fast but doesn’t support date/time types, or objects.
msgpack is an external package, but can support custom extensions easily.
Pickly is also built in, and supports all Python types, but can be a can of worms sometimes.

Then you just need a table to store str(30) -> bytes … easy in PG, SQLite, Redis… easiest to sub-class LocalMemorySessionStore since it already implements new() and _generate_key.

If you can wait, I’ll write some examples tonight.

1 Like

Thanks very very much for the Feedbacks !!!. :smirk_cat:

I want to help make components, pip installable ones, thats why Im asking the best way to do it, not just for me, so everyone can just install and use it.

I wrote a MsgPack Render and Parser here: Apistar-msgpack: MessagePackRenderer & MessagePackParser

I like I dont know if it can fit the role.
MsgPack is also nice.

I did at some time define a JSON-based format that would let you encode [only registered] Python objects. Just use the following function as your object_hook :


def restore_object(data):
    type_name = data.pop('__type__', None)
    return TYPE_MAP.get(type_name, dict).restore(**data)

So the ‘type’ key is used to alter the class, and all the other keys are used as kwargs to instantiating the class.

I call it “TSON” for Typed JSON.

It only supports registered types for safety… otherwise people could pass in anything at all.

1 Like

Hi @juancarlospaco,

I implemented storage of HTTP session in cookies, I have been using that approach in different lanugages for many years in productions.

I craeted library:

    import contextlib

import typing
import json
import os

from werkzeug.http import dump_cookie, parse_cookie

from apistar import http
from apistar.interfaces import SessionStore

from cryptography.fernet import Fernet

COOKIE_NAME = ‘session’

default_cipher_key = 'hdJOXy9nenVk3vllaxtbM7WyUL3UaykReMgrkCnmyxc='
cipher = Fernet(os.getenv(‘SESSION_CIPHER_KEY’, default_cipher_key))

class CookieSessionStore(SessionStore):

def new(self) -> http.Session:
    return http.Session(session_id='')

def load(self, session_data: str) -> http.Session:
        data = json.loads(cipher.decrypt(str.encode(session_data)))
    except (ValueError, Exception):
    return http.Session(session_id='', data=data)

def save(self, session: http.Session):
    data = cipher.encrypt(str.encode(json.dumps(
    cookie = dump_cookie(COOKIE_NAME, data)
    return {'Set-Cookie': cookie}

def init_cookie_session(cookie: http.Header,
response_headers: http.ResponseHeaders) -> typing.Generator[http.Session, None, None]:

cookies = parse_cookie(cookie)
session_data = cookies.get(COOKIE_NAME)
if session_data:
    session = CookieSessionStore().load(session_data)
    session = CookieSessionStore().new()
    yield session
    session_headers = CookieSessionStore().save(session)

And then I am using it as component:

from utils.cookie_sessions import init_cookie_session

Cookie based session

cookie_sessions = [
Component(http.Session, init=init_cookie_session)

Maybe you would like to create a pull request with this code and tests?

Thank you very very much!!!.

Can you please fix the Code tags here or paste it into a Gist, its hard to understand like that.

I can create a Package with tests, docs and publish to pypi, if you “Donate” this code. :grinning:

I have created gist:

It would be really great if you can do a pull request to apistar? In other case, just create pypi package and maybe it will be usefull for someone else. Feels free to use that code as you want.

Best, Vlad

1 Like


Great! Thanks @juancarlospaco

On PyPI: pip install apistar_session_cookie
With Docs, Tests, CI, working Example.

hey @juancarlospaco great work with that package, docs are really nice and clean. I am building a small api and I was reading about session storage in the apistar docs. The relevant bit is:

The default implementation stores the session information in local memory, which isn’t suitable for anything other than development and testing. For production you’ll need to implement a session store that integrates with some kind of persistent storage.

I am not sure what to do here exactly, so then I found your package and it looks like it provides a simple cookie based persistent session storage. But I am still not sure if this is what I need or what it accomplishes. When I have code as follows

def list_accounts(request: http.Request, auth: Auth, session: Session):
    queryset = session.Account.objects.filter(owner=auth.user['id'])
    accounts = account_schema.dump(queryset, many=True)

do I need to actually use a session storage? is the idea that if someone sends multiple API requests in a short window of time it will re-use the same session/connection to the database and not constantly be opening and closing db connections?

If so, do I just need to drop this package in and it basically handles setting the cookie and as long as clients send the cookie back it will re-use the session/db connection? I don’t really need to write any data to the session, they send their credentials through a JWT using an Authorization header and that is all I really need.

Cookie is like an encrypted JSON on the users browser.
Database is a relational data store on the server side.

On your code the variable session is a Database.
On my code the variable session is a Cookie.

Maybe rename the Database to database and the Cookie to cookie,
or any other name that works for you and reduces the confusion.

The rest depends on what you are building.

1 Like

Ah ok, I was getting confused by the similar terminology. I am not using an HTTP Session, I am using a Database session, and I do not need to create my own SessionStore, that would be if I wanted to manage an HTTP Session.

Thanks for clearing that up!

1 Like