Test add_sub_reverse_proxy

from fastcaddy.core import *
from fastcore.test import *
import json
def print_json(j): print(json.dumps(j))
pcfg({})
cf_token = 'DUMMY_TOKEN'
setup_caddy(cf_token)

At this point our Caddy config is:

print(gcfg())
{
    'apps': {
        'http': {'servers': {'srv0': {'listen': [':80', ':443'], 'routes': []}}},
        'tls': {
            'automation': {
                'policies': [{'issuers': [{'challenges': {'dns': {'provider': {'api_token': 'DUMMY_TOKEN', 'name': 
'cloudflare'}}}, 'module': 'acme'}]}]
            }
        }
    }
}

We can confirm that by going to http://localhost:2019/config/

Setup: add wildcard route *.something.example.com.

This is needed in order to add subroutes to it.

add_wildcard_route('something.example.com')

Now our config should include the wildcard route:

print(gcfg())
{
    'apps': {
        'http': {
            'servers': {
                'srv0': {
                    'listen': [':80', ':443'],
                    'routes': [{'@id': 'wildcard-something.example.com', 'handle': [{'handler': 'subroute', 
'routes': []}], 'match': [{'host': ['*.something.example.com']}], 'terminal': True}]
                }
            }
        },
        'tls': {
            'automation': {
                'policies': [{'issuers': [{'challenges': {'dns': {'provider': {'api_token': 'DUMMY_TOKEN', 'name': 
'cloudflare'}}}, 'module': 'acme'}]}]
            }
        }
    }
}

At this point there are no subroutes associated with that *.something.example.com wildcard. When that is matched, the handlers list is empty until…

Add subroute 1: foo.something.example.com

add_sub_reverse_proxy('something.example.com', 'foo', 5001)
print(gcfg('/apps/http/servers/srv0/routes/0/handle'))
[{'handler': 'subroute', 'routes': [{'@id': 'foo.something.example.com', 'handle': [{'handler': 'reverse_proxy', 
'upstreams': [{'dial': 'localhost:5001'}]}], 'match': [{'host': ['foo.something.example.com']}]}]}]

Now we can see the handle config with the list of sub-routes and the sub-route handler.

print(gcfg('/apps/http/servers/srv0/routes/0/handle/0/routes'))
[{'@id': 'foo.something.example.com', 'handle': [{'handler': 'reverse_proxy', 'upstreams': [{'dial': 
'localhost:5001'}]}], 'match': [{'host': ['foo.something.example.com']}]}]

We can see that:

  1. A route with id foo.something.example.com was created.
test_eq(gcfg('/apps/http/servers/srv0/routes/0/handle/0/routes/0/@id'), 'foo.something.example.com')
  1. It matches requests for foo.something.example.com
test_eq(gcfg('apps/http/servers/srv0/routes/0/handle/0/routes/0/match/0/host/0'), 'foo.something.example.com')
  1. When a request for foo.something.example.com is matched, its handler is a reverse proxy to localhost:5001.
test_eq(gcfg('apps/http/servers/srv0/routes/0/handle/0/routes/0/handle/0/upstreams/0/dial'), 'localhost:5001')

Add subroute 2: bar.something.example.com

add_sub_reverse_proxy('something.example.com', 'bar', 5002)
print(gcfg('/apps/http/servers/srv0/routes/0/handle'))
[{'handler': 'subroute', 'routes': [{'@id': 'foo.something.example.com', 'handle': [{'handler': 'reverse_proxy', 
'upstreams': [{'dial': 'localhost:5001'}]}], 'match': [{'host': ['foo.something.example.com']}]}, {'@id': 
'bar.something.example.com', 'handle': [{'handler': 'reverse_proxy', 'upstreams': [{'dial': 'localhost:5002'}]}], 
'match': [{'host': ['bar.something.example.com']}]}]}]

Now we see a single sub-route handler containing two routes.

print(gcfg('/apps/http/servers/srv0/routes/0/handle/0/routes'))
[{'@id': 'foo.something.example.com', 'handle': [{'handler': 'reverse_proxy', 'upstreams': [{'dial': 
'localhost:5001'}]}], 'match': [{'host': ['foo.something.example.com']}]}, {'@id': 'bar.something.example.com', 
'handle': [{'handler': 'reverse_proxy', 'upstreams': [{'dial': 'localhost:5002'}]}], 'match': [{'host': 
['bar.something.example.com']}]}]

Here we see that:

  1. The foo.something.example.com subroute is still present.
test_eq(gcfg('/apps/http/servers/srv0/routes/0/handle/0/handler'), 'subroute')
  1. A route with id bar.something.example.com was created.
test_eq(gcfg('/apps/http/servers/srv0/routes/0/handle/0/routes/1/@id'), 'bar.something.example.com')
  1. It matches requests for bar.something.example.com
test_eq(gcfg('/apps/http/servers/srv0/routes/0/handle/0/routes/1/match/0/host/0'),'bar.something.example.com')
  1. When a request for bar.something.example.com is matched, its handler is a reverse proxy to localhost:5002.
test_eq(gcfg('/apps/http/servers/srv0/routes/0/handle/0/routes/1/handle/0/upstreams/0/dial'), 'localhost:5002')

Add multi-port subroute

add_sub_reverse_proxy('something.example.com', 'multiport', [5003, 5004])
print(gcfg('/apps/http/servers/srv0/routes/0/handle/0/routes/2/handle/0/upstreams'))
[{'dial': 'localhost:5003'}, {'dial': 'localhost:5004'}]
test_eq[{'dial': 'localhost:5003'}, {'dial': 'localhost:5004'}]