Why Django test returns bad status code? - python

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 '/'

Related

Python requests returns 200 instead of 301

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).

How do I test for 401 response to a post request in python?

I'm using a post request to access a website that requires authentication. If that authentication is incorrect, I get a Response [401]. I want to test if the authentication is incorrect and if so, abort the process and display an error of some sort. I don't know the syntax to test if the response is 401.
output = requests.post(cfg.get('HTTP', 'url'), data = query, verify=False, auth=HTTPBasicAuth(credentials['user'], credentials['pass']))
if output == '<Response [401]>':
sys.exit('Incorrect Authentication. Please try again.')
else:
sys.exit('manual stop1')
Instead of '<Response [401]>', I've also tried 'Response [401]', 'response [401]', '<Response[401]>', 'Response[401]', 'response[401]', '[401]', '401', and all of those without quotes.
I've seen some responses using flask and json, but I was hoping to not have to change how I'm requesting the data. Thank you!
You want the status_code attribute
if output.status_code == 401:
...
Or to avoid hard coding numbers:
if output.status_code == requests.status_codes.codes.UNAUTHORIZED:
....

Flask abort() with custom http code

I use Flask framework in my project with pure json api. It renders only json responses without html or static files.
I am trying to achieve abort() function with custom http code, in my case 204 (No Content) which isn't defined by default. I have currently code like:
# Error define
class NoContent(HTTPException):
code = 204
description = ('No Content')
abort.mapping[204] = NoContent
def make_json_error(ex):
response = jsonify(error=str(ex))
response.status_code = (ex.code
if isinstance(ex, HTTPException)
else 500)
return response
custom_exceptions = {}
custom_exceptions[NoContent.code] = NoContent
for code in custom_exceptions.iterkeys():
app.error_handler_spec[None][code] = make_json_error
# Route
#app.route("/results/<name>")
def results(name=None):
return jsonify(data=results) if results else abort(204)
It works well I get response like:
127.0.0.1 - - [02/Dec/2014 10:51:09] "GET /results/test HTTP/1.1" 204 -
But without any content. It renders nothing, not even blank white page in browser.
I can use errorhandler
#app.errorhandler(204)
def error204(e):
response = jsonify(data=[])
return response
But it returns 200 http code. In need 204 here. When I add in error204() line like:
response.status_code = 204
It renders nothing once again.
I am stuck and I have no idea where there is an error with this approach. Please help.
If my approach is wrong from design perspective please propose something else.
Thanks in advance.
Remember, HTTP 204 is "No Content". RFC 7231 (and RFC 2616 before it) requires that user-agents ignore everything after the last header line:
The 204 (No Content) status code indicates that the server has successfully fulfilled the request and that there is no additional content to send in the response payload body ... A 204 response is terminated by the first empty line after the header fields because it cannot contain a message body.
~ RFC 7231 (emphasis mine)
The 204 response MUST NOT include a message-body, and thus is always terminated by the first empty line after the header fields.
~ RFC 2616
You need to return the status code in the error handler.
#app.errorhandler(204)
def error204(e):
response = jsonify(data=[])
return response, 204
Leaving off the status code is interpreted as 200 by Flask.

Does requests.codes.ok include a 304?

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.
"""

Testing for 400 errors with paste on a web.py app

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!

Categories