I'm going through the RESTful web services chapter of the Flask web development book by Miguel Grinberg and he mentions that errors can be generated by Flask on its own or explicitly by the web service.
For errors generated by Flask, he uses a error handler like the following:
#main.app_errorhandler(404)
def page_not_found(e):
if request.accept mimetypes.accept_json and \
not request.accept_mimetypes.accept_html:
response = jsonify({'error': 'not found'})
response.status_code = 404
return response
return render_template('404.html'), 404
While errors generated by the web service, have no error handler:
def forbidden(message):
response = jsonify({'error': 'forbidden', 'message': message})
response.status_code = 403
return response
I don't really understand the difference between a flask generated error vs a web service generated error.
The first is an example of how to make a custom handler for an error that Flask will raise. For example, it will raise a 404 error with a default "not found" message if it doesn't recognize the path. The custom handler allows you to still return the 404 error, but with your own, nicer looking response instead.
The second is an example of how to change the code for your response, without handling a previously raised error. In this example, you would probably return forbidden() from another view if the user doesn't have permission. The response would have a 403 code, which your frontend would know how to handle.
Related
I am using standard error handling in production - if there are server errors I am getting mails.
However, on certain APIs I want to have a response with HTTP code 500 or 502 as part of the "valid flow". (It's done for educational purposes)
So my view for that looks like this:
from rest_framework.response import Response
from rest_framework import status
def give_me_error(request):
return Response("This is expected error", status=status.HTTP_500_INTERNAL_SERVER_ERROR)
And what I want is not to get email of this particular response (because I wanted it to be 500)
I've also tried this way:
from django.http import JsonResponse
def give_me_error(request):
return JsonResponse({'error': 'expected error'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
But it also generates mail.
Is there a way to have a view returning error 500 that will not trigger e-mail send? (without disabling the e-mail functionality system-wide)
Per Django documentation: https://docs.djangoproject.com/en/4.0/howto/error-reporting/
When DEBUG is False, Django will email the users listed in the ADMINS setting whenever your code raises an unhandled exception and results in an internal server error (strictly speaking, for any response with an HTTP status code of 500 or greater)
Write now my code is able to successfully send a post request to the Django REST API which in result triggers the spider respectively and stores its output to the database successfully. For this cause I am using scrapyd API as you can see in the below code snippet
#api_view(['POST'])
#permission_classes((permissions.AllowAny,))
def crawlRottenTomatoes(request):
print("in crawl tottentomatoes method")
url = request.data["url"]
if not url:
return JsonResponse({'error': 'Missing args'})
if not is_valid_url(url):
return JsonResponse({'error': 'URL is invalid'})
domain = urlparse(url).netloc
msg_dic = {}
try:
scrapyd.schedule(project="movie_spider", spider="rottentomatoes", url=url, domain=domain)
msg_dic['msg'] = "Spider RottenTomatoes for given url is up and running"
except Exception as e:
print("exception")
msg_dic['error'] = "Error running spider for RottenTomatoes"
return JsonResponse(msg_dic, safe=False)
But now what I want. Is to have some kind of response back from the scrapyd when it's done crawling and parsing the website/channel for that I came across the WebSockets. I tried to use WebSockets but the problem is scrapyd is a demon itself. I am not really able to send a message to the WebSocket client from the scrappy. Does anyone have any idea of how do to do or can share some resources which can help me with this?
Looking at the API reference, it seems the only way to get the status of a scrapyd job is via listjobs https://scrapyd.readthedocs.io/en/stable/api.html#listjobs-json and looking for your job's id in the list.
Another option is to monitor scrapyd's log file. Or you could also try to add this feature to https://github.com/scrapy/scrapyd where it would send an http request after it's done with a job.
I got question about implementing google login. I was able to implement Google Login button on my react app using an open source library called react-google-login. I was able to set up the backend server using python flask. I host my api method on the api on Heroku: http://arrangement-server.herokuapp.com/login.
And my react app runs successfully locally, and I am able to use login-in button. But, my issue is that my server displays the following error:
Method not Allowed.
Is this because it is post method?
Why is it my Server shows me that that method is not allowed?
Even though on the client side it runs fine, and I am able to see user profile and user information.
Here's the code to my backend server, you can find it at Github:
#app.route("/login", methods=['POST'])
def login():
data = request.json
session['access_token'] = data['access_token'], ''
return jsonify({'message':'You are logged in.'})
Your "login" endpoint will accept only "POST" HTTP requests. Because of this line:
#app.route("/login", methods=['POST'])
When you try to open your page in a browser - the browser will send the "GET" HTTP request to that URL.
That is why you are getting "Method Not Allowed" error.
Take a look at my answer on upwork for more details.
Your heroku server is only a backend server.
And the route "/login" accepts only POST request.
So you can't send the GET request to this route on web browser.
If you want to look at the response with this route, you can send the POST request by using POSTMAN.
I think this part
#app.route("/")
def home_page():
access_token = session.get('access_token')
if access_token is None:
return redirect(url_for('login'))
Always force user to visit login page with GET method. Unfortunately you don't have method and route defined to handle this GET method.
I am developing with google appengine sdk and python, I'm trying to incorporate my twiiter app
import tweepy
TWITTER_CONSUMER_KEY = 'XXXXXXXXXXX'
TWITTER_CONSUMER_SECRET = 'xxxxxxxxxx'
auth = tweepy.OAuthHandler(TWITTER_CONSUMER_KEY,TWITTER_CONSUMER_SECRET)
but it does not work, return the following error
in get_authorization_url
raise TweepError(e)
TweepError: HTTP Error 401: Unauthorized
The problem is that this error is generated locally, but the upload my application on the web, works perfectly
I started digging into the Tweepy code and the error returned was this:
Desktop applications only
support the oauth_callback value \'oob\'
I got around it by setting a callback url in my application. I set mine to 127.0.0.1 and that seems to have fixed it.
In my Flask app, I set up a 404 handler like this:
#app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404
However, when a user goes to an unrecognized URL, the system gives an internal server error instead of rendering my 404 template. Am I missing something?
Internal Server Error is HTTP error 500 rather than 404 and you haven't added error handler for it. This occurs when the server is unable to fulfill the client request properly. To add a gracious message when such error occurred, you can add a errorhandler like 404.
#app.errorhandler(500)
def exception_handler(e):
return render_template('500.html'), 500
There is likely an issue while rendering the 404 template which then triggers an internal server error.
I suggest checking the logs for your app.
This will also occur if you have debug set to true. Try setting debug to false and see if your custom 404 shows up then.