question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Deep copy of request in copy_current_request_context function?

See original GitHub issue

Desiring a deep copy of session RequestContext data is present as a separate issue and pull request. This issue is focused on desiring a deep copy of the request RequestContext data for use in a separate thread. To pursue this, it is necessary to copy the environ data in a new function or the same copy_current_request_context function with a boolean argument to enable the deep copy.

Expected Behavior

For using a thread with a copy of a request, it is advantageous to have the functionality present in copy_current_request_context, though the request needs a deep copy instead of a shallow copy. Based on the code comment of the RequestContext copy function, the intent of the function was a shallow copy, due to “Because the actual request object is the same this cannot be used to move a request context to a different thread unless access to the request object is locked.”.

For having a copy of a request for a separate thread, I found it necessary to modify the flask.copy_current_request_context function to be:

def _copy_current_request_context(function):
    top = _request_ctx_stack.top
    if top is None:
        raise RuntimeError('This decorator can only be used at local scopes '
                           'when a request context is on the stack.  '
                           'For instance within view functions.')
    reqctx = top.copy()
    # environ is used by headers too, so only a copy of environ is necessary
    reqctx.request.environ = reqctx.request.environ.copy()
    def wrapper(*args, **kwargs):
        with reqctx:
            return function(*args, **kwargs)
    return update_wrapper(wrapper, function)

If the request environ is not copied, it is possible with flask 1.0.2 to have older requests in a separate thread read the environ data from newer requests with methods like request.method, which is not desirable at all. I am not suggesting modifying flask.copy_current_request_context to be like the source code above (1 line change), but rather suggesting the RequestContext copy function could be modified to create a deep copy of a request by providing an environ.copy() to the RequestContext class to create a new request object. The deep copy could occur based on a boolean keyword argument added to flask.copy_current_request_context.

However, if you want that functionality for threads, you also need to be able to copy the current_app context:

def _copy_current_app_context(function):
    app_context = _app_ctx_stack.top
    def current_app_context_decorator(*args, **kwargs):
        with app_context:
            return function(*args, **kwargs)
    return current_app_context_decorator

Then you would want to use them together with a single decorator:

def bind_context(function):
    function = _copy_current_request_context(function)
    function = _copy_current_app_context(function)
    return function

Actual Behavior

flask.copy_current_request_context will only do a shallow copy and the copy_current_app_context decorator is not provided, nor is the bind_context decorator. That makes development with threads require more custom source code and be more error-prone than it needs to be.

Environment

  • Python version: 2.7.9
  • Flask version: 1.0.2
  • Werkzeug version: 0.14.1

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:2
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
okeudaycommented, Oct 23, 2018

@dchevell Ok, thanks for the clarification!

0reactions
davidismcommented, Nov 4, 2018

I don’t consider threads uncommon, what I consider uncommon is what’s being asked for in this issue, when extension points to support if if needed already exist, as explained in my previous comment.

Read more comments on GitHub >

github_iconTop Results From Across the Web

No results found

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found