pallets/flask

Add domain support to Blueprint

fabswt opened this issue · 5 comments

Currently, Blueprints support a url_prefix and a subdomain option. I would like to see support for a domain option.

I need to host the same codebase on two different sites, but with some of the routes only available to one domain and others only to the other, and roughly 3/4 of routes available on both sites.

I don't want to split the codebase into two because 95% of the code is the same. Checking for request.host on every route (even with a route decorator) is cumbersome. Having this at the level of Blueprints would make the most sense.

There's a way to support multiple domains but it does not allow for the sharing of routes.

I'm not clear what the request is here. You should already be able to do this with host_matching=True. For the 5% that app A needs, make a blueprint only for A's domain, same for the 5% that only B needs.

Maybe you're saying that Blueprint() does not take a host= parameter. But bp.register() does take a host parameter. So you can still apply this to all routes on a blueprint without change, you just have to specify it at registration instead of at creation.

I want some routes to be available to example.org only, others to somesite.com only, and some to both. Didn't find any example of how to do it with Blueprints.

What's bp.register()?

Sorry, meant app.register_blueprint. But you can do that. You can have any layout you want with blueprints. So make some that are shared, some that have host=first_host, and some that have second_host.

a_bp = Blueprint()
b_bp = Blueprint()
shared_bp = Blueprint()

app.register_blueprint(a_bp, host="a")
app.register_blueprint(b_bp, host="b")
app.register_blueprint(shared_bp)

Something along those lines. Sorry, I don't really use this feature, so I don't have a ready made environment to spin up to answer your specific question.

i have the following example:

"""
attempt at an MVCE for Flask with domain blueprints (Flask 3.x)
python3 flaskapp-with-blueprint-example-1.py
"""

from flask import Blueprint, Flask, request


def create_app():
    app = Flask(__name__)

    first_bp = Blueprint('first', __name__)
    second_bp = Blueprint('second', __name__)
    shared_bp = Blueprint('shared', __name__)

    @first_bp.route('/')
    def first_home():
        return f"""route meant only for first.localhost"""

    @second_bp.route('/')
    def second_home():
        return f"""route meant only for second.localhost"""

    @shared_bp.route('/shared')
    def shared_page():
        return f"""this route should work with both domains"""

    app.register_blueprint(first_bp, host="first.localhost")
    app.register_blueprint(second_bp, host="second.localhost")
    app.register_blueprint(shared_bp)

    return app


if __name__ == "__main__":
    app = create_app()
    app.run(
        debug=True,
        host='0.0.0.0',
        port=6123,

        # if running it inside of my docker container:
        # ssl_context=(
        #     "/etc/apache2/ssl/SSLforMyHosts-certificate.pem",
        #     "/etc/apache2/ssl/SSLforMyHosts-key.pem",
        # ),
    )
    
"""adding these lines to your /etc/hosts file should be enough to get up and running:
127.0.0.1 first.localhost
127.0.0.1 second.localhost
"""

it runs, but not as expected:

i thought maybe i need this to set app instead:

app = Flask(__name__, host_matching=True, static_host='first.localhost')

but then every route becomes 404 Not Found.

i don't understand what static_host is. i guess it's the host used to serve static data but it's counter-intuitive that i should set it to a single value when working with multiple domains. likewise for app.config['SERVER_NAME'] (i don't understand if i'm supposed to set it or not, either way setting it to 'first.localhost' did not help in the examples above.)

no offense but the documentation could be clearer. host_matching and domain are not mentioned once on the blueprints page (only subdomains are.)