Python 同一域、不同端口的CherryPy会话

Python 同一域、不同端口的CherryPy会话,python,session,cherrypy,Python,Session,Cherrypy,考虑下面的脚本。它将启动两个子进程,每一个子进程都是一个CherryPy应用程序(点击Ctrl+C或系统上的任何键盘中断组合键来结束它们)。如果使用CP 3.0运行它(注意更改“StartServer”中的3.0/3.1特定行),请访问: …您看到一个空的目录。然后访问: …您将看到新填充的目录。然后访问: …然后回到 …什么都没有改变 如果您在CP3.1中尝试同样的方法(记住“StartServer”中的行!),当您进入最后一步时,dict现在是空的。这发生在Windows和Debi

考虑下面的脚本。它将启动两个子进程,每一个子进程都是一个CherryPy应用程序(点击Ctrl+C或系统上的任何键盘中断组合键来结束它们)。如果使用CP 3.0运行它(注意更改“StartServer”中的3.0/3.1特定行),请访问:

…您看到一个空的目录。然后访问:

…您将看到新填充的目录。然后访问:

…然后回到

…什么都没有改变

如果您在CP3.1中尝试同样的方法(记住“StartServer”中的行!),当您进入最后一步时,dict现在是空的。这发生在Windows和Debian、Python2.5和2.6中

您可以尝试各种方法:更改为文件存储、分离存储路径。。。它唯一的区别是会话可能被合并而不是被擦除。我也读过,有人建议将会话工具配置键放在应用程序配置中,而不是放在全局配置中,但我认为这与应用程序独立运行的用法无关

我该怎么做才能使独立的CherryPy应用程序不相互干扰

注意:我最初是在网上问这个问题的,但还没有得到答复,所以我在这里尝试。我希望没问题

import os, os.path, socket, sys
import subprocess
import cgi

import cherrypy

HTTP_PORT = 15002
HTTP_HOST = "127.0.0.1"

site1conf = {
    'global' : {
        'server.socket_host' : HTTP_HOST,
        'server.socket_port' : HTTP_PORT,
        'tools.sessions.on' : True,
#        'tools.sessions.storage_type': 'file',
#        'tools.sessions.storage_path': '1',
#        'tools.sessions.storage_path': '.',
        'tools.sessions.timeout' : 1440}}

site2conf = {
    'global' : {
        'server.socket_host' : HTTP_HOST,
        'server.socket_port' : HTTP_PORT + 10,
        'tools.sessions.on' : True,
#        'tools.sessions.storage_type': 'file',
#        'tools.sessions.storage_path': '2',
#        'tools.sessions.storage_path': '.',
        'tools.sessions.timeout' : 1440}}


class Home(object) :

    def __init__(self, key):
        self.key = key

    @cherrypy.expose
    def index(self):
        return """\
<html>
<body>Session:
<br>%s
</body>
</html> """ % cgi.escape(str(dict(cherrypy.session)))

    @cherrypy.expose
    def set(self, val):
        cherrypy.session[self.key.upper()] = val
        return """\
<html>
<body>Set %s to %s</body>
</html>""" % (cgi.escape(self.key), cgi.escape(val))

def StartServer(conf, key):
    cherrypy.config.update(conf)

    print 'Starting server (%s)' % key
    cherrypy.tree.mount(Home(key), '/', {})

    # Start the web server.
    #### 3.0
    # cherrypy.server.quickstart()
    # cherrypy.engine.start()
    ####

    #### 3.1
    cherrypy.engine.start()
    cherrypy.engine.block()
    ####

def Main():
    # Start first webserver
    proc1 = subprocess.Popen(
        [sys.executable, os.path.abspath(__file__), "1"])
    proc2 = subprocess.Popen(
        [sys.executable, os.path.abspath(__file__), "2"])

    proc1.wait()
    proc2.wait()

if __name__ == "__main__":

    print sys.argv

    if len(sys.argv) == 1:
        # Master process
        Main()
    elif(int(sys.argv[1]) == 1):
        StartServer(site1conf, 'magic')
    elif(int(sys.argv[1]) == 2):
        StartServer(site2conf, 'science')
    else:
        sys.exit(1)
