This post has to do with deploying AirBnBs knowledge repo app.
We are hosting our knowledge-repo on a sub-route of our server - for example https://aws.our-server-uri.com/knowledge-repo and I'm running into issues with loading static content and redirects.
In summary, I have no way of making the knowledge_repo Flask app aware that the app is running on a sub-route.
The issues
The first issue I ran into was making gunicorn aware of the context route in order to successfully locate the static files, which are now at /knowledge-repo/static/... and not relative to the root url. I solved this by setting the SCRIPT_NAME environment variable to /knowledge-repo before running knowledge_repo --repo . deploy. I'm including this for reference of what I've tried and for potential recommendations of a better solution.
The second issue, which is unresolved, is dynamically prepending our context route to the redirect urls generated by the web app. For example, the Home button in the top navigation bar redirects the user to the root url (https://aws.our-server-uri.com/ in our example case). I need the flask app to be aware of my context route and append /knowledge-repo/ to the page root for all links generated.
What I've tried:
I want to avoid forking and modifying this repo, so I've focussed on ways that do not involve editing the Flask app html, such as setting a <base> tag.
I've set the SCRIPT_NAME environment variable before deploying, but to no avail.
I've played around with setting some variables in a config.py which I passed using the --config config.py flag when running knowledge_repo deploy, but can't seem to find anything that does the trick.
I made some code changes to make it work:
Gave URL prefix to the static content.
Adding URL prefix to the blueprints in flask.
User URL_for with jinja templating to access the routes across HTML and JavaScript.
Here are the code changes.
Related
I had worked with the Flask application which functions as an admin panel and an API. My admin panel includes login page and bunch of admin stuff in it. So I don't want to expose it to the internet.Admin panel should be only accessible from the intranet however my API should be accessible from the internet.
I have two machines.One is a local machine and other one will be hosted at the AWS. The problem is that the code will be same in the two machines however one will serve as an API and other will serve as an Admin panel.
My supervisor told me that I can use "Flask blueprints" to achieve what I am trying to do but I want to be sure before starting to implement.
Can Flask blueprints solve this problem or are there any other options?
(One thing comes to mind is to separate the API from the admin panel into two different Flask apps. Which is easy to do and solves everything. However I am unable to do that right now. )
Image of what I am trying to do
You can use before_app_request on your blueprint and check if your client ip starts with 192.168 or 10.0 or 172.16
from flask import abort
#blueprint_1.before_request
def check_network():
if not request.remote_addr.startswith("192.168") or ...:
abort(404)
Edit : According to Blueprint documentation before_app_request Such a function is executed before each request, even if outside of a blueprint.
use before_request instead (it will be executed before request on blueprint_1 Blueprint ... i edited my code ...
I am trying to view my locally served site on other devices such as my phone or another laptop. On my current laptop the site works fine, I see everything (frontend) and I get 200s when I visit the site.
However, when I try to access the site with my iphone and second laptop, I do not see any frontend but I do get 200s when I try to access the site. The terminal on my working machine also tells me that there are requests coming in.
I use Django as a backend and I bundle/build my Javascript and CSS with webpack and serve it with webpack-dev-server.
When I run webpack I see this message:
http://0.0.0.0:3000/
webpack result is served from http://localhost:3000/public/bundle/
content is served from ./public
When I load my webpage on my working machine, the developer tools shows this:
and everything is working.
I run django with this command.
$ ./manage.py runserver 0.0.0.0:8000
My ifconfig gives me:
inet 192.168.1.102
With my second laptop, I visit 192.168.1.102:8000 and I see nothing on my page. I get a 200 on my machine with the site working meaning the requests has gone through. On my second laptop I see this in the developer tools:
Notice it doesnt have /public/ in the src and href
On my second machine if I visit 192.168.1.102:3000 I see an Interface and I am able to click around to 192.168.1.102:3000/bundle/main.js and see my webpack built javascript.
On my second machine, I tried to change the src and href in my developer tools to 192.168.1.102:3000/bundle/main.js. However nothing would change and I still see a blank screen
Here is a gist of my webpack config:
https://gist.github.com/liondancer/7685b53dffa50d7d102d
I believe your page is empty because the whole "app" is generated by javascript (it seems so in your two screenshots at least, assuming that the content of <div id="app"></div> is not generated by a django view) but the javascript file is not accessible to clients that are different from your development machine.
It's hard to guess why this is happening without your settings.py, urls.py and the code/template of the view generating your home page but we have some candidates that may be generating this issues: CORS, localhost "poisoning" and eventually STATIC_URL misconfiguration.
CORS: A request is considered cross-domain if any of the scheme,
hostname, or port do not match. You are requesting file both from localhost:8000 (or 192.168.1.102:8000) and from localhost:3000. So CORS issues will rise if you request files from an external device/laptop;
localhost is the same machine
as 192.168.1.102 on your "working computer" but it isn't on your second
laptop or any other device in your network;
Do you generate the URLs for css and js files using {% url %} or {% static %} tags? It seems no, but still they look dynamically generated (i.e. the missing "public/" part of their URL). I'm not aware of a way to get different paths using vanilla Django and the same settings, so you should provide the source code of your view, at least, to get a precise answer.
Solutions (or, at least, hints :-) ):
Serve the bundle from the same port (add them to your STATIC path)
Replace every localhost reference in your html URLs (it may require to change your sites - see sites framework)
Use standard template tags/filters and avoid hard-coded URLs in templates and code.
or install https://github.com/owais/django-webpack-loader/ (pip install django-webpack-loader) and follow their README or http://owaislone.org/blog/webpack-plus-reactjs-and-django/ guide
I am trying to set up a subdomain on a flask server, which has a server hosted on Heroku and a custom domain hosted on GoDaddy. I have verified that my subdomain is working locally. The subdomain is a separate blueprint in my app. My setup in flask is:
blueprint = Blueprint('blueprint', __name__, template_folder="templates", subdomain="blueprint")
#blueprint.route('/')
def index():
return "Hello Mate"
and then
app.config['SERVER_NAME'] = os.environ['MY_SERVER_NAME']
from blueprint.views import blueprint
app.register_blueprint(blueprint)
On my local machine, I set up a custom record in my hosts file (/etc/hosts) to test the subdomain. The file has the entries:
127.0.0.1 virtual.local
127.0.0.1 blueprint.virtual.local
If I navigate to blueprint.virtual.local:5000, I see the intended result (a page that just says Hello Mate. I believe this proves my subdomain settings are set up properly, at least within flask.
I push my code to my heroku app, and this is where I start running into problems. My heroku site has a custom domain associated with it from before. I start by adding an entry for the new subdomain. Running heroku domains in the terminal gives me:
=== myapp Domain Names
blueprint.mysite.com
www.mysite.com
myapp.herokuapp.com
mysite.com
The first issue I am running into is that I can only either view my site on the heroku URL or the custom domain. This is a result of app.config['SERVER_NAME'] (which I set to get my subdomain working) being linked to either the heroku URL or my custom URL. When it is set to the heroku URL, I can only see the site when I visit it at that URL, and when I go to my custom domain, I get a 404 error. This is reversed when I switch the value of the SERVER_NAME.
The second issue is that I cannot get my subdomain to work with GoDaddy on Heroku. In GoDaddy, I create a CNAME record that points my subdomain (blueprint) to my heroku site (myapp.herokuapp.com). Is this correct? I get a 404 error whenever I visit the subdomain on my custom domain (blueprint.mysite.com). I believe this is related to the first issue, but I am not sure. Am I missing any steps?
Any advice on the proper way to set this up, so that I can use Flask subdomains on Heroku, being hosted on a custom domain on GoDaddy? Thanks in advance!
I suspect you're confusing Flask Blueprints and Heroku apps. A flask app (and its containing git repository, in this case) is one and only one Heroku app (a single domain, or subdomian... but crucially, only one of them).
A Flask Blueprint is a way of organizing individual sections of a single Flask app to be more modular.
To create Heroku Apps at awesome.darrellsilver.com and sauce.darrellsilver.com you should set up two independent Flask Apps, in two independent Git repos.
For what it is worth, I had 404 issues when I switched to an SSL endpoint using Flask on Heroku. All I had to do was change the app.config "SERVER_NAME" to the new "www.CUSTOMENDPOINTNAME.com" address from the "CUSTOMENDPOINTNAME.herokuapp.com" which was there previously.
I have a simple portfolio website with some html and css files in the root directory of the site hosted by Dreamhost. I also have a Django app that I'd like to place in a subdomain of this same website. However, Heroku will be serving the django app. I'm confused about how to organize and configure the whole portfolio/django website. How would the system work using two different hosts? Should I integrate the static portfolio site into the django project? Or do I keep them completely seperate and have them live on their own servers? Sorry if my question doesn't make sense. I'm very confused.
As far as the internet's concerned, a subdomain is a completely separate website. You can point a subdomain at whatever address you like; the internet doesn't care that it's a completely separate host. You can host your system however you like: both on Dreamhost, both on Heroku, or one on each. The latter setup is the most complex, so we'll walk through that one here.
Let's say your site is example.com and you want the portfolio site to be portfolio.example.com. If your app's running on Heroku, it'll have a name similar to yourportfolio.herokuapp.com. So we need to do two things: tell Heroku that your app is served from portfolio.example.com, and tell the DNS system to point from your subdomain from Heroku.
Pointing the subdomain to Heroku
Presuming your domain name is hosted on Dreamhost, go to the Domains section of the control panel, then Manage Domains. Under example.com is a link called DNS. You need to add a custom CNAME record; set name to portfolio, type to CNAME, and value to yourportfolio.herokuapp.com.. CNAMEs are a way of setting up aliases on the web; they mean "this site is also known as foo".
Telling Heroku to serve your app
Within your Heroku project, run heroku domains:add portfolio.example.com.
Heroku has documentation about subdomains here, which is a useful overview of the process as well as giving details of more complex setups.
Ok, I started with flask and heroku, and I went on to learn more, I am extremely naive as I just started it today. I found this brilliant blog by Ryan Shea,
http://ryaneshea.com/lightweight-python-apps-with-flask-twitter-bootstrap-and-heroku
This particular blog explains the following,
1> what is flask and heroku
2> how to create and write and connect to heroku using CL.
I followed it because it was extremely easy, I had a lot of problems in the middle regarding the ssh keys and creating procfile etc, I used SO to figure it out.
What I did-->
I created virtualenv, then i typed the app.py , created procfile and also the req.txt file.
I connected to heroku and created a stack cedar, renamed it too.
Then comes the HTML files, there is one base.html , then one index and 404 html files.
I typed all of them and saved them. Then When I run the code,
python app.py
The code runs,
I try to connect to the IP from different computer on the same network, it gets connected and it prints
' Hello from python'
Which was the first
#app.route("/")
return 'Hello from python'
My question is, why isnt the base.html or the other html files exist?
I understood how the app was successfully deployed in heroku, but what are the other html files and how do they work?
Please refer to the above link and answer my questions.
I am really naive and do bare it. Thanks a ton.
First, if you are just starting out with Flask I would recommend you read The Flask Mega-Tutorial by Miguel Grinberg. The tutorial goes through the development of a web app, including deployment to Heroku, and does a good job of explaining why and how different methods are used.
Regarding your question, Flask uses .html files as templates using the Jinja 2 template engine, which has a markup syntax similar to Django's. In order to use a template you need to call it with one of Flask's template rendering hooks, most commonly render_template. You can see that render_template is used in the guide you linked here (third from last code block):
#app.route("/")
def index():
return render_template('index.html')
This tells Flask to generate a page using the 'index.html' template located in the templates folder relative to app.py.