class ...
self.response.headers.add_header('Set-Cookie','user_id = %s'% id_and_hash)
self.redirect("/app/login")
class ThanksHandler(webapp2.RequestHandler):
def get(self):
if 'user_id' in self.request.cookies:
self.response.out.write('user_id')
else:
self.response.out.write("wrong") // what i am getting
and i have this cookie (I saw in a manager of cookies)
name: user_id
content: 30|a9bdc98e952c0e787aaf0e5466809eea71635d38446d30a9f71f2d15e99fa701
well, basically the problem is that i can't retrieve the cookie that has been initialized. Any reason for that?
When setting the cookie directly using the "Set-Cookie" HTTP-header you have to also take care of the cookie-attributes (depending on how you want to use the cookie).
In this case you set the cookie for example in the path /app/auth and then redirect to /app/login. If you don't explicit specify the cookie-path the browser assumes /app/auth and therefore the cookie is not sent when requesting /app/login. This behaviour is specified in the RFC 6265 (this is more recent than the one I cited in my comment but now the exact algorithm is included in section 5.1.4).
To set the path (or any other cookie-attribute) you can append a list of semicolon-delimited name=value pairs. In this case you want to set the path to / (it could be something different like /app):
self.response.headers.add_header('Set-Cookie','user_id=%s; Path=/'% id_and_hash)
Of course most libraries/frameworks already provide a wrapper for the "Set-Cookie" header. In the case of "webapp2" you can set the cookie with response.set_cookie:
self.response.set_cookie('user_id', id_and_hash)
It's automatically setting the path to / so you don't have to worry about it (it does escape the values properly too).
Related
I'm using Python with the Django Rest framework and am trying to receive webhook events correctly from stripe.
However I constantly get this error:
stripe.error.SignatureVerificationError: No signatures found matching the expected signature for payload
This is the code:
WEBHOOK_SECRET = settings.STRIPE_WEBHOOK_SK
#csrf_exempt
def webhook(request):
sig_header = request.headers.get('Stripe-Signature', None)
payload = request.body
try:
event = stripe.Webhook.construct_event(
payload=payload,
sig_header=sig_header,
secret=WEBHOOK_SECRET
)
except ValueError as e:
raise e
except stripe.error.SignatureVerificationError as e:
raise e
return HttpResponse(status=200)
I have also tried modifying the request body format like so:
payload = request.body.decode('utf-8')
# and also
payload = json.loads(request.body)
And yet no luck.
The error is coming from the verify_header() class method inside the WebhookSignature class.
This is the part of the method where it fails:
if not any(util.secure_compare(expected_sig, s) for s in signatures):
raise error.SignatureVerificationError(
"No signatures found matching the expected signature for payload",
header,
payload,
)
So I printed out exptected_sig and signatures before this line and found that regardless of what format request.body is in, signatures is always there (which is good), but they never match the signature from the header.
Why is this?
When Stripe calculates the signature for the Event it sends you, it uses a specific "payload" representing the entire Event's content. The signature is done on that exact payload and any change to it such as adding a new line, removing a space or changing the order of the properties will change the payload and the corresponding signature.
When you verify the signature, you need to make sure that you pass the exact raw payload that Stripe sent you, otherwise the signature you calculate won't match the Stripe one.
Frameworks can sometimes try to be helpful when receiving a request and they detect JSON and automatically parse it for you. This means that you think you are getting the "raw payload/body" but really you get an alternate version. It has the same content but it doesn't match what Stripe sent you.
This is fairly common with Express in Node.js for example. So, as the developer, you have to explicitly request the exact raw/original payload Stripe sent you. And how to do this can differ based on a variety of factors. There are 2 issues on the stripe-node github with numerous potential fixes here and here.
With Django, the same can happen and you need to make sure that your code requests the raw payload. You seem to use request.body as expected but that's one thing you want to dig into further.
Additionally, another common mistake is using the wrong Webhook secret. If you use the Stripe CLI for example, it creates a new secret for you that is different from the one you see in the Dashboard for this Webhook Endpoint. You need to make sure you use the correct secret based on the environment you're in.
The Tornado RequestHandler class has add_header(), clear_header(), and set_header() methods. Is there a way to just see the headers that are currently set?
My use case is that I am writing some utility methods to automatically set response headers under certain conditions. But I want to add some error checking in order to not add duplicates of a header that I do not want to have duplicated.
I want to write come code that is more or less like this:
class MyHandler(tornado.web.RequestHandler):
def ensure_json_header(self):
if not self.has_header_with_key('Content-Type'):
self.set_header('Content-Type', 'application/json')
def finish_json(self, data):
self.ensure_json_header()
return self.finish(json.dumps(data))
But of course there is no has_header_with_key() method in Tornado. How can I accomplish this?
EDIT: this turned out to be an X-Y question. The real answer was to just use set_header instead of add_header. I am leaving this up for anyone else who might come along with a similar question.
There's no documented api for listing the headers present in a response.
But there is a self._headers private attribute (an instance of tornado.httputil.HTTPHeaders) which is basically a dict of all headers in the response. You can do this to check a header:
if 'Content-Type' in self._headers:
# do something
As an addendum, if you want to access all headers of a request, you can do self.request.headers.
Edit: I've opened an issue about this on github after seeing your question; let's see what happens.
Tornado will always have the Content-Type header set as it is in the default headers (https://www.tornadoweb.org/en/stable/_modules/tornado/web.html#RequestHandler.clear). So if you want to ensure you have a specific content type set, just call set_header.
If you want to check that the response does not have a header set in your code, you’ll have to first reset the default header, which you can do by implementing set_default_headers and do a clear_header(“Content-Type”) there.
But you could also achieve the same by setting a property on your handler (say override_content_type), set that in code and then do a non conditional set_header before rendering the result.
I have been experimenting with authentication on APIs and was looking to pass a token with the request that uniquely identifies the user.
I want to know why there would only be an encode function create_signed_value and no decode_signed_value or verify_signed_value.
Are you expected to set it in a cookie and use the get_secure_cookie although I'm struggling with actually setting it too?
UPDATE:
To decode a signed value created using create_signed_value, you can pass the signed value to the get_secure_cookie method (see docs):
signed_value = self.create_signed_value(name='auth', value='John Doe')
decoded_value = self.get_secure_cookie(name='auth', value=signed_value)
When I wrote the original answer, I was unaware of the API which I've mentioned above.
I am using QuickFix with Python. On the back of this question, I've explored the SessionID class a bit, but I am mystified by the behavior.
The SessionID class is described here. It is formed of a BeginString, SenderCompID and TargetCompID.
Say my SessionID in string form looks like this: FIX.4.2:LMXTS->TS68.
fix.SessionID().fromString() returns :->
Which if you look, are the three filler characters separating the BeginString, SenderCompID and TargetCompID.
fix.SessionID().getBeginString returns 8=☺ (i.e. the BeginString is nowhere). And the same thing applies to getSenderCompID and getTargetCompID, they return 49=☺ and 56=☺ respectively.
fix.SessionID().getTargetCompID().getValue() returns the empty string ''.
Trying another way, fix.SessionID().fromString('FIX.4.2:LMXTS->TS68') returns None.
I am trying to get these values after the session is created (which I can explicitly see happening when I pass fix.ScreenLogFactory(settings) to the initiator. So I am confused.
The method void onLogon( const SessionID& ) {} in Application.h is fired when the session is logged on, and gives you a reference to a SessionID. You could inspect the SessionID object inside onLogon to see how it behaves.
you can do it any of the quickfix methods after your session is created as the sesionId is one of the parameters.
The first method fired is onCreate so you can potentially store the sesionId in your class var and then reuse if if and when required to retrieve your settings. You can also use the onLogon method as suggested in one of the other answers.
Example below
def onCreate(self, sessionID):
self.session_id = sessionID
target = sessionID.getTargetCompID().getString()
sender = sessionID.getSenderCompID().getString()
It sounds like you're looking at the session directly after creating it, before logging on etc. So that means you're not using a breakpoint in, say, FromApp or ToApp to look at the session properties there. If you do, you get the properties directly i.e. SenderCompID, or TargetCompID.
I cannot find the method SessionID in the objects I use. How do you define your 'fix' object?
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
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.
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.