Serve static files with Eve - python

I am running Flask and Eve on localhost at a same time. The Flask app serves static files and makes requests to the Eve app to get some data. I want to run Eve only, without a separate Flask app. How can I serve static files with Eve?

A better approach will be to prefix the /api for all REST APIs. This can be done by adding URL_PREFIX="api" in settings.py.
By doing this whenever there is request to /, Eve(Flask) will not return the resource catalog instead returns the page as given in run.py.
To serve static content add route decorators accordingly in run.py,
#app.route('/')
def index():
return app.send_static_file('index.html')
app.run(host="0.0.0.0", debug=True)

Eve is a Flask application (a subclass) so as a general rule everything that works with Flask works with Eve too. You could register a blueprint, or add new routes.
Also see this answer for a link to a working example: Servicing html requests with Eve

try set import_name arg for Eve:
app = Eve(import_name=__name__)

Related

Proper way to serve React frontend with Flask-RestX?

I'm trying to make a website where the APIs are defined with Flask-RestX and the React frontend can use those APIs. However, with the code below, and after running FLASK_APP=app.py flask run --host=0.0.0.0 --port=8000, the server won't return the index.html. I just get 404s. If I remove the doc="/documentation", then the / page becomes the swagger documentation. What should I do here?
from flask import Flask, send_from_directory
from flask_restx import Resource, Api
from .src.endpoints.endpoints import Endpoints
app = Flask(__name__, static_folder="frontend/build")
api = Api(app,
title="app",
version="v0.1",
doc="/documentation")
api.add_resource(Endpoints, "/endpoints")
#app.route("/")
def index():
return send_from_directory(app.static_folder,'index.html')

Flask building urls for api and view

I am writing a flask application with angularjs frontend. Templates aren't rendered from flask yet, they are delivered as static files. My api endpoint is as following:
#route('/projects', method=['GET'])
def rest_projects(self):
"""TODO: CRUD operation
"""
Project = Model.get('project.project')
return jsonify([project.serialize() for project in Project.search([])])
url_for works perfect with above endpoint but is there any way it can build urls for js templates also?. Say if url has api prefixed ie: /api/tasks, it comes to this handler otherwise deliver template. Right now I am using nginx to achieve that but is there anything wrong in my design which is restricting me to do this from flask only.
Flask is not intended to serve static files and you are better off keeping your files served by nginx for performance reasons. You can serve static files however using send_static_file() or send_from_directory methods.
http://flask.pocoo.org/docs/0.10/api/

Inheriting configuration from parent app in Flask

I have an application that is constructed as follows:
app = Flask(__name__)
app.wsgi_app = DispatcherMiddleware(frontend.create_app(), {
'/api': api.create_app()
})
app.config['DATABASE'] = db
I want to access the same database in both the frontend and api apps, but when I run something like current_app.config['DATABASE'] in Blueprints registered to api, that raises KeyError: 'DATABASE'. Is it possible to inherit configurations so that tests, etc. need only modify the top-level abstraction? Thanks.
Simply change your create_app methods on frontend and api to take a configuration dictionary and use flask.Config to create a configuration with all the properties of app.config (loadable from environmental variables, etc.):
from flask import Config
from werkzeug.wsgi import DispatcherMiddlware
config = Config()
config.from_envvar("YOUR_PROGRAM_CONFIG")
app = DispatcherMiddlware(frontend.create_app(config), {
'/api': api.create_app(config)
})
Then you can merge the provided config with each of your app's configurations:
def create_app(config):
app = Flask(__name__)
app.config.update(config)
# Potentially, load another config
app.config.from_envvar("YOUR_PROGRAM_CONFIG_FRONTEND", silent=True)
return app
Note that there is no need to create an app to route to other apps - the dispatcher middleware can already do that for you.
Also note that if you are already using blueprints it may make more sense to simply ship the blueprints and compose them on a single application, rather than using dispatcher middleware (depending, of course on how complex your apps are).

With Flask, how can I serve robots.txt and sitemap.xml as static files? [duplicate]

This question already has answers here:
Static files in Flask - robot.txt, sitemap.xml (mod_wsgi)
(10 answers)
Closed 8 years ago.
I've read on quiet a few places that serving static files should be left to the server, for example in a couple of the answers on this SO question. But I use the OpenShift PaaS, and can't figure out how to modify the .htaccess file there.
I came across this piece of code that serves the sitemap from a template. I did that on my app for both the sitemap, and robots.txt, like so -
#app.route("/sitemap.xml")
def sitemap_xml():
response= make_response(render_template("sitemap.xml"))
response.headers['Content-Type'] = 'application/xml'
return response
#app.route("/robots.txt")
def robots_txt():
return render_template("robots.txt")
Is there any harm in this, or is my approach okay?
Put robots.txt and sitemap.xml into your app's static directory and define this view:
from flask import Flask, request, send_from_directory
#app.route('/robots.txt')
#app.route('/sitemap.xml')
def static_from_root():
return send_from_directory(app.static_folder, request.path[1:])
Flask has built in support for serving static files.
Make a /static directory and put your files there. Then, when you instantiate Flask, specify the static_url_path parameter:
app = Flask(__name__, static_url_path='/')
The default is to serve static files from the /static/ path, but you want them served from / so they are where expected.
See the Flask API Docs for more info.
In addition to overhead and unnecessary code, the problem with your approach is if / when one of the files you want to serve contains something that looks like a template tag to render_template -- you can cause a rendering error. If you were to read the file into memory (once, not inside the method) then use that string as the body of the response without calling render_template, you would at least avoid that problem.
The best way is to set static_url_path to root url
from flask import Flask
app = Flask(__name__, static_folder='static', static_url_path='')

Flask app that routes based on subdomain

I want to have my top-level domain as a portal for various subdomains that correspond to different sections of my site. example.com should route to a welcome.html template. eggs.example.com should route to an "eggs" subsection or application of the site. How would I achieve this in Flask?
#app.route() takes a subdomain argument to specify what subdomain the route is matched on. Blueprint also takes a subdomain argument to set subdomain matching for all routes in a blueprint.
You must set app.config['SERVER_NAME'] to the base domain so Flask knows what to match against. You will also need to specify the port, unless your app is running on port 80 or 443 (i.e in production).
As of Flask 1.0 you must also set subdomain_matching=True when creating the app object.
from flask import Flask
app = Flask(__name__, subdomain_matching=True)
app.config['SERVER_NAME'] = "example.com:5000"
#app.route("/")
def index():
return "example.com"
#app.route("/", subdomain="eggs")
def egg_index():
return "eggs.example.com"
ham = Blueprint("ham", __name__, subdomain="ham")
#ham.route("/")
def index():
return "ham.example.com"
app.register_blueprint(ham)
When running locally, you'll need to edit your computer's hosts file (/etc/hosts on Unix) so that it will know how to route the subdomains, since the domains don't actually exist locally.
127.0.0.1 localhost example.com eggs.example.com ham.example.com
Remember to still specify the port in the browser, http://example.com:5000, http://eggs.example.com:5000, etc.
Similarly, when deploying to production, you'll need to configure DNS so that the subdomains route to the same host as the base name, and configure the web server to route all those names to the app.
Remember, all Flask routes are really instances of werkzeug.routing.Rule. Consulting Werkzeug's documentation for Rule will show you quite a few things that routes can do that Flask's documentation glosses over (since it is already well documented by Werkzeug).

Categories