I was deploying my flask react application to Heroku. It's all located in the same folder. My app.py code is here
import time
from flask import Flask, send_from_directory
from flask_cors import CORS
app = Flask(__name__, static_folder='build/', template_folder="build", static_url_path='/')
CORS(app)
#app.route('/', defaults={'path': ''})
#app.route('/<path:path>')
def serve(path):
if path != "" and os.path.exists(app.static_folder + '/' + path):
return send_from_directory(app.static_folder, path)
else:
return send_from_directory(app.static_folder, 'index.html')
if __name__ == "__main__":
app.run()
Here's an image of my folder structure:
I deployed it on Heroku but I find 404 error. The code seems to work fine on localhost though, and I have tried everything I could do. My other APIs which send data seem to work fine. It's just the issue with this one.
I am trying to use the wsgi DispatcherMiddleware in order to prefix a url on my application. I've written one module for the dispatcher and one for the app, which has just one view called home and this is where the homepage is served from.
here is my app1.py
import flask
from flask import request, jsonify
app = flask.Flask(__name__)
app.config["DEBUG"] = True
#app.route('/home', methods=['GET'])
def home():
return "<h1>Home</h1>"
and dispatcher.py
from flask import Flask
from werkzeug.wsgi import DispatcherMiddleware
from werkzeug.exceptions import NotFound
from app1 import app
app = Flask(__name__)
app.wsgi_app = DispatcherMiddleware(NotFound(), {
"/prefix": app
})
if __name__ == "__main__":
app.run()
what I wanna do is be able to navigate to http://127.0.0.1:5000/prefix/home
when I run on console py dispatcher.py, but however when I navigate on that url I get a 404 response. What works in only the navigation to the pagehttp://127.0.0.1:5000/home. Could someone help me understand why this happens? I appreciate any help you can provide
Adding prefix to all routes is really simple if you opt for using Blueprints
https://flask.palletsprojects.com/en/1.0.x/tutorial/views/#create-a-blueprint
from flask import Flask, Blueprint
app = Flask(__name__)
prefixed = Blueprint('prefixed', __name__, url_prefix='/prefixed')
#app.route('/nonprefixed')
def non_prefixed_route():
return 'this is the nonprefixed route'
#prefixed.route('/route')
def some_route():
return 'this is the prefixed route'
app.register_blueprint(prefixed)
if __name__ == "__main__":
app.run()
Testing the routes:
> curl localhost:5000/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
> curl localhost:5000/nonprefixed
this is the nonprefixed route
> curl localhost:5000/prefixed/route
this is the prefixed route
SOLUTION:
I was using wrong tha same name for the dispacher and the app1.
dispacher.py should be edited as follows:
from flask import Flask
from werkzeug.wsgi import DispatcherMiddleware
from werkzeug.exceptions import NotFound
from app1 import app as app1
app = Flask(__name__)
app.wsgi_app = DispatcherMiddleware(NotFound(), {
"/prefix": app1
})
if __name__ == "__main__":
app.run()
I have a Flask back-end with API routes which are accessed by a React single page application created using create-react-app. When using the create-react-app dev server, my Flask back end works.
I would like to serve the built (using npm run build) static React app from my Flask server. Building the React app leads to the following directory structure:
- build
- static
- css
- style.[crypto].css
- style.[crypto].css.map
- js
- main.[crypto].js
- main.[crypto].js.map
- index.html
- service-worker.js
- [more meta files]
By [crypto], I mean the randomly generated strings generated at build time.
Having received the index.html file, the browser then makes the following requests:
- GET /static/css/main.[crypto].css
- GET /static/css/main.[crypto].css
- GET /service-worker.js
How should I serve these files? I came up with this:
from flask import Blueprint, send_from_directory
static = Blueprint('static', __name__)
#static.route('/')
def serve_static_index():
return send_from_directory('../client/build/', 'index.html')
#static.route('/static/<path:path>') # serve whatever the client requested in the static folder
def serve_static(path):
return send_from_directory('../client/build/static/', path)
#static.route('/service-worker.js')
def serve_worker():
return send_from_directory('../client/build/', 'service-worker.js')
This way, the static assets are successfully served.
On the other hand, I could incorporate this with the built-in Flask static utilities. But I do not understand how to configure this.
Is my solution robust enough? Is there a way to use built-in Flask features to serve these assets? Is there a better way to use create-react-app?
import os
from flask import Flask, send_from_directory
app = Flask(__name__, static_folder='react_app/build')
# Serve React App
#app.route('/', defaults={'path': ''})
#app.route('/<path:path>')
def serve(path):
if path != "" and os.path.exists(app.static_folder + '/' + path):
return send_from_directory(app.static_folder, path)
else:
return send_from_directory(app.static_folder, 'index.html')
if __name__ == '__main__':
app.run(use_reloader=True, port=5000, threaded=True)
Thats what I ended up with. So bascially catch all routes, test if the path is a file => send file => else send the index.html. That way you can reload the react app from any route you wish and it does not break.
First do npm run build to build the static production files as mentioned by you above
from flask import Flask, render_template
app = Flask(__name__, static_folder="build/static", template_folder="build")
#app.route("/")
def hello():
return render_template('index.html')
print('Starting Flask!')
app.debug=True
app.run(host='0.0.0.0')
Unfortunately, I don't think you can get it work with the development hot-reload.
A working solution here.
Ever thought why we need two separate folders for static and templates. To segregate the mess, right?
But, it's a problem with the production build since it has one folder for both static and templates type of files and all dependencies are linked like that.
The build folder will be served if you consider it both static and templates.
Use something like this
from flask import Flask, render_template
app = Flask(__name__, static_url_path='',
static_folder='build',
template_folder='build')
#app.route("/")
def hello():
return render_template("index.html")
Your flask app will run fine.
The accepted answer does not work for me. I have used
import os
from flask import Flask, send_from_directory, jsonify, render_template, request
from server.landing import landing as landing_bp
from server.api import api as api_bp
app = Flask(__name__, static_folder="../client/build")
app.register_blueprint(landing_bp, url_prefix="/landing")
app.register_blueprint(api_bp, url_prefix="/api/v1")
#app.route("/")
def serve():
"""serves React App"""
return send_from_directory(app.static_folder, "index.html")
#app.route("/<path:path>")
def static_proxy(path):
"""static folder serve"""
file_name = path.split("/")[-1]
dir_name = os.path.join(app.static_folder, "/".join(path.split("/")[:-1]))
return send_from_directory(dir_name, file_name)
#app.errorhandler(404)
def handle_404(e):
if request.path.startswith("/api/"):
return jsonify(message="Resource not found"), 404
return send_from_directory(app.static_folder, "index.html")
#app.errorhandler(405)
def handle_405(e):
if request.path.startswith("/api/"):
return jsonify(message="Mehtod not allowed"), 405
return e
I used a flask server with only one route / which read the index.html file from the build folder of Create react app(CRA)
from flask import Flask
app = Flask(__name__)
app.static_folder = '../build'
#app.route('/')
def index():
fref = open(r'../build/index.html')
html_text = fref.read()
fref.close()
return html_text
app.run()
Setting up this way I faced an error, the static files are not properly served due to path mismatch, so the solution I used is
Add a homepage property in package.json of CRA and set it to "/static"
{
"name":"App-name",
"version":"",
"dependencies":{}
"homepage":"/static",....[other keys]}
Add **homepage** key parallel to the **dependencies** key in the package.json file
This homepage property will be used during the build process of CRA and used in the place of %PUBLIC_URL% of index.html and gets appended to other static assets URL path (you can verify by viewing the index.html code after the build process)
After the build process, run the flask server,we can see the GET request coming with / for the first time and index.html will be served and followed by requests /static/static/js/[[filename]] for other static assets from HTML file and everything works correctly
I am refreshing my browser...after running but,
changes are not affected in browser
from flask import Flask, send_file, render_template, send_file
app = Flask(__name__)
#app.route('/')
def hello_world():
return send_file('templates/create_conf_view.html')
if __name__ == '__main__':
app.run(debug=True, use_reloader=True, host='0.0.0.0', port=1672,threaded=True)
What i am doing wrong ?
According to your code you need to have a directory structure as follows:
app
|_
run.py
templates/
|_create_conf_view.html
According to docs you should not pass templates when rendering a template.
Change your original file to and see if it works:
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def hello_world():
return render_template('create_conf_view.html')
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=1672, thread=True)
Also be sure to access your application at specified port!
I have been following the methods provided in this post:
https://stackoverflow.com/questions/12167729/flask-subdomains-with-blueprint-getting-404
Here is my relevant code:
__init__.py
from flask import Flask, render_template
app = Flask(__name__, static_url_path="", static_folder="static"
import myApp.views
views.py
from flask import Flask, render_template, request, Blueprint
from myApp import app
app.config['SERVER_NAME'] = 'myapp.com'
app.url_map.default_subdomain = "www"
#app.route("/")
def index():
return "This is index page."
test = Blueprint('test', 'test', subdomain='test')
#test.route("/")
def testindex():
return "This is test index page."
app.register_blueprint(test)
if __name__ == "__main__":
app.run()
Using this method I am able to get subdomains 'test' and 'www' working, but now I am unable to access my website via IP address.
Any guidance into the right direction would be appreciated!