tornado icon indicating copy to clipboard operation
tornado copied to clipboard

Update documentation regarding running tests when using a subdomain in application routing

Open emehrkay opened this issue 5 years ago • 1 comments

I had an existing set of tests that subclass AsyncHTTPTestCase and call routes defined as /api/some/route via the self.fetch method. These work fine.

I decided that I would like the api stuff to live at a subdomain -- api.mysite.tld -- and I followed the instructions laid out here https://stackoverflow.com/a/25592711

I ran my existing tests and they, of course, didnt work. Did some digging and found this test case which seems to resolve the issue (I need to add a Host header in my test cases) https://github.com/tornadoweb/tornado/blob/master/tornado/test/routing_test.py#L199-L227 ( && the HostMatchingTest cases)

Long story long. I setup

app.add_handlers(r'^api\..*', API_ROUTES)

and needed to pass a header value of Host: api. in order to get my existing tests to pass.

Could the documentation be updated to talk about how to test when using subdomain routing? Where should this be outlined at? I wouldn't mind adding some verbiage

emehrkay avatar Aug 19 '20 21:08 emehrkay

I'm not sure where this would best be documented. You might be better suited to answer that than me - you needed this feature; where did you look in the docs before you went digging through the source code? I'm thinking maybe there should be a sort of "testing cookbook" added to docs/guide.

Note that there are multiple possible solutions here. If you're using self.fetch, you need to add a host header directly. But instead you could use an OverrideResolver and then make requests with the natural URLs (`await self.http_client.fetch("http://api.example.com/bar"). That's probably what I'd do if I was in this situation, but it definitely needs documentation since someone not steeped in Tornado's internals is unlikely to come up with it.

I haven't run this but here's the basic idea:

class MyTest(AsyncHTTPTestCase):
    def get_http_client(self):
        domains = ["www.example.com", "api.example.com"]
        return AsyncHTTPClient(resolver=tornado.netutil.OverrideResolver(
            {d: ("127.0.0.1", self.get_http_port()) for d in domains}))

    def test_foo(self):
        resp = await self.http_client.fetch("http://www.example.com/foo")

    def test_bar(self):
        resp = await self.http_client.fetch("http://api.example.com/bar")

bdarnell avatar Sep 03 '20 18:09 bdarnell