Intercept static routes in a falcon app does not work - python

I am creating a falcon app which has many endpoints. Just like this [example][1] I want to add a function to call before every request to send to some data. I have followed their examples, however they don't work for me if the route has been added already. For example if I call endpoint /test and it is added by add_route it wont work, but if not it will work fine. I am wondering is there any other example then the two explained in the example. At the moment I am creating it in the following way.
middleware_list = [utils.FuncMiddleware(hook) for hook in
utils.before_hooks()]
middleware_list.append(middlewares.RequireJSON())
middleware_list.append(middlewares.JSONTranslator())
tve_app = falcon.API(middleware=middleware_list)
for exception_class in tveapi_exc.exception_handlers_catalog:
tve_app.add_error_handler(exception_class, exception_class.handle)
endpoint_catalog = [
('/v1', v1.public_endpoints()),
('/apps', apps.public_endpoints()),
]
for version_path, endpoints in endpoint_catalog:
for route, resource in endpoints:
#tve_app.add_sink(request_notifier, version_path + route)
tve_app.add_route(version_path + route, resource)
The other option is to add decorator before every function but this involves a lot of code re-writing. Or maybe the problem is that it is integrated with apache. Any ideas where to continue on?
[1]: How can I intercept static routes in a falcon app?

Related

Is there a better way to use rollbar error reporting with flask?

I just came across rollbar and wanted to include it in my Python project.
This is the standard way in which I am told to implement rollbar from the website.
import rollbar
rollbar.init('KEY')
try:
a = s
except:
rollbar.report_exc_info()
Is there a better way to implement this without going through all my try except blocks and replacing them with rollbar.report_exc_info()
Can there be a decorator implementation for this?
My current project is a Flask app that provides API's to end users.
Here's an example for rollbar integration in Flask apps.
https://github.com/rollbar/rollbar-flask-example/blob/master/hello.py
#app.before_first_request
def init_rollbar():
"""init rollbar module"""
rollbar.init(
# access token for the demo app: https://rollbar.com/demo
'fc316ac1f7404dc28af26d5baed1416c',
# environment name
'flasktest',
# server root directory, makes tracebacks prettier
root=os.path.dirname(os.path.realpath(__file__)),
# flask already sets up logging
allow_logging_basic_config=False)
# send exceptions from `app` to rollbar, using flask's signal system.
got_request_exception.connect(rollbar.contrib.flask.report_exception, app)

Flask/Werkzeug equivalence of web.py app.request()

I'm porting an app from web.py to Flask, mainly because web.py support for Python 3 is spotty and there seems to be less and less interest in web.py.
But what I can't find in Flask/Werkzeug is a way to use the router to do dispatching of internal requests within my application. The app is structured such that there will be a lot of intra-application calls, and in web.py I handle these more or less as follows:
app = web.application(....)
def callUrl(url, method, env, data):
parserUrl = url lib.parse.urlparse(url)
if parsedUrl.scheme == '' and parsedUrl.netloc == '':
# local call
res = app.request(url, method=method, data=data, env=env)
...
else:
assert env == {}
res = requests.request(url, method=method, data=data)
....
I am trying to find a way to do something similar with Flask, but apparently I am looking in the wrong places. Can someone point me in the right direction?
Ok, answering my own question. The solution I chose was to basically re-implement app.request from web.py by filling an environ dictionary with all the required WSGI variables (REQUEST_METHOD, PATH_INFO, etc), including wsgi.input as an io.BytesIO() object that feeds the correct data into the WSGI app.
Then I created a suitable start_response() method to save the headers, and called
resultData = app.wsgi_app(environ, start_response)
The flask app goes through all the motions of pushing requests and environments and does all the routing, and I get the returned data back in resultData (and the headers with any errors and such have been passed to my start_response method).

Angular router not engaging with Flask server using ng build

