I recently bought a new domain from Namecheap and I wanted to deploy a website using Flask on AWS Elastic Beanstalk. However, I do not want to create another Elastic Beanstalk application since there's not much content in my new website and I do not want to pay for additional cost.
Enter Flask Host Matching
Flask host matching provides a way to perform matching on domain names. For example, if you have several domain names and you want to host these domains on a single Flask application, the host matching feature will come in handy.
Installing Flask
The first step is making sure that Flask is already installed on your platform. To install Flask, run any of the following command:
pip install flask # using pip
easy_install flask # using easy_install
Working Locally
For local development, updating the hosts file is a required step to use multiple domains. By default, localhost
or 127.0.0.1
is used and we do not want to use these. For example, if we want to use the domains www.first.local
and www.second.local
, we need to add these lines to C:\Windows\System32\drivers\etc\hosts
.
127.0.0.1 www.first.local
127.0.0.1 www.second.local
Flask @route() Decorator
The easiest way to perform routing in Flask is the use the @route()
decorator. The example below creates two index routes, one for www.first.local
and one for www.second.local
. To enable host matching, we pass the argument host_matching=True
and static_host=FIRST_DOMAIN
to the Flask()
constructor then pass the argument host=<desired_host>
to the @route()
decorator. The argument static_host
is required when using host_matching=True
.
from flask import Flask
FIRST_DOMAIN = 'www.first.local'
SECOND_DOMAIN = 'www.second.local'
application = Flask(__name__, host_matching=True, static_host=FIRST_DOMAIN)
@application.route('/', host=FIRST_DOMAIN)
def first_index():
return f"Hello from {FIRST_DOMAIN}!"
@application.route('/', host=SECOND_DOMAIN)
def second_index():
return f"Hello from {SECOND_DOMAIN}!"
if __name__ == '__main__':
r"""
Add these to hosts (C:\Windows\System32\drivers\etc\hosts) file:
127.0.0.1 www.first.local
127.0.0.1 www.second.local
"""
application.run(host=FIRST_DOMAIN, port=80, debug=True, threaded=True)
Flask Blueprint @route() Decorator
Blueprint @route() decorator does not support the parameter host
. Instead, we use the partial() function. With the use of the partial function, we can simplify the usage similar to the first example.
from functools import partial
from flask import Flask, Blueprint
FIRST_DOMAIN = 'www.first.local'
SECOND_DOMAIN = 'www.second.local'
application = Flask(__name__, host_matching=True, static_host=FIRST_DOMAIN)
second = Blueprint('second', __name__)
second_route = partial(second.route, host=SECOND_DOMAIN)
@application.route('/', host=FIRST_DOMAIN)
def first_index():
return f"Hello from {FIRST_DOMAIN}!"
@second_route('/')
def second_index():
return f"Hello from {SECOND_DOMAIN}!"
application.register_blueprint(second)
if __name__ == '__main__':
r"""
Add these to hosts (C:\Windows\System32\drivers\etc\hosts) file:
127.0.0.1 www.first.local
127.0.0.1 www.second.local
"""
application.run(host=FIRST_DOMAIN, port=80, debug=True, threaded=True)
Using Pluggable Views
To perform host matching on pluggable views, we only need to pass the host
parameter to add_url_rule() function. This also applies to blueprints. The example below uses MethodView.
from flask import Flask
from flask.views import MethodView
FIRST_DOMAIN = 'www.first.local'
SECOND_DOMAIN = 'www.second.local'
application = Flask(__name__, host_matching=True, static_host=FIRST_DOMAIN)
class FirstIndexView(MethodView):
def get(self):
return f"Hello from {FIRST_DOMAIN}!"
class SecondIndexView(MethodView):
def get(self):
return f"Hello from {SECOND_DOMAIN}!"
application.add_url_rule('/', view_func=FirstIndexView.as_view('first_index'), host=FIRST_DOMAIN)
application.add_url_rule('/', view_func=SecondIndexView.as_view('second_index'), host=SECOND_DOMAIN)
if __name__ == '__main__':
r"""
Add these to hosts (C:\Windows\System32\drivers\etc\hosts) file:
127.0.0.1 www.first.local
127.0.0.1 www.second.local
"""
application.run(host=FIRST_DOMAIN, port=80, debug=True, threaded=True)
Can I use more than 2 domain names? Definitely! The purpose of the title is to make it click-baity ?! (If you are aware of a once trending item on the internet with similar sounding title)
The example codes can be downloaded from Github.