Question

I'm trying to implement a batch request method in pyramid. I see in the docs that it's done with

subrequest = Request.blank('/relative/url')
request.invoke_subrequest(subrequest)

I'm just wondering how do you pass along the headers and cookies? Is it already done for you or is it

request.invoke_subrequest(subrequest, cookies=request.cookies, headers=request.headers)

What about parameters for different methods? The docs only have a POST keyword arg.

I feel like the docs are a little vague, or I can't find the correct docs on how to do this. Thanks

Was it helpful?

Solution

I'm just wondering how do you pass along the headers and cookies?

From http://docs.pylonsproject.org/projects/pyramid/en/1.5-branch/narr/subrequest.html#subrequest-chapter :

The pyramid.request.Request.invoke_subrequest() API accepts two arguments: a positional argument request that must be provided, and use_tweens keyword argument that is optional; it defaults to False.

This tells us that the constructor only wants a Request object, and optionally a value for use_tweens, so no, this

request.invoke_subrequest(subrequest, cookies=request.cookies, headers=request.headers)

will not work.

Then, from http://docs.pylonsproject.org/projects/pyramid/en/1.5-branch/narr/subrequest.html

It's a poor idea to use the original request object as an argument to invoke_subrequest(). You should construct a new request instead as demonstrated in the above example, using pyramid.request.Request.blank(). Once you've constructed a request object, you'll need to massage it to match the view callable you'd like to be executed during the subrequest. This can be done by adjusting the subrequest's URL, its headers, its request method, and other attributes. The documentation for pyramid.request.Request exposes the methods you should call and attributes you should set on the request you create to massage it into something that will actually match the view you'd like to call via a subrequest.

So basically, you need to configure your request before you pass it to invoke_subrequest().

Luckily there is an entire page that documents the Request class. There we can find a whole lot options to configure it, etc.


What about parameters for different methods? The docs only have a POST keyword arg.

Also on the Request class documentation page, there is this

method

Gets and sets the REQUEST_METHOD key in the environment.

And on http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/narr/viewconfig.html I found

request_method This value can be a string (typically "GET", "POST", "PUT", "DELETE", or "HEAD") representing an HTTP REQUEST_METHOD

I must agree with you that the documentation is a little vague here and there, but I assume you can use it like this

request.method = 'POST'
# Or
request.method = 'GET'
# Etc.

Summary

You'll want to do it like this

subrequest = Request.blank('/relative/url')
# Configure the subrequest object
# set headers and other options you need.
request.invoke_subrequest(subrequest)

Note

I am aware this is not a 100% complete answer with some code that you can copy paste and it'll just work (especially regarding configuring the request object), but I think this answer contains some information that, at the very least, will get you on the right track and I hope it will be of some help to you.

OTHER TIPS

The following code worked for me. It copies all (headers, cookies, query string, post parameters, etc.):

def subrequest(request, path):
    subreq = request.copy()
    subreq.path_info = path
    response = request.invoke_subrequest(subreq)
    return response

Somewhat late, but based on the above two answers here is how I did this. I didn't quite like the above answer to just copy everything. Looking at the documentation of the blank() method there is a kw argument and it says

All necessary keys will be added to the environ, but the values you pass in will take precedence. If you pass in base_url then wsgi.url_scheme, HTTP_HOST, and SCRIPT_NAME will be filled in from that value.

Assuming that the view's request contains the right header information and cookies that you need for your subrequest, you can use the following code:

@view_config( ... )
def something(request):
    ...
    kwargs = { "cookies": request.cookies,                                  
               "host"   : request.host,                                     
             }                                                              
    req = Request.blank("/relative/url", **kwargs)
    resp = request.invoke_subrequest(req)                                   

Other header information (e.g. accept, accept_encoding, etc.) are properties of pyramid.request objects, and can be added to the kwargs dictionary like shown in the code snippet above.

The object returned by invoke_subrequest() is a Response object documented here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top