在单一Pyramid实例上使用多个域和子域

14 投票
2 回答
3381 浏览
提问于 2025-04-17 03:24

我想在一个Pyramid实例上使用多个域名和子域名。但是,我找不到相关的文档。之前有一个问题提到过一个词汇表,但里面的信息很少,也没有例子。你们有没有什么例子或者能推荐更好的文档给我?

2 个回答

0

如果你能控制你的服务器环境,我强烈建议把域名的相关设置放在外面,使用像Apache的代理服务器来处理,这样可以把请求路由到Pyramid的子域名上。这样一来,你就可以轻松地切换任何域名来查看路由,而不需要在Pyramid的代码中处理那些脆弱的东西(比如域名)。这样你的应用代码会更干净,也更容易在以后进行修改。

下面是一个Apache的例子,展示了两个域名如何指向一个Pyramid应用,假设我们在5001端口上运行这个Pyramid应用(可以是gunicorn或者你想用的其他方式)。

<VirtualHost *:80>
    ServerName domain_2.com

    ProxyPreserveHost On

    # send all request to our app at /app1/*
    ProxyPass / http://127.0.0.1:5001/app_1/
    ProxyPassReverse / http://127.0.0.1:5001/app_1/

</VirtualHost>

<VirtualHost *:80>
    ServerName domain_2.com

    ProxyPreserveHost On

    # send all request to our app at /app2/*
    ProxyPass / http://127.0.0.1:5001/app_2/
    ProxyPassReverse / http://127.0.0.1:5001/app_2/

</VirtualHost>

还有一个例子是一个域名指向多个Pyramid实例:

<VirtualHost *:80>
    ServerName mydomain.com

    ProxyPreserveHost On

    # admin go to manager app on 5001
    ProxyPass /media/manager/ http://127.0.0.1:5001/ retry=5
    ProxyPassReverse /media/manager/ http://127.0.0.1:5001/

    # downloads from server app on 5002
    ProxyPass /media/server/ http://127.0.0.1:5002/ retry=5
    ProxyPassReverse /media/server/ http://127.0.0.1:5002/

</VirtualHost>
24

Pyramid其实就是一个WSGI应用。这意味着它依赖于HTTP_HOST这个环境变量(由Host头设置)来确定应用的主机。简单来说,就是一切都是相对的。重点是,Pyramid对它能接受的内容没有限制,所以你可以随意设置,让它只接受特定域名的内容。当然,这一切都得从你的网络服务器是如何配置来给应用提供服务说起。

假设你在使用URL调度,你可能想设计一些自定义的路由条件,来检查request.host的值,看看是否符合你的要求。如果这个条件返回False,那么这个路由就永远不会匹配到那个主机的请求。

这个话题比较大,所以如果你能提供更多具体信息会更有帮助。例如,由于Pyramid是相对的,任何你想从'example.com'生成的URL,去重定向到'sub.example.com',都需要通过一个预生成器来完成。

def pregen(request, elements, kw):
    kw['_app_url'] = 'http://sub.example.com'
    return elements, kw

def req_sub(info, request):
    return request.host.startswith('sub')

config.add_route('sub_only', '/',
                 custom_predicates=(req_sub,),
                 pregenerator=pregen)
config.add_route('foo', '/foo')
config.add_view(view, route_name-'foo')

def view(request):
    # redirect the user to "http://sub.example.com", regardless of whether
    # request.host is "example.com" or "sub.example.com"
    return HTTPFound(request.route_url('sub_only'))

撰写回答