user14335743
user14335743

Reputation:

Check the size of Flask's session cookie

I'm using Flask's default secure cookie session. I've seen that the size limit of a cookie is 4KB. How can I check the size of Flask's session cookie?

Upvotes: 2

Views: 2734

Answers (2)

davidism
davidism

Reputation: 127180

Werkzeug already shows a detailed warning when generating a set-cookie header if the serialized cookie value is too large (> 4093 bytes).

UserWarning: The 'session' cookie is too large: the value was 4050 bytes but the header required 50 extra bytes. The final size was 4100 bytes but the limit is 4093 bytes. Browsers may silently ignore cookies larger than this.

This is only a warning because we don't actually know what any given browser will accept, 4093 is just the lowest value in common use as of a few years ago. (What is the maximum size of a web browser's cookie's key?)

If you're storing >4k of data in a session cookie, you probably want to reevaluate how you're storing data rather than trying to add size checks. A 4k cookie means that 4k of data is being sent with every request and response. For example, you probably want to retrieve data from a database, or Store large data or a service connection per Flask session, in which case all you need to store in the session is an id to fetch the data.


If you really want to check the size of cookies programmatically, you can get them from response.headers, and check their length. Flask only serializes the session cookie right before returning the response, but you can trigger that manually so that the cookie value is available.

from flask.globals import request_ctx

@app.after_request()
def error_for_large_cookie(response):
    app.session_interface.save_session(app, request_ctx, response)
    
    for value in response.headers.getlist("Set-Cookie", as_bytes=True):
        if len(value) >= 4093:
            raise ValueError("Cookie too large.")

This will cause a 500 error (and show the traceback in the terminal) if any cookie including the session is too large. Or turn the warning into an error for the same effect but less code:

import warnings

warnings.filterwarnings("error", r".* cookie is too large", module=r"werkzeug\.http")

Checking the size of the session dict in Python with sys.getsizeof() recursively isn't useful, as the size that matters is the serialized cookie header, not the Python object size.

Upvotes: 4

JimmyLamothe
JimmyLamothe

Reputation: 59

I coulnd't get the previous answer to work in Flask 3.0. It seems that _request_ctx_stack is deprecated since 2.4.

This solution is less precise, but might suffice. We serialize the cookie values ourselves using pickle. While this won't be identical to the actual cookie size, the values will hopefully be similar.

You could test this using dummy session data. Increase its size until you get the Werkzeug user warning. You could then check the estimated value to see if it's close enough to the actual 4k limit for your purposes.

I also don't know Flask well enough to know if the before_request or the after_request decorator is more appropriate, though I would guess both would work.

@app.before_request
def print_cookie_size():
    import pickle
    values = []
    for key in session.keys():
        values.append(session[key])
    print(f'approximate cookie size: {len(pickle.dumps(values))} bytes')

Upvotes: -1

Related Questions