导入操作系统、操作系统路径、套接字、系统
导入子流程
导入cgi
进口樱桃
HTTP_端口=15002
HTTP_HOST=“127.0.0.1”
site1conf={
“全球”:{
'server.socket\u host':HTTP\u主机,
'server.socket\u port':HTTP\u端口,
'tools.sessions.on':True,
#'tools.sessions.storage_type':'file',
#'tools.sessions.storage_path':'1',
#'tools.sessions.storage_path':',
'tools.sessions.timeout':1440}
site2conf={
“全球”:{
'server.socket\u host':HTTP\u主机,
'server.socket\u port':HTTP\u端口+10,
'tools.sessions.on':True,
#'tools.sessions.storage_type':'file',
#'tools.sessions.storage_path':'2',
#'tools.sessions.storage_path':',
'tools.sessions.timeout':1440}
类主(对象):
def uuu init uuuu(self,key):
self.key=key
@樱桃树
def索引(自):
返回“”\
会议:

% “%cgi.escape(str(dict(cherrypy.session))) @樱桃树 def设置(自身,val): cherrypy.session[self.key.upper()]=val 返回“”\ 将%s设置为%s “”“%(cgi.escape(self.key),cgi.escape(val)) def StartServer(配置,键): cherrypy.config.update(conf) 打印“正在启动服务器(%s)”%key mount(Home(key),“/”,{}) #启动web服务器。 #### 3.0 #cherrypy.server.quickstart() #cherrypy.engine.start() #### #### 3.1 cherrypy.engine.start() cherrypy.engine.block() #### def Main(): #启动第一个Web服务器 proc1=子进程.Popen( [sys.executable,os.path.abspath(_文件__),“1”] proc2=子进程.Popen( [sys.executable,os.path.abspath(_文件__),“2”] proc1.wait() proc2.wait() 如果名称=“\uuuuu main\uuuuuuuu”: 打印系统argv 如果len(sys.argv)==1: #主进程 Main() elif(int(sys.argv[1])==1): StartServer(site1conf,“magic”) elif(int(sys.argv[1])==2): StartServer(site2conf,“科学”) 其他: 系统出口(1)
存储会话标识符的cookie绑定到主机,而不是主机+端口。当您访问第一个站点时,您会在3.1(而不是3.0)中获得新的会话id,然后您可以填充会话数据并查看它。之后,您使用该会话id转到其他端口,但现在它无效(我相信您可以在调试模式下的日志中看到)。因此,服务器会向您发送新的会话id。现在您返回到第一个服务器,并且您的标识符再次无效,因此您将获得新的会话id。当然,中的会话中没有此新标识符的数据

更新:RFC 2109,第4.3.1节解释集Cookie说明:

用户代理单独跟踪 通过 从每个源设置Cookie响应头 源服务器(区别于 名称或IP地址和端口)

但对标准的解释并不明显。以下是firefox tracker中相关网站的引用:

有两个用于cookies的RFC,2109 (用于设置cookie)和2965(用于 set-cookie2)

在RFC 2109第4.3.1节中 解释它声明的集Cookie
“域默认为请求主机。 “在第2节术语中 声明“主机和服务器请求的条款” 请求URI指的是 客户端将发送到服务器作为, 分别是主机(但不是端口) 以及 http的绝对URI(http_URL) 请求行。请注意 请求主机必须是RFC中的FQHN 第3.3.1节中的2965 Set-Cookie2表示“域” 默认为有效值 请求主机。“它还声明” 端口默认行为是 饼干可能是 返回到任何请求端口。”第1节 术语它表示“术语” 请求主机和请求URI参考 客户的价值观 将分别作为主机(而不是端口)发送到服务器 及 http的绝对URI(http\U URL)的abs\u路径部分 请求行。”(与RFC2109一样)

我对这些的解释是 端口号不应用于 记录cookie域,除非 set-cookie2头显式定义 端口号


TL;DR:将CherryPy配置参数
tools.sessions.name
更改为每个应用程序特有的参数

长答案

我知道这是一个非常古老的问题,但我认为有一个非常简单的答案。写下面的内容是为了将来的搜索者

CherryPy使用cookie查找会话。德福
site1conf = {
    'global': {
        'server.socket_host': HTTP_HOST,
        'server.socket_port': HTTP_PORT,
        'tools.sessions.on': True,
        'tools.sessions.storage_type': 'file',
        'tools.sessions.storage_path': '/tmp/site1_sessions/',
        'tools.sessions.name': 'site1_session_id',
        'tools.sessions.timeout': 1440
    }
}
site2conf = {
    'global': {
        'server.socket_host': HTTP_HOST,
        'server.socket_port': HTTP_PORT + 10,
        'tools.sessions.on': True,
        'tools.sessions.storage_type': 'file',
        'tools.sessions.storage_path': '/tmp/site2_sessions/',
        'tools.sessions.name': 'site2_session_id',
        'tools.sessions.timeout': 1440
    }
}