When using Angular 5 with Flask and ng build --aot --watch, I am having major issues getting Angular's routing and refreshing the page to work.
I have come across many attempts to fix this, but none of them when applied to my project work (and the example projects provided when I try it there also do not seem to work).
What happens (depending on the thing I try) are these:
It can't find the path at all and I get a Jinja2 error
It can't find the document for localhost:5015/ (the port I'm using) and I get a 404 and a white screen
It loads index.html, but upon refresh it gets a 404 (implying that the browser is attempting to fetch the page from the server, not using the Angular routing system)
I get the same issue as this one: Syntax Error in Angular App: Unexpected token <
I am under the impression this is a normal issue with all SPAs and that the solution is to always redirect the server to index.html. We have done this (AFAIK), and attempted multiple ways to do this:
Our structure is roughly the following:
- ProjectDir
- reverseProxy_Calls
- scripts
- swagger_yaml_definitions
- templates
- e2e
- dist
- src
- app
And our server.py contains this (among other stuff)
Swagger(app)
app.template_folder = "./templates/dist/"
app.static_folder = "./templates/dist/"
app.static_path = "./templates/dist/"
app.static_url_path = "./templates/dist/"
app.instance_path = "./templates/dist/"
config = settings.config()
config.read("settings.cfg")
#app.route('/', defaults={'path': ''}, methods=['GET', 'POST'])
#app.route('/<path:path>', methods=['GET', 'POST'])
def get_resource(path): # pragma: no cover
# If we are devmode, proxy through flask.
if config.getKey("devmode") == True:
url = "http://localhost:%s/%s" % (config.getKey('ng_port'), path)
j = requests.get(url, stream=True, params=request.args)
return make_response(j.text)
# return the results
# return render_template('dist/index.html')
# return app.send_static_file("index.html")
return send_from_directory('dist/', path)
if __name__ == '__main__':
app.run(debug=True, port=int(config.getKey("port"))) # , host='0.0.0.0')
^ A variety of ways here show various attempts to handle this.
I have also looked at and tried projects that use variations of the following:
Flask Cli
Flask-Script
Flask-Bootstrap
None of them have solved this problem when I have tried them.
I have been told that using the hashRoute location strategy in Angular rather than the History PushState strategy will also work, however when I attempted to do that it had the same behavior of losing the page upon refresh (additionally we wish to use server side rendering in the future, and hashRoute location strategy prevents this possibility, among many other downsides).
Possibly related is that Flask seems to reload or re-render the page when it does find the index.html and routes initially, wiping anything printed to the browser dev console. I have seen this in some of the flask examples, but not all, and I'm uncertain what causes this.
When running via ng serve --aot --prod, things work exactly correctly and as expected. It's only when serving via Flask that things break down.
Apologies for the long question and thank you for your time in advance.
I am under the impression this is a normal issue with all SPAs and
that the solution is to always redirect the server to index.html. We
have done this (AFAIK), and attempted multiple ways to do this
You also need to redirect all HTTP errors to index.html.

flask how to log all warning exceptions (full stack trace) to file

So I am trying to build a restful API using flask, served up by apache on centos (httpd).
Basic API calls work just fine but I am not making much progress on the more advanced aspects because every time it fails I just get an HTTP 500 response which is completely useless for troubleshooting and I have no server-side logs to look at. I am literally trying to solve this through trial and error and it is making me bang my head against the wall.
In order to make any progress on this project I need to setup some basic error logging, but I do not understand the documentation or existing threads about this. It is completely over my head.
What I want to do is have flask write out all warnings and exceptions generated by my application to a specific file (it can be in the app directory to keep it simple).
I am looking for the simplest, easiest, least mind bendy way of doing this... suggestions?
Here is a very simplified version of my app... it shows the basic structure I am using, so please use that for reference.
from flask import Flask, jsonify, request
from flask_restful import reqparse, abort, Resource, Api
app = Flask(__name__)
api = Api(app)
class fetchTicket(Resource):
def post(self):
request_data = request.get_json(force=True)
r_ticket_id = request_data['ticket_id']
return jsonify(ticket_id=r_ticket_id)
api.add_resource(fetchTicket, '/ticket/fetch')
if __name__ == "__main__":
import logging
from logging.handlers import FileHandler
app.debug = True
file_handler = FileHandler("/var/www/project_folder/error.log")
file_handler.setLevel(logging.DEBUG)
app.logger.addHandler(file_handler)
app.run()
But when I run the above code no error.log file is created. I am not sure what I am doing wrong.
Note: I did set the folder permissions so that the apache user has access to write to the directory where the log file should go, as per http://fideloper.com/user-group-permissions-chmod-apache but it did not help so I don't think it is a permissions issue.
You’ll need to explicitly include the stack trace when logging, using the extra kwarg.
logger.exception('Probably something went wrong', extra={'stack': True})

Deploy multiple web services, i.e. multiple wsdl files, in python

I'm creating web services in python using Spyne based on this example. However, all my services are combined into one wsdl file locating at http://localhost:8000/?wsdl. I'm looking for another way to deploy each web service separately in a single wsdl file, e.g.
http://localhost:8000/service1/?wsdl and http://localhost:8000/service2?wsdl
Spyne has a WsgiMounter class for this:
from spyne.util.wsgi_wrapper import WsgiMounter
app1 = Application([SomeService], tns=tns,
in_protocol=Soap11(), out_protocol=Soap11())
app2 = Application([SomeOtherService], tns=tns,
in_protocol=Soap11(), out_protocol=Soap11())
wsgi_app = WsgiMounter({
'app1': app1,
'app2': app2,
})
Now you can pass wsgi_app to the Wsgi implementation that you're using the same way you'd pass a WsgiApplication instance.
Your Wsgi implementation also would definitely have a similar functionality, you can also use that in case e.g. you need to serve something for the root request instead of an empty 404 request.
An up-to-date fully working example can be found at: https://github.com/plq/spyne/blob/master/examples/multiple_protocols/server.py
Please note that you can't use one Service class with multiple applications. If you must do that, you can do it like this:
def SomeServiceFactory():
class SomeService(ServiceBase):
#rpc(Unicode, _returns=Unicode)
def echo_string(ctx, string):
return string
return SomeService
and use the SomeServiceFactory() call for every Application instance.
e.g.
app1 = Application([SomeServiceFactory()], tns=tns,
in_protocol=Soap11(), out_protocol=Soap11())
app2 = Application([SomeServiceFactory()], tns=tns,
in_protocol=Soap11(), out_protocol=Soap11())
Hope that helps.

Categories