Forums

DNS CNAME "Unconfigured Domain"

Hi guys,

I've registered the domain "boxbuyerlogistics.com" and created a CNAME for "www" to geoffham.pythonanywhere.com, but when I visit the page I get pointed to a PA "Unconfigured Domain" error page. I eventually realized that I needed to upgrade to the $12/month account to use non-PA domains, and did so, but the error persists. An inspection of the DNS settings and what-not reveals that all appears to be configured properly. Is there a lag after account upgrade before non-PA domains start being permitted?

G

I think this usually is the result of there not being a web app configured with the correct domain name - your DNS settings seem correct, so I'd double check your PA dashboard to make sure the web app you're expecting to see is set up and has its domain set to www.boxbuyerlogistics.com.

If that's all right, I'm afraid I'm out of ideas.

Fixed - didn't realize a change was needed on the dashboard as well. Thanks very much.

Yes, that controls the PA front-end webserver configuration.

Your DNS configuration arranges that clients who request the website are directed to the IP address of the PA server (via the CNAME bouncing the request to the PA hostname and then the PA DNS servers responding to that). The client then makes a HTTP request with an appropriate Host header to that IP address, but since that's shared between multiple user accounts then the PA webserver needs to know which account to direct the request to, and it does this based on the configuration in the "web" tab on the dashboard. At that point the request is delegated to your WSGI application and that is then responsible for using the path portion of the URL to serve the appropriate response.

Hmmm... interesting bit of "how the sausage gets made" background. If I understand it correctly, I would be able to configure the WSGI application so that a specific domain (say, "foo.whatever.com") could be served up from myaccount.pythonanywhere.com/foo - is that right?

The answer to what I believe you're asking is "no". I'm assuming you're asking if you can have a web application at myaccount.pythonanywhere.com which serves particular requests at /foo and then have DNS configured to somehow redirect foo.whatever.com to that path. This is not possible purely with DNS configuration, but you may be able to achieve something similar. Allow me to elaborate...

You can set up foo.whatever.com with a CNAME for myaccount.pythonanywhere.com in your DNS. You can't include the subdirectory /foo because DNS only deals with hostnames not paths. In case this isn't clear, bear in mind that a request to, say, http://foo.whatever.com/path/index.html actually gets split up by your web browser. First it does a DNS lookup for just foo.whatever.com and what it gets back is an IP address, which in this case will be one owned by PA. Then it connects to this address and makes a HTTP request which starts:

GET /path/index.html HTTP/1.1
Host: foo.whatever.com
[... other HTTP headers here...]

Note that the PA IP address doesn't appear here anywhere - that's just for the browser to know which machine on the Internet to connect to to make the request. The hostname included is that of the original request, which is the important part.

So, at this point you'll get a request coming in to PA with a Host: header of foo.whatever.com. At this point the PA front-end receives the request and looks up the hostname against all the registered customer domains - so, you'll need to have a web app configured with the domain foo.whatever.com, or you'll get the PA "unconfigured domain" error. Note that (AFAIK) it does not look at the path (as far as I know) - it selects a web app based entirely on the domain.

Assuming you have a web app set up, it'll now receive the request and how it's handled is up to your code, modulo the capabilities of whatever framework you're using.

Since each PA web app only allows a single domain to be associated with it, you need to create a new one for each domain. However, if you want to handle multiple domains, I can't see any reason that you can't specify the same code back-end for multiple web apps (i.e. provide the same WSGI python file when configuring multiple domains). Since the WSGI application code has access to the HTTP Host header (as the HTTP_HOST environment variable as per the WSGI spec, although most frameworks make this available in a more convenient manner) then there's nothing to stop you using that as well as the path to decide which response to serve. Some frameworks may not make this so convenient, however, as they tend to assume that request routing is based solely on the path and query arguments.

With a bit more work on the WSGI application you could import the same back-end code, and just have the domain-specific WSGI application be a simple wrapper which directs requests based on the paths, which can differ between domains. This is pretty simple - you just have small, unique WSGI applications and use straightforward Python import to include the common code to do the work. For this to work conveniently, all your WSGI apps would need to be based on the same, or very similar, frameworks.

Finally, you do have a simpler option - set up a very simple WSGI application for foo.whatever.com that just sends an appropriate 30x response redirecting the user to myaccount.pythonanywhere.com/foo. Unlike DNS CNAMEs, redirects at the HTTP level can specify a target URL and not just a hostname, but be aware that the address shown in the browser will change with this approach. This may or may not be what you want.

Hopefully I've covered that in enough detail that you're more familiar with what's involved and what your choices are - let me know if you have any more specific questions.

As always, you're 100% correct, Cartroo :-)

Heh, I wish it was always - I'd be very rich. And also barred from a lot of casinos, I guess...

Fantastic! I knew there wasn't a DNS solution, but being a WSGI neophyte I wasn't sure exactly what server-side jigging needed to be done. Thanks muchly.

In this thread I recently posted an example WSGI application which could operate the way that most webservers load CGI scripts, dynamically loading Python script files and mapping them by name into the URL space, so you can dump a Python script into a directory and have it available without reloading your web app. You might find it useful. Also, if all you're interested in is a static mapping, and you're happy to live with reloading your web app when it changes, you can do it with something much simpler, like this:

"""Delegate to one of several WSGI apps."""

# Add your project directory to the path.
project_home = os.path.expanduser("~/mysite")
if project_home not in sys.path:
    sys.path.insert(1, project_home)

# Import applications to use
from default_app import app as default_application
from foo_app import app as application_foo
from bar_app import app as application_bar

# Set up dictionary mapping top-level URLs to apps.
APPS = {
    "foo": application_foo,
    "bar": application_bar
}

def application(environ, start_response):
    """Main application wrapper - delegates to either default or alternate app."""
    path_items = environ.get("PATH_INFO", "").lstrip("/").split("/", 1)
    app = None
    if path_items and path_items[0] in APPS:
        app = APPS[path_items[0]]
        environ["SCRIPT_NAME"] = "/" + path_items[0]
        if path_items[1:]:
            environ["PATH_INFO"] = "/" + "/".join(path_items[1:])
        else:
            environ["PATH_INFO"] = ""
    app = default_application if app is None else app
    return app(environ, start_response)

DISCLAIMER: I just knocked this out, I haven't tested it - unlike Knuth, I haven't even proved it correct. So, be aware that there might be daft bugs. Hopefully you get the idea, anyway.

Once again, this is just an example - you'll need to modify it to suit your needs. I think the most important point to note is that you don't need to be a WSGI expert because most of the hard work is done by the application to which you're delegating (typically by some framework).