I have a program which uses the requests module to send a get request which (correctly) responds with a 304 "Not Modified". After making the request, I check to make sure response.status_code == requests.codes.ok, but this check fails. Does requests not consider a 304 as "ok"?
There is a property called ok in the Response object that returns True if the status code is not a 4xx or a 5xx.
So you could do the following:
if response.ok:
# 304 is included
The code of this property is pretty simple:
#property
def ok(self):
try:
self.raise_for_status()
except HTTPError:
return False
return True
You can check actual codes in the source. ok means 200 only.
You can check the implementation of requests.status code here source code.The implementation allows you to access all/any kind of status_codes as follow:
import requests
import traceback
url = "https://google.com"
req = requests.get(url)
try:
if req.status_code == requests.codes['ok']: # Check the source code for all the codes
print('200')
elif req.status_code == requests.codes['not_modified']: # 304
print("304")
elifreq.status_code == requests.codes['not_found']: # 404
print("404")
else:
print("None of the codes")
except:
traceback.print_exc(file=sys.stdout)
In conclusion, you can access any request-response like demonstrated. I am sure there are better ways but this worked for me.
.ok "..If the status code is between 200 and 400, this will return True."
mentioned in source code as:
"""Returns True if :attr:status_code is less than 400, False if not.
This attribute checks if the status code of the response is between
400 and 600 to see if there was a client error or a server error. If
the status code is between 200 and 400, this will return True. This
is not a check to see if the response code is 200 OK.
"""
Related
url = "https://www.avito.ma/fr/2_mars/sacs_et_accessoires/Ch%C3%A2les_en_Vrai_Soie_Chanel_avec_boite_38445885.htm"
try
r = requests.get(url,headers={'User-Agent': ua.random},timeout=timeout) # execute a timed website request
if r.status_code > 299: # check for bad status
r.raise_for_status() # if confirmed raise bad status
else:
print(r.status_code, url) # otherwise print status code and url
except Exception as e:
print('\nThe following exception: {0}, \nhas been found found on the following post: "{1}".\n'.format(e,url))
Expected status = 301 Moved Permanently
You can visit the page or check http://www.redirect-checker.org/index.php with the url for a correct terminal print.
Returned status = 200 OK
The page has been moved and it should return the above 301 Moved Permanently, however it returns a 200. I read the requests doc and checked all the parameters (allow_redirects=False etc.) but I don't think it is a mistake of configuration.
I am puzzled at why requests wouldn't see the redirects.
Any ideas?
Thank you in advance.
Python Requests module has the allow_redirect parameter in True by default. I've tested it with False and it gives the 301 code that you're looking for.
Note after reading your comment above: r.history saves each response_code before the one that you're right now which is saved in r.status_code (only if you leave the parameter in True).
What is the easiest way to check whether the response received from a requests post was "200 OK" or an error has occurred?
I tried doing something like this:
....
resp = requests.post(my_endpoint_var, headers=header_var, data=post_data_var)
print(resp)
if resp == "<Response [200]>":
print ('OK!')
else:
print ('Boo!')
The output on the screen is:
Response [200] (including the "<" and ">")
Boo!
So even though I am getting a 200, my check in the if statement is somehow not matching?
According to the docs, there's a status_code property on the response-object. So you can do the following:
if resp.status_code == 200:
print ('OK!')
else:
print ('Boo!')
EDIT:
As others have pointed out, a simpler check would be
if resp.ok:
print ('OK!')
else:
print ('Boo!')
if you want to consider all 2xx response codes and not 200 explicitly.
You may also want to check Peter's answer for a more python-like way to do this.
Just check the response attribute resp.ok. It is True for all 2xx responses, but False for 4xx and 5xx. However, the pythonic way to check for success would be to optionally raise an exception with Response.raise_for_status():
try:
resp = requests.get(url)
resp.raise_for_status()
except requests.exceptions.HTTPError as err:
print(err)
EAFP: It’s Easier to Ask for Forgiveness than Permission: You should just do what you expect to work and if an exception might be thrown from the operation then catch it and deal with that fact.
Much simpler check would be
if resp.ok :
print ('OK!')
else:
print ('Boo!')
Since any 2XX class response is considered successful in HTTP, I would use:
if 200 <= resp.status_code <= 299:
print ('OK!')
else:
print ('Boo!')
I'm surprised no one has mentioned this so:
If you want to check for exactly a 200 response:
if resp.status_code == requests.codes.ok:
The status_code of a response contains the HTTP status returned.
requests.codes.ok is exactly 200.
If you want to check if the status code is "ok", and not an error:
if resp.ok:
The ok attribute of a response checks that the status code of the response is less than 400.
Make sure you know what it is you want to check, for example a 201 HTTP Created is a successful response that you would be omitting if you only check for exactly 200.
resp.status_code will return the status code as an integer.
See http://docs.python-requests.org/en/master/
try:
if resp.status_code == 200:
print ('OK!')
else:
print ('Boo!)
In easy case:
import requests
response = requests.get(url)
if not response:
#handle error here
else:
#handle normal response
My question is closely related to this one.
I'm using the Requests library to hit an HTTP endpoint.
I want to check if the response is a success.
I am currently doing this:
r = requests.get(url)
if 200 <= response.status_code <= 299:
# Do something here!
Instead of doing that ugly check for values between 200 and 299, is there a shorthand I can use?
The response has an ok property. Use that:
if response.ok:
...
The implementation is just a try/except around Response.raise_for_status, which is itself checks the status code.
#property
def ok(self):
"""Returns True if :attr:`status_code` is less than 400, False if not.
This attribute checks if the status code of the response is between
400 and 600 to see if there was a client error or a server error. If
the status code is between 200 and 400, this will return True. This
is **not** a check to see if the response code is ``200 OK``.
"""
try:
self.raise_for_status()
except HTTPError:
return False
return True
I am a Python newbie but I think the easiest way is:
if response.ok:
# whatever
The pythonic way to check for requests success would be to optionally raise an exception with
try:
resp = requests.get(url)
resp.raise_for_status()
except requests.exceptions.HTTPError as err:
print(err)
EAFP: It’s Easier to Ask for Forgiveness than Permission: You should just do what you expect to work and if an exception might be thrown from the operation then catch it and deal with that fact.
I'm testing my Django API and I have a simple test that looks like this:
def test_owner_is_refused_when_not_logged(self):
resp = self.client.get('/api2/get_owner_infos')
self.assertEqual(resp.status_code, 401)
However, the test fails because the status code in the test is 301 so I get a AssertionError: 301 != 401 error.
Yet, when I do http://my-local-server/api2/get_owner_infos I get a 401 HTTP response.
What's wrong with my test?
Thanks.
resp = self.client.get('/api2/get_owner_infos/')
pls check where the url endswith '/'
I'm using paste to do some functional testing on my 'controllers' in my web.py app. In one case I'm trying to test for a 400 response when a malformed post is made to an API endpoint. Here is what my test looks like:
def test_api_users_index_post_malformed(self):
r = self.testApp.post('/api/users', params={})
assert r.header('Content-Type') == 'application/json'
assert r.status == 400
But I'm getting the following exception:
AppError: Bad response: 400 Bad Request (not 200 OK or 3xx redirect for /api/users)
I see paste has HttpException middleware, but I can't find any examples on how to use it or if its even the right way to go. Any suggestions? Or am I just going about this wrong?
I know I'm tardy to the party, but I ran across this searching for the answer to the same issue. To allow the TestApp to pass non 2xx/3xx responses back you need to tell the request to allow "errors".
def test_api_users_index_post_malformed(self):
r = self.testApp.post('/api/users', params={}, expect_errors=True)
assert r.header('Content-Type') == 'application/json'
assert r.status == 400
Happy Hacking!