Search code examples
python-3.xflaskwerkzeug

Flask - Trouble Requesting Specific Endpoint that lies at a Subdomain


So.. Back again with another flask question:

My application is set up largely around the use of subdomains for various portions instead of prefixes. As such, typical urls for my app look like this:

domain.tld/
domain.tld/about
admin.domain.tld/
admin.domain.tld/login
etc.

I'm composing unit tests and I've seem to run into a problem. I've done a lot of searching of the Flask and Werkzeug documentation but I can't seem to figure out how to fix my issue.

Basically, when I'm testing I'm trying to simulate a GET request to various urls.. and a lot of those URLs will fall on subdomains. I've tried the following which would seem to be logical:

with app.app_context():
    url = url_for("admin.login") # returns http://admin.domain.tld:80/login
    with app.test_client() as c:
        resp = c.get(url) # Fails: returns 404
        assert resp.data == "Expected test response", "Bad Response"

Now.. my c.get should return a response containing expected data at the url, but instead I'm being given the default 404 handler. This makes it quite hard to test many of my routes.

I've done some reading into Flask and found a github issue that notes that the test client expects a relative url... well.. I'm not sure how to provide that since I need to specify the subdomain.

Additionally, I've done further reading and discovered that the Flask test client is built on the Werkzeug test client and the Werkzeug test client contains an option for "allow_subdomain_redirects" that is normally false. Sadly, attempting to configure my Flask test client to have that behavior so far has failed (I might be doing it wrong).

Anyways, does anyone know how I can simulate a request in my flask app and target a subdomain? At the moment, I'm all out of ideas. Thanks for any suggestions. :)


Solution

  • So.. After a lot of debugging I have found the problem... and it seems to be a Flask issue after all, though not the one I linked above.

    First, after LOTS of searching I found this archive here which seemed to give guidance on how to properly make the request for subdomains:

    with app.test_client() as c:
        c.get("/target/path.html", base_url="admin.domain.tld/")
    

    There is a caveat, however... Depending on what app.config["SERVER_NAME"] is set to this might not work... Specifically, as of flask 0.11.1 if app.config["SERVER_NAME"] has an explicit port of 80 the above c.get will FAIL. (i.e. if SERVER_NAME looks like domain.tld:80 ) However.. if SERVER_NAME contains any other port it will function properly. (i.e. if SERVER_NAME looks like domain.tld:5000 everything will work fine)

    I don't know if this is intended or not.. but it has caused me a lot of headache and work.. I'll be posting a github issue on it shortly just to make sure it is indeed intended.