Flask Error: If something fails in the flask backend, how does the error propagate to the front end? - api

Consider a simple application where a user fills a form to divide two numbers, in the routes the form data is proceeded [made into float] and then passed as parameters to a python script's function that has the division logic.
The logic fails due to division by 0 is handled as a custom message in the terminal. How does one send this custom message back to the front end UI along with a 500 error message? Trying to make a restful flask app here.
So far I can abort and show a custom message but not the one that propagated from the backend. Also looked into custom error handling but I want to writer of the external python script to be able to write the custom message.

You can Flask errorhandler(errorcode) to manage your errors and display those on the frontend.
#app.errorhandler(500)
def code_500(error):
return render_template("errors/500.html", error=error), 500
You can put whatever else you want in the html template.
You can also call the code_500(error) func directly.
Same principle applies for any other HTTP error code if you want to customize the page and the message (401, 403, 404, etc...).
If you're inside a blueprint, you can use app_errorhandler instead.

You could use the abort() function. From the docs:
When using Flask for web APIs, you can use the same techniques as above to return JSON responses to API errors. abort() is called with a description parameter. The errorhandler() will use that as the JSON error message, and set the status code to 404.
You could implement it like this
#app.route("/div")
def divide():
x, y = request.form['x'], request.form['y']
try:
result = x / y
except ZeroDivisionError:
abort(400, description="Your message here")
else:
# Proper response
From there, the important step is properly catching that message on your frontend.

Related

How to stop further routing in a plug?

I'm using Phoenix, and in router.ex, I have defined a function that verifies the user's JWT token, before continuing on to routing through the api, in order to protect the routes. However, I am having the issue that if, say, I return a status of 403 in the plug, it continues routing and I end up getting an error as I am both accessing the route and disallowing access.
My code looks something like this:
def validate(conn, _opts) do
if !Map.has_key?(conn.cookies, "jwt") do
conn
|> send_resp(403, "Forbidden")
# I would like to have something here that stops further
# routing - i.e. a way to say 'already sent a response; don't keep going'
end
end
Here is an excerpt from Plug.Conn.send_resp/3
Note that this function does not halt the connection, so if subsequent plugs try to send another response, it will error out. Use halt/1 after this function if you want to halt the plug pipeline.

Insert Record to BigQuery or some RDB during API Call

I am writing a REST API GET endpoint that needs to both return a response and store records to either GCP Cloud SQL (MySQL), but I want the return to not be dependent on completion of the writing of the records. Basically, my code will look like:
def predict():
req = request.json.get("instances")
resp = make_response(req)
write_to_bq(req)
write_to_bq(resp)
return resp
Is there any easy way to do this with Cloud SQL Client Library or something?
Turns our flask has a functionality that does what I require:
#app.route("predict", method=["GET"]):
def predict():
# do some stuff with the request.json object
return jsonify(response)
#app.after_request
def after_request_func(response):
# do anything you want that relies on context of predict()
#response.call_on_close
def persist():
# this will happen after response is sent,
# so even if this function fails, the predict()
# will still get it's response out
write_to_db()
return response
One important thing is that a method tagged with after_request must take an argument and return something of type flask.Response. Also I think if method has call_on_close tag, you cannot access from context of main method, so you need to define anything you want to use from the main method inside the after_request tagged method but outside (above) the call_on_close method.

unable to use 'call' method in lagom

I am experimenting with Lagom to check how call, pathCall and namedCall are invoked. I am following lagom's tutorial. I created a new service and opened url using following urls but I get error
URL used (I expect to see hello2 response)
http://localhost:9000/
Error
GET\Q/stream\EService: hello-stream (http://0.0.0.0:58322)
2GET\Q/api/hello/\E([^/]+)Service: hello (http://0.0.0.0:57797)
3POST\Q/api/hello/\E([^/]+)Service: hello (http://0.0.0.0:57797)
**4POST\Q/hello2\EService: hello (http://0.0.0.0:57797)**
I have done following steps
After downloading template (see https://www.lagomframework.com/documentation/1.3.x/scala/IntroGetStarted.html), I have changed the code to add a new service call (called hello2). Following is teh code I have added in HelloService.scala
named("hello")
.withCalls(
pathCall("/api/hello/:id", hello _),
pathCall("/api/hello/:id", useGreeting _),
call(hello2) //added this line in default template.
)
I have defined hello2 as (in HelloService.scala)
def hello2: ServiceCall[String, String]
The code in HelloServiceImpl.scala is
override def hello2 = ServiceCall {
Future.successful("Hello2")
}
Questin 1 - What is the mistake (I guess I am not invoking the service correctly from the browser)?
When you say, "I guess I am not invoking the service correctly from the browser", do you mean you're just navigating to the URL in your browser? If so, this won't work because hello2 is defined as a POST endpoint and your browser will be sending a GET request.
hello2 is defined as a POST endpoint because in your ServiceCall definition it takes a request message. (See https://www.lagomframework.com/documentation/1.3.x/java/ServiceDescriptors.html for more info.)
If you change the request message type from String to NotUsed then Lagom should start generating a GET endpoint instead.

Where is a Response transformed into one of its subclasses?

I'm trying to write a downloader middleware that ignores responses that don't have a pre-defined element. However, I can't use the css method of the HtmlResponse class inside the middleware because, at that point, the response's type is just Response. When it reaches the spider it's an HtmlResponse, but then it's too late because I can't perform certain actions to the middleware state.
Where is the response's final type set?
Without seeing your code of the middleware it is hard to tell what the matter is.
However my middleware below gets an HtmlResponse object:
class FilterMiddleware(object):
def process_response(self, request, response, spider):
print response.__class__
print type(response)
return response**strong text**
Both print statements verify this:
<class 'scrapy.http.response.html.HtmlResponse'>
<class 'scrapy.http.response.html.HtmlResponse'>
And I can use the css method on the response without any exception. The order of the middleware in the settings.py does not matter either: with 10, 100 or 500 I get the same result as above.
However if I configure the middleware to 590 or above I get plain old Response object. And this is because the conversion happens in the HttpCompressionMiddleware class on line 35 in the current version.
To solve your issue order your middleware somewhere later on the pipeline (with a lower order number) or convert the response yourself (I would not do this however).

Change User Agent and Headers in pyWebkitGTK?

I've read the suggestions for making your own data handler, for example:
web_view.connect('resource-request-starting', resource_cb)
def resource_cb(view, frame, resource, request, response):
print request.get_uri()
#get data using urllib with different user-agent...
request.set_uri('data:....')
(from http://code.google.com/p/pywebkitgtk/wiki/HowDoI)
will let you download using custom header/useragent. However, sometimes it will complain if set_uri is given string with null-char, or it will give an error like "** Message: console message: (http://url) #linenumber: SECURITY_ERR: DOM Exception 18: An attempt was made to break through the security policy of the user agent."
Is there a better way to set a browser useragent for pygtk code? This says you can add/remove/replace headers using SoupMessage, however that documentation is missing...
This code sets a special user-agent:
http://nullege.com/codes/show/src%40p%40r%40PrisPy-HEAD%40PrisPy.py/33/webkit.WebView/python
webkit.WebSettings() allows user-agent switching, and a few other settings, but it seems it doesn't have the option to add other headers.