test / bt-source /panel /mod /project /docker /sites /sitesManage.py
GGSheng's picture
feat: deploy Gemma 4 to hf space
08c964e verified
# coding: utf-8
# -------------------------------------------------------------------
# 宝塔Linux面板
# -------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
# -------------------------------------------------------------------
# Author: wzz <wzz@bt.cn>
# -------------------------------------------------------------------
# ------------------------------
# docker模型 - docker runtime 业务类
# ------------------------------
import json
import os
import sys
import re
import time
from datetime import datetime, timedelta
if "/www/server/panel/class" not in sys.path:
sys.path.insert(0, "/www/server/panel/class")
import public
from btdockerModel import dk_public as dp
from mod.project.docker.sites.base import Sites
class SitesManage(Sites):
def __init__(self):
super(SitesManage, self).__init__()
self.enable_php_template = '''
location ~ [^/]\.php(/|$) {{
if (!-f $document_root$fastcgi_script_name) {{
return 404;
}}
fastcgi_pass 127.0.0.1:{port};
include fastcgi.conf;
include fastcgi_params;
fastcgi_index index.php;
set $real_script_name $fastcgi_script_name;
if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") {{
set $real_script_name $1;
set $path_info $2;
}}
fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
fastcgi_param SCRIPT_NAME $real_script_name;
fastcgi_param PATH_INFO $path_info;
}}'''
# 2024/11/6 10:44 运行指定php环境
def run_php(self, get):
'''
@name 运行指定php环境
'''
# 2024/11/6 10:44 查询是否存在指定版本的docker image
from btdockerModel.dockerSock import image
sk_image = image.dockerImage()
img_inspect = sk_image.inspect(get.name)
if not img_inspect:
return public.returnResult(False, msg="未找到指定的php环境镜像!")
# 2024/11/6 10:45 运行指定php环境
from mod.project.docker.runtime.runtimeManage import RuntimeManage
runtimeManage = RuntimeManage()
run_result = runtimeManage.run_php_project(get)
if not run_result["status"]: return run_result
return public.returnResult(True)
# 2024/10/29 17:45 获取所有Docker网站项目列表
def get_site_list(self, get):
'''
@name 获取所有Docker网站项目列表
'''
get.type = get.get("type", "all")
if not get.type in ("php", "java", "go", "python", "proxy", "app", "all","nodejs"):
return public.returnResult(False, msg="type仅支持php、java、go、python、proxy、app、all")
if not os.path.exists("{}/synced_docker_sites.pl".format(self.sites_config_path)):
args = public.dict_obj()
self.sync_docker_sites(args)
if not os.path.exists("{}/init_exts_templates.pl".format(self.sites_config_path)):
exts = dp.sql("ext_templates").select()
if not exts:
from mod.project.docker.runtime.runtimeManage import RuntimeManage
runtimeManage = RuntimeManage()
runtimeManage.download_templates()
runtimeManage.add_default_php_ext_template()
public.writeFile("{}/init_exts_templates.pl".format(self.sites_config_path), "init exts templates")
get.query = get.get("query", "")
get.p = get.get("p", 1)
get.row = get.get("row", 10)
get.classify = get.get("classify", 999)
where_parm = [None, (None,)]
if get.type == "all":
if get.classify != 999:
where_parm = ["classify=?", (get.classify,)]
if get.query == "":
sites_result = dp.sql("docker_sites").where(where_parm[0], where_parm[1]).order("addtime desc").select()
else:
where_parm[0] = "classify=? and (name like ? or remark like ?)"
where_parm[1] = (get.classify, "%{}%".format(get.query), "%{}%".format(get.query))
sites_result = dp.sql("docker_sites").where(where_parm[0], where_parm[1]).order("addtime desc").select()
else:
if get.query == "":
sites_result = dp.sql("docker_sites").order("addtime desc").select()
else:
where_parm[0] = "name like ? or remark like ?"
where_parm[1] = ("%{}%".format(get.query), "%{}%".format(get.query))
sites_result = dp.sql("docker_sites").where(where_parm[0], where_parm[1]).order("addtime desc").select()
else:
where_parm[0] = "type=?"
where_parm[1] = (get.type,)
if get.classify != 999:
where_parm[0] = "type=? and classify=?"
where_parm[1] = (get.type, get.classify)
if get.query == "":
sites_result = dp.sql("docker_sites").where(where_parm[0], where_parm[1]).order("addtime desc").select()
else:
where_parm[0] = "type=? and classify=? and (? in name or ? in remark)"
where_parm[1] = (get.type, get.classify, get.query, get.query)
sites_result = dp.sql("docker_sites").where(where_parm[0], where_parm[1]).order("addtime desc").select()
sites_result = self.get_page(sites_result, get)
try:
path = '/www/server/btwaf/site.json'
waf_res = json.loads(public.readFile(path))
except:
waf_res = {}
type_infp = {
"php": "PHP",
"java": "JAVA",
"go": "Go",
"python": "Python",
"proxy": "反向代理",
"app": "Docker应用",
"nodejs": "Nodejs"
}
for site in sites_result["data"]:
site["type"] = type_infp[site["type"]]
get.site_name = site["name"]
project_config = self.read_json_conf(get)
site["healthy"] = 1
site["waf"] = {}
if not project_config:
site["healthy"] = 0
site["conf_path"] = ""
site["ssl"] = -1
site["proxy_pass"] = ""
continue
site["conf_path"] = public.get_setup_path() + '/panel/vhost/nginx/' + get.site_name + '.conf'
site["ssl"] = self.get_site_ssl_info(get.site_name)
site["proxy_pass"] = project_config["proxy_info"][0]["proxy_pass"] if len(project_config["proxy_info"]) > 0 else ""
if waf_res:
for waf in waf_res:
if "open" in waf_res[waf]:
site["waf"] = {"status": True}
return self.pageResult(data=sites_result["data"], page=sites_result["page"])
# 2024/10/29 18:00 创建指定类型的网站项目
def create_site(self, get):
'''
@name 创建指定类型的网站项目
'''
get.domains = get.get("domains", "")
if not get.domains:
return public.returnResult(status=False, msg="域名不能为空,至少输入一个域名!")
get.remark = get.get("remark", "")
get.domain_list = get.domains.split("\n") if get.domains != "" else []
# get.domain_list = json.loads(get.domains) if get.domains != "" else []
get.site_port = get.domain_list[0].strip().split(":")[1] if ":" in get.domain_list[0] else "80"
get.port_list = [get.site_port]
from mod.base.web_conf import util
get.domain_name = get.site_name = util.to_puny_code(get.domain_list[0].strip().split(":")[0]).strip().lower()
public.check_domain_cloud(get.site_name)
if get.domain_name.find("*.") != -1: return public.returnResult(False, "主域名不能是通配符域名!")
cwsres = self.check_web_status()
if not cwsres["status"]: return cwsres
from firewallModel.comModel import main as comModel
firewall_com = comModel()
get.type = get.get("type", None)
if get.type is None: return public.returnResult(False, "type参数不能为空!")
get.name = get.get("name", None)
if get.name is None: return public.returnResult(False, "name参数不能为空!")
get.proxy_path = get.get("proxy_path", "/")
get.runtime_port = None
get.enable_php_conf = ""
get.port = get.get("port", None)
get.runtime_port = get.port
get.project_name = None
get.project_path = None
get.container_id = get.get("container_id", None)
if get.port is None: return public.returnResult(False, "port参数不能为空!")
if get.type == "php":
# 2024/11/6 11:08 检查端口是否占用
import psutil
all_ports = []
for net_port in psutil.net_connections("tcp4"):
all_ports.append(net_port.laddr.port)
if int(get.runtime_port) in all_ports:
get.port = str(get.runtime_port)
from safeModel.firewallModel import main as firewall_main
res_dict = firewall_main().get_listening_processes(get)
return public.returnResult(False, msg="{}端口已被【{}】占用,请更换端口!".format(get.port, res_dict.get("process_name")))
run_result = self.run_php(get)
if not run_result["status"]: return run_result
# 2024/11/6 17:23 写入nginx连接php-fpm的配置文件
enable_php_body = public.readFile("/www/dk_project/runtime/templates/php/enable_php_template.conf")
if enable_php_body: self.enable_php_template = enable_php_body
get.enable_php_conf = self.enable_php_template.format(port=get.runtime_port)
elif get.type in ("java", "go", "python", "app", "proxy","nodejs"):
get.proxy_pass = get.get("proxy_pass", "http://127.0.0.1:{}".format(get.port))
get.proxy_host = get.get("proxy_host", "$http_host")
get.proxy_type = "http"
else:
return public.returnResult(False, "type参数: {} 不支持!".format(get.type))
if get.site_port != "80":
get.domain_name = "{}_{}".format(get.domain_name, get.site_port)
get.site_path = get.get("site_path", "/www/dk_project/wwwroot/{}".format(get.domain_name))
cache_name = "{}_{}".format(get.site_name.replace(".", "_"), get.site_port)
else:
get.site_path = get.get("site_path", "/www/dk_project/wwwroot/{}".format(get.site_name))
cache_name = get.site_name.replace(".", "_")
if dp.sql("docker_sites").where("name=?", (get.domain_name,)).count():
return public.returnResult(False, "域名【{}】已存在,请勿重复添加!".format(get.domain_name))
for domain in get.domain_list:
domain = domain.strip().split(":")[0]
if not public.is_domain(domain):
return public.returnResult(False, "域名【{}】格式不正确".format(domain))
newpid = public.M('domain').where("name=? and port=?", (domain, 80)).getField('pid')
if newpid:
result = public.M('sites').where("id=?", (newpid,)).find()
if result:
return public.returnResult(False, '项目类型【{}】已存在域名:{},请勿重复添加!'.format(
result['project_type'], domain))
newpid = dp.sql("docker_domain").where("name=? and port=?", (domain, 80)).getField('pid')
if newpid:
result = dp.sql("docker_sites").where("id=?", (newpid,)).find()
if result:
return public.returnResult(False, 'docker网站项目【{}】已存在域名:{},请勿重复添加!'.format(result['name'], domain))
if not ":" in domain.strip(): continue
d_port = domain.strip().split(":")[1]
if not public.checkPort(d_port):
return public.returnResult(status=False, msg='端口【{}】不合法!'.format(d_port))
get.port = d_port
firewall_com.set_port_rule(get)
self.site_config_path = os.path.join(self.sites_config_path, get.domain_name)
# 2024/4/18 上午10:46 写入网站配置文件
get.http_block = "proxy_cache_path {site_config_path}/proxy_cache_dir levels=1:2 keys_zone={cache_name}_cache:20m inactive=1d max_size=5g;".format(
site_config_path=self.site_config_path,
cache_name=cache_name
)
get.service_info = {
"name": get.name,
"port": get.runtime_port,
"project_name": get.project_name,
"project_path": get.project_path,
}
get.old_info = {}
get.remark = public.xssencode2(get.get("remark", ""))
if get.remark == "":
get.remark = get.domain_name
# 2024/4/18 上午10:22 写入数据库
ires = self.insert_sites(get)
if not ires["status"]: return ires
# 2024/6/4 下午4:30 写nginx配置文件
self.write_nginx_conf(get)
# 2024/11/8 15:32 创建比网站相关目录和默认文档
self.create_must_dir(get)
self.create_default_html(get)
self.site_conf_file = '{}/{}.json'.format(self.site_config_path, get.domain_name)
public.writeFile(self.site_conf_file, json.dumps(self.init_site_json))
cres = self.check_after_create(get)
if not cres["status"]: return cres
# 2024/11/19 11:48 开启防跨站
get.id = get.pid
get.status = 1
self.SetDirUserINI(get)
public.WriteLog('TYPE_SITE', 'SITE_ADD_SUCCESS', (get.site_name,))
public.set_module_logs('docker_site', 'create', 1)
public.set_module_logs('docker_site_{}'.format(get.type), 'create', 1)
public.serviceReload()
return public.returnResult(msg="创建网站成功")
# 2024/10/31 10:04 设置指定网站的备注
def set_remak(self, get):
'''
@name 设置指定网站的备注
'''
get.remark = get.get("remark", "")
get.id = get.get("id", None)
if get.id is None: return public.returnResult(False, "id参数不能为空!")
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
dp.sql("docker_sites").where("id=?", (get.id,)).setField("remark", public.xssencode2(get.remark))
get.proxy_json_conf["remark"] = public.xssencode2(get.remark)
self._site_proxy_conf_path = "{path}/{site_name}/{site_name}.json".format(
path=self.sites_config_path,
site_name=get.site_name
)
public.writeFile(self._site_proxy_conf_path, json.dumps(get.proxy_json_conf))
return public.returnResult(msg="修改备注成功")
# 2024/10/31 10:05 设置网站到期时间
def set_site_edate(self, get):
'''
@name 设置网站到期时间
'''
get.edate = get.get("edate", "0000-00-00")
get.id = get.get("id", None)
if get.id is None: return public.returnResult(False, "id参数不能为空!")
dp.sql("docker_sites").where("id=?", (get.id,)).setField("edate", get.edate)
return public.returnResult(msg="设置到期时间成功")
# 2024/10/31 10:05 设置网站运行状态
def set_site_status(self, get):
'''
@name 设置网站运行状态
'''
get.status = get.get("status", 1)
get.id = get.get("id", None)
if get.id is None: return public.returnResult(False, "id参数不能为空!")
get.site_name = get.get("site_name", None)
if get.site_name is None: return public.returnResult(False, "site_name参数不能为空!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
old_file = "{path}/{site_name}/{site_name}.json".format(
path="/www/server/proxy_project/sites",
site_name=get.site_name
)
if not os.path.exists(old_file):
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
os.makedirs("{}/{}".format(self.sites_config_path, get.site_name), exist_ok=True)
public.ExecShell("\cp -r {} {}".format(old_file, os.path.join(self.sites_config_path, get.site_name)))
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
get.proxy_json_conf["stop_site_conf"] = '''rewrite ^/(?!bt-stop\.html$).* /bt-stop.html last;
location = /bt-stop.html { # 网站停止,并设置网站停止页面
root /www/server/stop;
}'''
if int(get.status) == 1:
get.proxy_json_conf["stop_site"] = False
args = public.dict_obj()
args.id = [get.id]
args.classify = get.proxy_json_conf["classify"] if "classify" in get.proxy_json_conf else 0
self.set_site_type(args)
else:
path = '/www/server/stop'
if not os.path.exists(path) or not os.path.isfile(path + '/index.html'):
os.makedirs(path)
public.downloadFile('http://{}/stop.html'.format(public.get_url()), path + '/index.html')
bt_stop = path + '/bt-stop.html'
if not os.path.exists(bt_stop):
os.symlink(path + '/index.html', bt_stop)
if not os.path.islink(bt_stop):
os.unlink(bt_stop)
os.symlink(path + '/index.html', bt_stop)
get.proxy_json_conf["stop_site"] = True
args = public.dict_obj()
args.id = [get.id]
args.classify = "-2"
self.set_site_type(args)
dp.sql("docker_sites").where("id=?", (get.id,)).setField("status", get.status)
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置运行状态成功")
# 2024/10/31 10:04 删除指定网站
def delete_site(self, get):
'''
@name 删除指定网站
'''
get.id = get.get("id", None)
if get.id is None: return public.returnResult(False, "id参数不能为空!")
get.remove_path = get.get("remove_path", 0)
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.reload = get.get("reload/d", 1)
find_result = dp.sql("docker_sites").where("id=?", (get.id,)).find()
if not find_result: return public.returnResult(False, "未找到指定网站!")
# 2024/11/6 16:36 停止指定php环境
if find_result["type"] == "php":
service_info = json.loads(find_result["service_info"])
public.ExecShell("docker-compose -f {} down".format(os.path.join(service_info["project_path"], "docker-compose.yml")))
public.ExecShell("docker-compose -f {} rm -f".format(os.path.join(service_info["project_path"], "docker-compose.yml")))
public.ExecShell("rm -rf {}".format(service_info["project_path"]))
# 2024/4/18 上午10:46 删除网站配置文件
self.site_config_path = os.path.join(self.sites_config_path, find_result["name"])
public.ExecShell("rm -rf {}".format(self.site_config_path))
nginx_conf = os.path.join("/www/server/panel/vhost/nginx", "{}.conf".format(find_result["name"]))
public.ExecShell("rm -rf {}".format(nginx_conf))
redirect_dir = public.get_setup_path() + '/panel/vhost/nginx/redirect/' + get.site_name
if os.path.exists(redirect_dir):
public.ExecShell('rm -rf {}'.format(redirect_dir))
logs_file = public.get_logs_path() + '/{}*'.format(get.site_name)
public.ExecShell('rm -f {}'.format(logs_file))
self._site_proxy_conf_path = "{path}/{site_name}".format(
path=self.sites_config_path,
site_name=get.site_name
)
public.ExecShell('rm -rf {}'.format(self._site_proxy_conf_path))
if get.remove_path == 1:
public.ExecShell("rm -rf {}".format(find_result["path"]))
# 2024/4/18 上午10:22 删除数据库
dp.sql("docker_sites").where("id=?", (get.id,)).delete()
# 2024/11/6 10:15 删除所有docker_domain里面pid=id的域名
dp.sql("docker_domain").where("pid=?", (get.id,)).delete()
# 2024/11/7 14:50 删除json配置文件
conf_path = "{path}/{site_name}/{site_name}.json".format(
path=self.sites_config_path,
site_name=find_result["name"]
)
public.ExecShell("rm -rf {}".format(conf_path))
if get.reload == 1:
public.serviceReload()
return public.returnResult(msg="删除网站成功")
# 2024/10/31 10:05 批量删除指定网站
def batch_delete_site(self, get):
'''
@name 批量删除指定网站
'''
get.site_list = get.get("site_list", [])
get.remove_path = get.get("remove_path/d", 0)
get.reload = get.get("reload/d", 0)
try:
site_list = json.loads(get.site_list)
except:
return public.returnResult(False, "请传入需要删除的网站列表!")
acc_list = []
for site in site_list:
args = public.dict_obj()
args.site_name = site["site_name"]
args.remove_path = get.remove_path
args.reload = get.reload
args.id = site["id"]
de_result = self.delete_site(args)
if not de_result["status"]:
acc_list.append({"site_name": site["site_name"], "status": False})
continue
acc_list.append({"site_name": site["site_name"], "status": True})
public.serviceReload()
return public.returnResult(True, msg="批量删除站点成功!", data=acc_list)
# 2024/11/7 17:30 清空所有网站
def prune_sites(self, get):
'''
@name 清空所有网站
'''
get.remove_path = get.get("remove_path/d", 0)
select_result = dp.sql("docker_sites").select()
acc_list = []
for site in select_result:
args = public.dict_obj()
args.site_name = site["name"]
args.remove_path = get.remove_path
args.reload = 0
args.id = site["id"]
de_result = self.delete_site(args)
if not de_result["status"]:
acc_list.append({"site_name": site["name"], "status": False})
continue
acc_list.append({"site_name": site["name"], "status": True})
public.serviceReload()
return public.returnResult(True, msg="清空所有网站成功!", data=acc_list)
# 2024/10/31 10:07 获取指定网站的网站目录
def get_site_path(self, get):
'''
@name 获取指定网站的网站目录
'''
get.id = get.get("id", None)
if get.id is None: return public.returnResult(False, "id参数不能为空!")
site_result = dp.sql("docker_sites").where("id=?", (get.id,)).find()
if not site_result: return public.returnResult(False, "未找到指定网站!")
return public.returnResult(data=site_result)
# 2024/10/31 10:07 设置指定网站的网站目录
def set_site_path(self, get):
'''
@name 设置指定网站的网站目录
'''
get.id = get.get("id", None)
if get.id is None: return public.returnResult(False, "id参数不能为空!")
path = get.get("path", None)
if path is None: return public.returnResult(False, "path参数不能为空!")
get.site_name = get.get("site_name", None)
if get.site_name is None: return public.returnResult(False, "site_name参数不能为空!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
get.proxy_json_conf["site_path"] = path
dp.sql("docker_sites").where("id=?", (get.id,)).setField("path", path)
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
# 2024/11/20 10:45 如果项目是php类型,则替换docker-compose.yml的site_path,然后重新up容器
if "type" in get.proxy_json_conf and get.proxy_json_conf["type"] == "php":
service_info = json.loads(dp.sql("docker_sites").where("id=?", (get.id,)).getField("service_info"))
public.ExecShell("sed -i 's,^SITE_PATH=.*,SITE_PATH={},' {}/.env".format(path, service_info["project_path"]))
public.ExecShell("docker-compose -f {} up -d".format(os.path.join(service_info["project_path"], "docker-compose.yml")))
public.serviceReload()
return public.returnResult(msg="设置网站目录成功")
# 2024/10/31 10:08 设置指定网站的运行目录
def set_site_run_path(self, get):
'''
@name 设置指定网站的运行目录
'''
get.id = get.get("id", None)
if get.id is None: return public.returnResult(False, "id参数不能为空!")
get.run_path = get.get("run_path", None)
if get.run_path is None: return public.returnResult(False, "run_path参数不能为空!")
get.site_name = get.get("site_name", None)
if get.site_name is None: return public.returnResult(False, "site_name参数不能为空!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
get.proxy_json_conf["run_path"] = get.run_path.replace(get.proxy_json_conf["site_path"], "")
if not get.proxy_json_conf["run_path"]: get.proxy_json_conf["run_path"] = "/"
dp.sql("docker_sites").where("id=?", (get.id,)).setField("run_path", get.proxy_json_conf["run_path"])
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
# 2024/11/20 10:45 如果项目是php类型,则替换env的site_path,然后重新up容器
if "type" in get.proxy_json_conf and get.proxy_json_conf["type"] == "php":
service_info = json.loads(dp.sql("docker_sites").where("id=?", (get.id,)).getField("service_info"))
public.ExecShell("sed -i 's,^SITE_PATH=.*,SITE_PATH={},' {}/.env".format(os.path.join(get.proxy_json_conf["site_path"], get.proxy_json_conf["run_path"].replace("/","",1)), service_info["project_path"]))
public.ExecShell("docker-compose -f {} up -d".format(os.path.join(service_info["project_path"], "docker-compose.yml")))
public.serviceReload()
return public.returnResult(msg="设置网站运行目录成功")
# 2024/4/21 下午10:46 设置商业ssl证书
def set_cert(self, get):
'''
@name
@author wzz <2024/4/21 下午10:46>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.oid = get.get("oid", "")
if get.oid == "":
return public.returnResult(status=False, msg="oid不能为空!")
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.siteName = get.site_name
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
from mod.project.docker.sites.sslManage import SslManage
ssl_manage = SslManage()
set_result = ssl_manage.set_cert(get)
if not set_result["status"]: return set_result
get.proxy_json_conf["ssl_info"]["ssl_status"] = True
get.proxy_json_conf["https_port"] = "443"
self._site_proxy_conf_path = "{path}/{site_name}/{site_name}.json".format(
path=self.sites_config_path,
site_name=get.site_name
)
public.writeFile(self._site_proxy_conf_path, json.dumps(get.proxy_json_conf))
return set_result
# 2024/10/31 10:08 保存并启用指定网站的SSL
def set_ssl(self, get):
'''
@name 保存并启用指定网站的SSL
'''
get.key = get.get("key", "")
if get.key == "":
return public.returnResult(status=False, msg="key不能为空!")
get.csr = get.get("csr", "")
if get.csr == "":
return public.returnResult(status=False, msg="csr不能为空!")
get.siteName = get.get("siteName", "")
get.site_name = get.get("site_name", "")
if get.siteName == "":
if get.site_name == "":
return public.returnResult(status=False, msg="网站名不能为空!")
get.siteName = get.site_name
else:
get.site_name = get.siteName
get.type = -1
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
from mod.project.docker.sites.sslManage import SslManage
ssl_manage = SslManage()
result = ssl_manage.set_ssl_to_site(get)
if not result["status"]: return result
get.proxy_json_conf["ssl_info"]["ssl_status"] = True
get.proxy_json_conf["https_port"] = "443"
self._site_proxy_conf_path = "{path}/{site_name}/{site_name}.json".format(
path=self.sites_config_path,
site_name=get.site_name
)
public.writeFile(self._site_proxy_conf_path, json.dumps(get.proxy_json_conf))
return result
# 2024/11/7 15:21 申请let' encrypt证书
def apply_cert_api(self, get):
'''
@name
@author wzz <2024/4/21 下午11:34>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.domains = get.get("domains", "")
if get.domains == "":
return public.returnResult(status=False, msg="domains不能为空!")
get.auth_type = get.get("auth_type", "")
if get.auth_type == "":
return public.returnResult(status=False, msg="auth_type不能为空!")
get.auth_to = get.get("auth_to", "")
if get.auth_to == "":
return public.returnResult(status=False, msg="auth_to不能为空!")
get.auto_wildcard = get.get("auto_wildcard", "")
if get.auto_wildcard == "":
return public.returnResult(status=False, msg="auto_wildcard不能为空!")
get.id = get.get("id", "")
if get.id == "":
return public.returnResult(status=False, msg="id不能为空!")
get.siteName = get.site_name
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
from mod.project.docker.sites.sslManage import Acme_V2
acme = Acme_V2()
result = acme.apply_cert_api(get)
if not result["status"]: return result
get.proxy_json_conf["ssl_info"]["ssl_status"] = True
get.proxy_json_conf["https_port"] = "443"
self._site_proxy_conf_path = "{path}/{site_name}/{site_name}.json".format(
path=self.sites_config_path,
site_name=get.site_name
)
public.writeFile(self._site_proxy_conf_path, json.dumps(get.proxy_json_conf))
return result
# 2024/4/21 下午11:36 验证let' encrypt dns
def apply_dns_auth(self, get):
'''
@name
@author wzz <2024/4/21 下午11:36>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.index = get.get("index", "")
if get.index == "":
return public.returnResult(status=False, msg="index不能为空!")
from acme_v2 import acme_v2
acme = acme_v2()
return acme.apply_dns_auth(get)
# 2024/4/21 下午11:44 设置证书夹里面的证书
def SetBatchCertToSite(self, get):
'''
@name
@author wzz <2024/4/21 下午11:44>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.BatchInfo = get.get("BatchInfo", "")
if get.BatchInfo == "":
return public.returnResult(status=False, msg="BatchInfo不能为空!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
from mod.project.docker.sites.sslManage import SslManage
ssl_manage = SslManage()
set_result = ssl_manage.SetBatchCertToSite(get)
if not "successList" in set_result: return set_result
for re in set_result["successList"]:
if re["status"] and re["siteName"] == get.site_name:
get.proxy_json_conf["ssl_info"]["ssl_status"] = True
break
self._site_proxy_conf_path = "{path}/{site_name}/{site_name}.json".format(
path=self.sites_config_path,
site_name=get.site_name
)
public.writeFile(self._site_proxy_conf_path, json.dumps(get.proxy_json_conf))
return set_result
# 2024/4/22 上午9:43 设置强制https
def set_force_https(self, get):
'''
@name 设置强制https
@param get:
site_name: 网站名
force_https: 1/0
@return:
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.force_https = get.get("force_https/d", 999)
if get.force_https == 999:
return public.returnResult(status=False, msg="force_https不能为空!")
get.siteName = get.site_name
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
get.proxy_json_conf["ssl_info"]["force_https"] = True if get.force_https == 1 else False
from mod.project.docker.sites.sslManage import SslManage
ssl_manage = SslManage()
if get.force_https == 1:
result = ssl_manage.HttpToHttps(get)
else:
result = ssl_manage.CloseToHttps(get)
if not result["status"]: return result
self._site_proxy_conf_path = "{path}/{site_name}/{site_name}.json".format(
path=self.sites_config_path,
site_name=get.site_name
)
public.writeFile(self._site_proxy_conf_path, json.dumps(get.proxy_json_conf))
return result
# 2024/4/21 下午11:03 关闭SSl证书
def close_ssl(self, get):
'''
@name
@author wzz <2024/4/21 下午11:04>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.siteName = get.get("siteName", "")
if get.siteName == "":
return public.returnResult(status=False, msg="siteName不能为空!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
from mod.project.docker.sites.sslManage import SslManage
ssl_manage = SslManage()
result = ssl_manage.CloseSSLConf(get)
if not result["status"]: return result
get.proxy_json_conf["ssl_info"]["ssl_status"] = False
get.proxy_json_conf["https_port"] = "443"
self._site_proxy_conf_path = "{path}/{site_name}/{site_name}.json".format(
path=self.sites_config_path,
site_name=get.site_name
)
public.writeFile(self._site_proxy_conf_path, json.dumps(get.proxy_json_conf))
return result
# 2024/4/19 下午11:46 给指定网站添加域名
def add_domain(self, get):
'''
@name
@author wzz <2024/4/19 下午11:46>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.id = get.get("id", "")
if get.id == "":
return public.returnResult(status=False, msg="id不能为空!")
get.domains = get.get("domains", "")
if get.domains == "":
return public.returnResult(status=False, msg="domains不能为空!")
if "," in get.domains:
return public.returnResult(status=False, msg="域名不能包含逗号!")
isError = public.checkWebConfig()
if isError != True:
return public.returnResult(False, 'ERROR: 检测到配置文件有错误,请先排除后再操作<br><br><a style="color:red;">' + isError.replace("\n", '<br>') + '</a>')
get.domain_list = get.domains.strip().replace(' ', '').split("\n")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
from firewallModel.comModel import main as comModel
firewall_com = comModel()
res_domains = []
for domain in get.domain_list:
if domain == "": continue
domain = domain.strip().split(':')
get.domain = self.ToPunycode(domain[0]).lower()
get.port = '80'
# 判断通配符域名格式
if get.domain.find('*') != -1 and get.domain.find('*.') == -1:
res_domains.append({"name": get.domain, "status": False, "msg": '域名格式不正确'})
continue
# 判断域名格式
reg = "^([\w\-\*]{1,100}\.){1,24}([\w\-]{1,24}|[\w\-]{1,24}\.[\w\-]{1,24})$"
if not re.match(reg, get.domain):
res_domains.append({"name": get.domain, "status": False, "msg": '域名格式不正确'})
continue
# 获取自定义端口
if len(domain) == 2:
get.port = domain[1]
if get.port == "": get.port = "80"
# 判断端口是否合法
if not re.match("^\d+$", get.port):
res_domains.append({"name": get.domain, "status": False, "msg": '端口不合法,应该为数字'})
continue
not_used_ports = ('21', '25', '443', '888', '8888', '8443')
if get.port in not_used_ports:
res_domains.append(
{"name": get.domain, "status": False, "msg": '端口不合法,请勿使用常用端口,例如:ssh的22端口等'})
continue
intport = int(get.port)
if intport < 1 or intport > 65535:
res_domains.append({"name": get.domain, "status": False, "msg": '端口范围不合法'})
continue
# 2024/11/7 18:07 检查域名是否已经存在
find_pid = dp.sql("docker_domain").where("name=? and port=?", (get.domain, get.port)).getField('pid')
if find_pid:
siteName = dp.sql("docker_sites").where("id=?", (find_pid,)).getField('name')
if siteName:
res_domains.append({"name": get.domain, "status": False, "msg": '指定域名[{}]已被网站[{}]绑定过了'.format(get.domain, siteName)})
continue
dp.sql("docker_domain").where("pid=?", (find_pid,)).delete()
# if get.domain in get.proxy_json_conf["domain_list"]:
# res_domains.append({"name": get.domain, "status": False, "msg": '指定域名[{}]已经存在'.format(get.domain)})
# continue
# 2024/11/7 18:09 写配置文件
if not get.domain in get.proxy_json_conf["domain_list"]:
get.proxy_json_conf["domain_list"].append(get.domain)
if not get.port in get.proxy_json_conf["site_port"]:
get.proxy_json_conf["site_port"].append(get.port)
# 2024/11/7 18:19 写入数据库
dp.sql("docker_domain").add('name,port,pid', (get.domain, get.port, get.id))
firewall_com.set_port_rule(get)
res_domains.append({"name": get.domain, "status": True})
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(status=True, data=res_domains)
# 2024/4/20 上午12:07 删除指定网站的某个域名
def del_domain(self, get):
'''
@name
@author wzz <2024/4/20 上午12:07>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.id = get.get("id", "")
if get.id == "":
return public.returnResult(status=False, msg="id不能为空!")
get.port = get.get("port", "")
if get.port == "":
return public.returnResult(status=False, msg="port不能为空!")
get.domain = get.get("domain", "")
if get.domain == "":
return public.returnResult(status=False, msg="domain不能为空!")
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.reload = get.get("reload/d", 1)
# 2024/4/20 上午12:02 更新json文件
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
if len(get.proxy_json_conf["domain_list"]) < 2 and dp.sql("docker_domain").where("pid=?", (get.id,)).count() < 2:
return public.returnResult(status=False, msg="至少保留一个域名!")
while get.domain in get.proxy_json_conf["domain_list"]:
get.proxy_json_conf["domain_list"].remove(get.domain)
if get.port in get.proxy_json_conf["site_port"] and len(get.proxy_json_conf["site_port"]) != 1:
find_r = dp.sql("docker_domain").where("name=? and port=?", (get.domain, get.port)).find()
if find_r:
while get.port in get.proxy_json_conf["site_port"]:
get.proxy_json_conf["site_port"].remove(get.port)
dp.sql("docker_domain").where("name=? and port=?", (get.domain, get.port)).delete()
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
if get.reload == 1:
public.serviceReload()
return public.returnResult(status=True, msg="删除域名成功")
# 2024/4/20 上午12:20 批量删除指定网站域名
def batch_del_domain(self, get):
'''
@name 批量删除指定网站域名
@param get:
@return:
'''
get.del_domain_list = get.get("del_domain_list", None)
if get.del_domain_list is None:
return public.returnResult(status=False, msg="del_domain_list不能为空!")
try:
get.del_domain_list = json.loads(get.del_domain_list)
except:
return public.returnResult(status=False, msg="del_domain_list格式错误!")
res_domains = {"success": [], "error": []}
for domain in get.del_domain_list:
args = public.dict_obj()
args.id = domain["id"]
args.port = domain["port"]
args.domain = domain["domain"]
args.site_name = domain["site_name"]
args.reload = 0
del_result = self.del_domain(args)
if not del_result["status"]:
res_domains["error"].append({"domain": args.domain, "msg": del_result["msg"]})
continue
res_domains["success"].append({"domain": args.domain})
public.serviceReload()
return public.returnResult(status=True, data=res_domains)
# 2024/4/18 下午9:58 设置全局日志
def set_global_log(self, get):
'''
@name
@author wzz <2024/4/18 下午9:58>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.log_type = get.get("log_type", "default")
if not get.log_type in ["default", "file", "rsyslog", "off"]:
return public.returnResult(status=False, msg="日志类型错误,请传入default/file/rsyslog/off!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
get.proxy_json_conf["proxy_log"]["log_type"] = get.log_type
if get.log_type == "file":
get.log_path = get.get("log_path", "")
if get.log_path == "":
return public.returnResult(status=False, msg="日志路径不能为空!")
if not get.log_path.startswith("/"):
return public.returnResult(status=False, msg="日志路径必须以/开头!")
get.proxy_json_conf["proxy_log"]["log_path"] = get.log_path
get.proxy_json_conf["proxy_log"]["log_conf"] = self.init_site_json["proxy_log"]["log_conf"].format(
log_path=get.log_path,
site_name=get.site_name
)
elif get.log_type == "rsyslog":
get.log_path = get.get("log_path", "")
if get.log_path == "":
return public.returnResult(status=False, msg="日志路径不能为空!")
site_name = get.site_name.replace(".", "_")
get.proxy_json_conf["proxy_log"]["log_conf"] = (
"\n access_log syslog:server={server_host},nohostname,tag=nginx_{site_name}_access;"
"\n error_log syslog:server={server_host},nohostname,tag=nginx_{site_name}_error;"
.format(
server_host=get.log_path,
site_name=site_name
))
get.proxy_json_conf["proxy_log"]["rsyslog_host"] = get.log_path
elif get.log_type == "off":
get.proxy_json_conf["proxy_log"]["log_conf"] = "\n access_log off;\n error_log /dev/null;"
else:
get.proxy_json_conf["proxy_log"]["log_conf"] = " " + self.init_site_json["proxy_log"][
"log_conf"].format(
log_path=public.get_logs_path(),
site_name=get.site_name
)
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/4/18 下午10:21 设置basic_auth
def set_dir_auth(self, get):
'''
@name 设置basic_auth
@param auth_type: add/edit
auth_path: /api
username: admin
password: admin
@return:
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.name = get.get("name", "")
if get.name == "":
return public.returnResult(status=False, msg="name不能为空!")
get.auth_path = get.get("auth_path", "")
if get.auth_path == "":
return public.returnResult(status=False, msg="auth_path不能为空!")
if not get.auth_path.startswith("/"):
return public.returnResult(status=False, msg="auth_path必须以/开头!")
get.username = get.get("username", "")
get.password = get.get("password", "")
if get.username == "" or get.password == "":
return public.returnResult(status=False, msg="用户名和密码不能为空!")
if len(get.password) > 8:
return public.returnResult(status=False, msg="密码不能超过8位,超过的部分无法验证!")
get.password = public.hasPwd(get.password)
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
if len(get.proxy_json_conf["basic_auth"]) == 0:
return public.returnResult(status=False, msg="【{}】不存在http认证中,请先添加!".format(get.auth_path))
for i in range(len(get.proxy_json_conf["basic_auth"])):
if get.proxy_json_conf["basic_auth"][i]["auth_path"] == get.auth_path:
if get.proxy_json_conf["basic_auth"][i]["auth_name"] == get.name:
get.proxy_json_conf["basic_auth"][i]["username"] = get.username
get.proxy_json_conf["basic_auth"][i]["password"] = get.password
break
auth_file = "/www/server/pass/{site_name}/{name}.htpasswd".format(site_name=get.site_name, name=get.name)
public.writeFile(auth_file, "{}:{}".format(get.username, get.password))
self._site_proxy_conf_path = "{path}/{site_name}/{site_name}.json".format(
path=self.sites_config_path,
site_name=get.site_name
)
public.writeFile(self._site_proxy_conf_path, json.dumps(get.proxy_json_conf))
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/4/22 下午4:17 添加指定网站的basic_auth
def add_dir_auth(self, get):
'''
@name 添加指定网站的basic_auth
@author wzz <2024/4/22 下午4:17>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.auth_path = get.get("auth_path", "")
if get.auth_path == "":
return public.returnResult(status=False, msg="auth_path不能为空!")
if not get.auth_path.startswith("/"):
return public.returnResult(status=False, msg="auth_path必须以/开头!")
get.name = get.get("name", "")
if get.name == "":
return public.returnResult(status=False, msg="name不能为空!")
get.username = get.get("username", "")
if get.username == "":
return public.returnResult(status=False, msg="username不能为空!")
get.password = get.get("password", "")
if get.password == "":
return public.returnResult(status=False, msg="password不能为空!")
if len(get.password) > 8:
return public.returnResult(status=False, msg="密码不能超过8位,超过的部分无法验证!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
auth_file = "/www/server/pass/{site_name}/{name}.htpasswd".format(site_name=get.site_name, name=get.name)
auth_conf = {
"auth_status": True,
"auth_path": get.auth_path,
"auth_name": get.name,
"username": get.username,
"password": public.hasPwd(get.password),
"auth_file": auth_file,
}
if len(get.proxy_json_conf["basic_auth"]) != 0:
for i in range(len(get.proxy_json_conf["basic_auth"])):
if get.proxy_json_conf["basic_auth"][i]["auth_path"] == get.auth_path:
return public.returnResult(status=False,
msg="【{}】已存在http认证中,无法重复添加!".format(get.auth_path))
if not os.path.exists("/www/server/pass"):
public.ExecShell("mkdir -p /www/server/pass")
if not os.path.exists("/www/server/pass/{}".format(get.site_name)):
public.ExecShell("mkdir -p /www/server/pass/{}".format(get.site_name))
public.writeFile(auth_file, "{}:{}".format(get.username, public.hasPwd(get.password)))
get.proxy_json_conf["basic_auth"].append(auth_conf)
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
return public.returnResult(msg="添加成功!")
# 2024/4/23 上午9:34 删除指定网站的basic_auth
def del_dir_auth(self, get):
'''
@name 删除指定网站的basic_auth
@author wzz <2024/4/23 上午9:35>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.auth_path = get.get("auth_path", "")
if get.auth_path == "":
return public.returnResult(status=False, msg="auth_path不能为空!")
get.name = get.get("name", "")
if get.name == "":
return public.returnResult(status=False, msg="name不能为空!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
auth_file = "/www/server/pass/{site_name}/{name}.htpasswd".format(site_name=get.site_name, name=get.name)
panel_port = public.readFile('/www/server/panel/data/port.pl')
proxy_list = self.get_proxy_list(get)
if proxy_list["data"][0]["proxy_pass"] == "https://127.0.0.1:{}".format(
panel_port.strip()) and get.auth_path.strip() == "/":
return public.returnResult(False, "【{}】是面板的反代,不能删除【/】的http认证!".format(get.site_name))
if len(get.proxy_json_conf["basic_auth"]) != 0:
for i in range(len(get.proxy_json_conf["basic_auth"])):
if get.proxy_json_conf["basic_auth"][i]["auth_path"] == get.auth_path:
if get.proxy_json_conf["basic_auth"][i]["auth_name"] == get.name:
get.proxy_json_conf["basic_auth"].pop(i)
break
public.ExecShell("rm -f {}".format(auth_file))
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="删除成功!")
# 2024/4/18 下午10:26 设置全局gzip
def set_global_gzip(self, get):
'''
@name 设置全局gzip
@param get:
@return:
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.gzip_status = get.get("gzip_status/d", 999)
if get.gzip_status == 999:
return public.returnResult(status=False, msg="gzip_status不能为空,请传number 1或0!")
get.gzip_min_length = get.get("gzip_min_length", "10k")
get.gzip_comp_level = get.get("gzip_comp_level", "6")
if get.gzip_min_length[0] == "0" or get.gzip_min_length.startswith("-"):
return public.returnResult(status=False, msg="gzip_min_length参数不合法,请输入大于0的数字!")
if get.gzip_comp_level == "0" or get.gzip_comp_level.startswith("-"):
return public.returnResult(status=False, msg="gzip_comp_level参数不合法,请输入大于0的数字!")
get.gzip_types = get.get(
"gzip_types",
"text/plain application/javascript application/x-javascript text/javascript text/css application/xml application/json image/jpeg image/gif image/png font/ttf font/otf image/svg+xml application/xml+rss text/x-js"
)
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
get.proxy_json_conf["gzip"]["gzip_status"] = True if get.gzip_status == 1 else False
if get.proxy_json_conf["gzip"]["gzip_status"]:
get.proxy_json_conf["gzip"]["gzip_status"] = True
get.proxy_json_conf["gzip"]["gzip_min_length"] = get.gzip_min_length
get.proxy_json_conf["gzip"]["gzip_comp_level"] = get.gzip_comp_level
get.proxy_json_conf["gzip"]["gzip_types"] = get.gzip_types
get.gzip_conf = ("gzip on;"
"\n gzip_min_length {gzip_min_length};"
"\n gzip_buffers 4 16k;"
"\n gzip_http_version 1.1;"
"\n gzip_comp_level {gzip_comp_level};"
"\n gzip_types {gzip_types};"
"\n gzip_vary on;"
"\n gzip_proxied expired no-cache no-store private auth;"
"\n gzip_disable \"MSIE [1-6]\.\";").format(
gzip_min_length=get.gzip_min_length,
gzip_comp_level=get.gzip_comp_level,
gzip_types=get.gzip_types
)
get.proxy_json_conf["gzip"]["gzip_conf"] = get.gzip_conf
else:
get.proxy_json_conf["gzip"]["gzip_conf"] = ""
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/4/18 下午10:27 设置全局缓存
def set_global_cache(self, get):
'''
@name 设置全局缓存
@param get:
@return:
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.cache_status = get.get("cache_status/d", 999)
if get.cache_status == 999:
return public.returnResult(status=False, msg="cache_status不能为空,请传number 1或0!")
get.expires = get.get("expires", "1d")
if get.expires[0] == "0" or get.expires.startswith("-"):
return public.returnResult(status=False, msg="expires参数不合法,请输入大于0的数字!")
expires = "expires {}".format(get.expires)
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
static_cache = ("\n location ~ .*\\.(css|js|jpe?g|gif|png|webp|woff|eot|ttf|svg|ico|css\.map|js\.map)$"
"\n {{"
"\n {expires};"
"\n error_log /dev/null;"
"\n access_log /dev/null;"
"\n }}").format(
expires=expires,
)
cache_conf = ("\n proxy_cache {cache_zone};"
"\n proxy_cache_key $host$uri$is_args$args;"
"\n proxy_ignore_headers Set-Cookie Cache-Control expires X-Accel-Expires;"
"\n proxy_cache_valid 200 304 301 302 {expires};"
"\n proxy_cache_valid 404 1m;"
"{static_cache}").format(
cache_zone=get.proxy_json_conf["proxy_cache"]["cache_zone"],
expires=get.expires,
static_cache=get.proxy_json_conf["proxy_cache"]["static_cache"] if get.proxy_json_conf["proxy_cache"][
"static_cache"] != "" else static_cache
)
get.proxy_json_conf["proxy_cache"]["cache_status"] = True if get.cache_status == 1 else False
if get.proxy_json_conf["proxy_cache"]["cache_status"]:
get.proxy_json_conf["proxy_cache"]["cache_status"] = True
get.proxy_json_conf["proxy_cache"]["expires"] = get.expires
get.proxy_json_conf["proxy_cache"]["cache_conf"] = cache_conf
else:
get.proxy_json_conf["proxy_cache"]["cache_status"] = False
get.proxy_json_conf["proxy_cache"]["cache_conf"] = static_cache
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/4/18 下午10:43 设置全局websocket支持
def set_global_websocket(self, get):
'''
@name
@author wzz <2024/4/19 下午2:37>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.websocket_status = get.get("websocket_status/d", 999)
if get.websocket_status == 999:
return public.returnResult(status=False, msg="websocket_status不能为空,请传number 1或0!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
if get.websocket_status == 1:
get.proxy_json_conf["websocket"]["websocket_status"] = True
else:
get.proxy_json_conf["websocket"]["websocket_status"] = False
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/4/22 上午10:27 创建重定向
def CreateRedirect(self, get):
'''
@name
@author wzz <2024/4/22 上午10:27>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.domainorpath = get.get("domainorpath", "")
if get.domainorpath == "":
return public.returnResult(status=False, msg="domainorpath不能为空!")
get.redirecttype = get.get("redirecttype", "")
if get.redirecttype == "":
return public.returnResult(status=False, msg="redirecttype不能为空!")
get.redirectpath = get.get("redirectpath", "")
if get.domainorpath == "path" and get.redirectpath == "":
return public.returnResult(status=False, msg="redirectpath不能为空!")
get.tourl = get.get("tourl", "")
if get.tourl == "":
return public.returnResult(status=False, msg="tourl不能为空!")
get.redirectdomain = get.get("redirectdomain", "")
if get.domainorpath == "domain" and get.redirectdomain == "":
return public.returnResult(status=False, msg="redirectdomain不能为空!")
get.redirectname = get.get("redirectname", "")
if get.redirectname == "":
return public.returnResult(status=False, msg="redirectname不能为空!")
get.sitename = get.site_name
get.type = 1
try:
get.holdpath = int(get.get("holdpath", 1))
except:
get.holdpath = 1
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
get.proxy_json_conf["redirect"]["redirect_status"] = True
from panelRedirect import panelRedirect
result = panelRedirect().CreateRedirect(get)
self._site_proxy_conf_path = "{path}/{site_name}/{site_name}.json".format(
path=self.sites_config_path,
site_name=get.site_name
)
public.writeFile(self._site_proxy_conf_path, json.dumps(get.proxy_json_conf))
return result
# 2024/4/22 上午10:45 删除指定网站的某个重定向规则
def DeleteRedirect(self, get):
'''
@name 删除指定网站的某个重定向规则
@author wzz <2024/4/22 上午10:45>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.redirectname = get.get("redirectname", "")
if get.redirectname == "":
return public.returnResult(status=False, msg="redirectname不能为空!")
get.sitename = get.site_name
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
from panelRedirect import panelRedirect
redirect_list = panelRedirect().GetRedirectList(get)
if len(redirect_list) == 0:
get.proxy_json_conf["redirect"]["redirect_status"] = False
self._site_proxy_conf_path = "{path}/{site_name}/{site_name}.json".format(
path=self.sites_config_path,
site_name=get.site_name
)
public.writeFile(self._site_proxy_conf_path, json.dumps(get.proxy_json_conf))
return panelRedirect().DeleteRedirect(get)
# 2024/4/23 上午10:38 编辑指定网站的某个重定向规则
def ModifyRedirect(self, get):
'''
@name 编辑指定网站的某个重定向规则
@author wzz <2024/4/23 上午10:38>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.domainorpath = get.get("domainorpath", "")
if get.domainorpath == "":
return public.returnResult(status=False, msg="domainorpath不能为空!")
get.redirecttype = get.get("redirecttype", "")
if get.redirecttype == "":
return public.returnResult(status=False, msg="redirecttype不能为空!")
get.redirectpath = get.get("redirectpath", "")
if get.domainorpath == "path" and get.redirectpath == "":
return public.returnResult(status=False, msg="redirectpath不能为空!")
get.tourl = get.get("tourl", "")
if get.tourl == "":
return public.returnResult(status=False, msg="tourl不能为空!")
get.redirectdomain = get.get("redirectdomain", "")
if get.domainorpath == "domain" and get.redirectdomain == "":
return public.returnResult(status=False, msg="redirectdomain不能为空!")
get.redirectname = get.get("redirectname", "")
if get.redirectname == "":
return public.returnResult(status=False, msg="redirectname不能为空!")
get.sitename = get.site_name
get.type = get.get("type/d", 1)
get.holdpath = get.get("holdpath/d", 1)
from panelRedirect import panelRedirect
return panelRedirect().ModifyRedirect(get)
# 2024/4/26 下午3:32 获取指定网站指定重定向规则的信息
def GetRedirectFile(self, get):
'''
@name 获取指定网站指定重定向规则的信息
@author wzz <2024/4/26 下午3:32>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.path = get.get("path", "")
if get.path == "":
return public.returnResult(status=False, msg="path不能为空!")
if not os.path.exists(get.path):
return public.returnResult(status=False, msg="重定向已停止或配置文件目录不存在!")
import files
f = files.files()
return f.GetFileBody(get)
# 2024/11/22 10:45 获取防盗链信息
def GetSecurity(self, get):
'''
@name 获取防盗链信息
'''
file = '/www/server/panel/vhost/nginx/' + get.name + '.conf'
conf = public.readFile(file)
data = {}
if type(conf) == bool: return public.returnMsg(False, '读取配置文件失败!')
if conf.find('SECURITY-START') != -1:
rep = "#SECURITY-START(\n|.)+#SECURITY-END"
tmp = re.search(rep, conf).group()
content = re.search("\(.+\)\$", tmp)
if content:
data['fix'] = content.group().replace('(', '').replace(')$', '').replace('|', ',')
else:
data['fix'] = ''
try:
data['domains'] = ','.join(list(set(re.search("valid_referers\s+none\s+blocked\s+(.+);\n", tmp).groups()[0].split())))
except:
data['domains'] = ','.join(list(set(re.search("valid_referers\s+(.+);\n", tmp).groups()[0].split())))
data['status'] = True
data['http_status'] = tmp.find('none blocked') != -1
try:
data['return_rule'] = re.findall(r'(return|rewrite)\s+.*(\d{3}|(/.+)\s+(break|last));', conf)[0][1].replace('break', '').strip()
except:
data['return_rule'] = '404'
else:
conf_file = '/www/server/panel/vhost/config/{}_door_chain.json'.format(get.name)
try:
data = json.loads(public.readFile(conf_file))
data['status'] = data['status'] == "true"
except:
data = {}
data['fix'] = 'jpg,jpeg,gif,png,js,css'
domains = public.M('docker_domain').where('pid=?', (get.id,)).field('name').select()
tmp = []
for domain in domains:
tmp.append(domain['name'])
data['domains'] = ','.join(tmp)
data['return_rule'] = '404'
data['status'] = False
data['http_status'] = False
return data
# 2024/4/22 上午11:12 设置防盗链
def SetSecurity(self, get):
'''
@name 设置防盗链
@author wzz <2024/4/22 上午11:12>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.fix = get.get("fix", "")
if get.fix == "":
return public.returnResult(status=False, msg="fix不能为空!")
get.domains = get.get("domains", "")
if get.domains == "":
return public.returnResult(status=False, msg="domains不能为空!")
get.return_rule = get.get("return_rule", "")
if get.return_rule == "":
return public.returnResult(status=False, msg="return_rule不能为空!")
get.http_status = get.get("http_status", "")
if get.http_status == "":
return public.returnResult(status=False, msg="http_status不能为空!")
get.status = get.get("status", "")
if get.status == "":
return public.returnResult(status=False, msg="status不能为空!")
get.id = get.get("id", "")
if get.id == "":
return public.returnResult(status=False, msg="id不能为空!")
get.name = get.site_name
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
get.proxy_json_conf["security"]["security_status"] = True if get.status == "true" else False
get.proxy_json_conf["security"]["static_resource"] = get.fix
get.proxy_json_conf["security"]["domains"] = get.domains
get.proxy_json_conf["security"]["return_resource"] = get.return_rule
get.proxy_json_conf["security"]["http_status"] = True if get.http_status else False
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/11/7 15:26 添加全局IP黑白名单
def add_ip_limit(self, get):
'''
@name 添加全局IP黑白名单
@author wzz <2024/4/23 下午3:08>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.ip_type = get.get("ip_type", "black")
if get.ip_type not in ["black", "white"]:
return public.returnResult(status=False, msg="ip_type参数错误,必须传black或white!")
get.ips = get.get("ips", "")
if get.ips == "":
return public.returnResult(status=False, msg="ips不能为空,请输入IP,一行一个!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
get.ips = get.ips.split("\n")
for ip in get.ips:
if ip not in get.proxy_json_conf["ip_limit"]["ip_{}".format(get.ip_type)]:
get.proxy_json_conf["ip_limit"]["ip_{}".format(get.ip_type)].append(ip)
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/4/23 下午3:12 删除全局IP黑白名单
def del_ip_limit(self, get):
'''
@name 删除全局IP黑白名单
@author wzz <2024/4/23 下午3:12>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.ip_type = get.get("ip_type", "black")
if get.ip_type not in ["black", "white"]:
return public.returnResult(status=False, msg="ip_type参数错误,必须传black或white!")
get.ip = get.get("ip", "")
if get.ip == "":
return public.returnResult(status=False, msg="ip不能为空,请输入IP!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
if get.ip in get.proxy_json_conf["ip_limit"]["ip_{}".format(get.ip_type)]:
get.proxy_json_conf["ip_limit"]["ip_{}".format(get.ip_type)].remove(get.ip)
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="删除成功!")
# 2024/4/23 下午3:13 批量删除全局IP黑白名单
def batch_del_ip_limit(self, get):
'''
@name 批量删除全局IP黑白名单
@author wzz <2024/4/23 下午3:14>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.ip_type = get.get("ip_type", "black")
if get.ip_type not in ["black", "white", "all"]:
return public.returnResult(status=False, msg="ip_type参数错误,必须传black或white!")
get.ips = get.get("ips", "")
if get.ips == "":
return public.returnResult(status=False, msg="ips不能为空,请输入IP,一行一个!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
get.ips = get.ips.split("\n")
for ip in get.ips:
if get.ip_type == "all":
if ip in get.proxy_json_conf["ip_limit"]["ip_black"]:
get.proxy_json_conf["ip_limit"]["ip_black"].remove(ip)
if ip in get.proxy_json_conf["ip_limit"]["ip_white"]:
get.proxy_json_conf["ip_limit"]["ip_white"].remove(ip)
else:
if ip in get.proxy_json_conf["ip_limit"]["ip_{}".format(get.ip_type)]:
get.proxy_json_conf["ip_limit"]["ip_{}".format(get.ip_type)].remove(ip)
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="删除成功!")
# 2024/4/22 下午9:01 获取指定网站的方向代理列表
def get_proxy_list(self, get):
'''
@name
@author wzz <2024/4/22 下午9:02>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.proxy_path = get.get("proxy_path", "")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
if len(get.proxy_json_conf["proxy_info"]) == 0:
return public.returnResult(status=False, msg="没有代理信息!")
subs_filter = get.proxy_json_conf["subs_filter"] if "subs_filter" in get.proxy_json_conf else \
public.ExecShell("nginx -V 2>&1|grep 'ngx_http_substitutions_filter' -o")[0] != ""
if get.proxy_path != "":
for info in get.proxy_json_conf["proxy_info"]:
if not "proxy_buffering" in info: info["proxy_buffering"] = True
if info["proxy_path"] == get.proxy_path:
info["global_websocket"] = get.proxy_json_conf["websocket"]["websocket_status"]
info["subs_filter"] = subs_filter
if "http://unix:" in info["proxy_pass"]:
info["proxy_pass"] = info["proxy_pass"].replace("http://unix:", "")
return public.returnResult(data=info)
else:
return public.returnResult(status=False, msg="未找到此URL【{}】的代理信息!".format(get.proxy_path))
return public.returnResult(data=get.proxy_json_conf["proxy_info"])
# 2024/4/23 上午11:16 获取指定网站的所有配置信息
def get_global_conf(self, get):
'''
@name 获取指定网站的所有配置信息
@author wzz <2024/4/23 上午11:16>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
return public.returnResult(data=get.proxy_json_conf)
# 2024/4/22 下午9:04 设置指定网站指定URL的反向代理
def set_url_proxy(self, get):
'''
@name
@author wzz <2024/4/22 下午9:04>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.proxy_path = get.get("proxy_path", "")
if get.proxy_path == "":
return public.returnResult(status=False, msg="proxy_path不能为空!")
get.proxy_host = get.get("proxy_host", "")
if get.proxy_host == "":
return public.returnResult(status=False, msg="proxy_host不能为空!")
get.proxy_pass = get.get("proxy_pass", "")
if get.proxy_pass == "":
return public.returnResult(status=False, msg="proxy_pass不能为空!")
get.proxy_type = get.get("proxy_type", "")
if get.proxy_type == "":
return public.returnResult(status=False, msg="proxy_type不能为空!")
get.proxy_connect_timeout = get.get("proxy_connect_timeout", "60s")
get.proxy_send_timeout = get.get("proxy_send_timeout", "600s")
get.proxy_read_timeout = get.get("proxy_read_timeout", "600s")
get.remark = get.get("remark", "")
if get.remark != "":
get.remark = public.xssencode2(get.remark)
if get.proxy_type == "unix":
if not get.proxy_pass.startswith("http://unix:"):
if not get.proxy_pass.startswith("/"):
return public.returnResult(status=False,
msg="unix文件路径必须以/或http://unix:开头,如/tmp/flask_app.sock!")
if not get.proxy_pass.endswith(".sock"):
return public.returnResult(status=False, msg="unix文件必须以.sock结尾,如/tmp/flask_app.sock!")
if not os.path.exists(get.proxy_pass):
return public.returnResult(status=False, msg="代理目标不存在!")
get.proxy_pass = "http://unix:" + get.proxy_pass
elif get.proxy_type == "http":
if not get.proxy_pass.startswith("http://") and not get.proxy_pass.startswith("https://"):
return public.returnResult(status=False, msg="代理目标必须以http://或https://开头!")
get.websocket = get.get("websocket/d", 1)
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
if get.proxy_json_conf["websocket"]["websocket_status"] and get.websocket != 1:
return public.returnResult(status=False,
msg="全局websocket为开启状态,不允许单独关闭此URL的websocket支持!")
for info in get.proxy_json_conf["proxy_info"]:
if info["proxy_path"] == get.proxy_path:
info["proxy_host"] = get.proxy_host
info["proxy_pass"] = get.proxy_pass
info["proxy_type"] = get.proxy_type
info["timeout"]["proxy_connect_timeout"] = get.proxy_connect_timeout.replace("s", "")
info["timeout"]["proxy_send_timeout"] = get.proxy_send_timeout.replace("s", "")
info["timeout"]["proxy_read_timeout"] = get.proxy_read_timeout.replace("s", "")
info["websocket"]["websocket_status"] = True if get.websocket == 1 else False
info["remark"] = get.remark
break
else:
return public.returnResult(status=False, msg="未找到此URL【{}】的代理信息!".format(get.proxy_path))
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/4/19 下午2:59 添加反向代理
def add_proxy(self, get):
'''
@name
@author wzz <2024/4/19 下午3:00>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.proxy_path = get.get("proxy_path", "")
if get.proxy_path == "":
return public.returnResult(status=False, msg="proxy_path不能为空!")
get.proxy_pass = get.get("proxy_pass", "")
if get.proxy_pass == "":
return public.returnResult(status=False, msg="proxy_pass不能为空!")
get.proxy_host = get.get("proxy_host", "$http_host")
get.proxy_type = get.get("proxy_type", "http")
get.remark = get.get("remark", "")
get.proxy_timeout = "proxy_connect_timeout 60s;\n proxy_send_timeout 600s;\n proxy_read_timeout 600s;"
if get.remark != "":
get.remark = public.xssencode2(get.remark)
if get.proxy_type == "unix":
if not get.proxy_pass.startswith("/"):
return public.returnResult(status=False, msg="unix文件路径必须以/开头,如/tmp/flask_app.sock!")
if not get.proxy_pass.endswith(".sock"):
return public.returnResult(status=False, msg="unix文件必须以.sock结尾,如/tmp/flask_app.sock!")
if not os.path.exists(get.proxy_pass):
return public.returnResult(status=False, msg="代理目标不存在!")
get.proxy_pass = "http://unix:{}".format(get.proxy_pass)
elif get.proxy_type == "http":
if not get.proxy_pass.startswith("http://") and not get.proxy_pass.startswith("https://"):
return public.returnResult(status=False, msg="代理目标必须以http://或https://开头!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
# 2024/4/19 下午3:45 检测是否已经存在proxy_path,有的话就返回错误
for proxy_info in get.proxy_json_conf["proxy_info"]:
if proxy_info["proxy_path"] == get.proxy_path:
return public.returnResult(status=False,
msg="【{}】已存在反向代理中,无法重复添加!".format(get.proxy_path))
if len(get.proxy_json_conf["basic_auth"]) != 0:
for i in range(len(get.proxy_json_conf["basic_auth"])):
if get.proxy_json_conf["basic_auth"][i]["auth_path"] == get.proxy_path:
return public.returnResult(status=False, msg="【{}】已存在basicauth中,请先删除再添加反向代理!".format(
get.proxy_path))
sni_conf = ""
if get.proxy_pass.startswith("https://"):
sni_conf = "proxy_ssl_server_name on;"
get.proxy_conf = self._template_proxy_conf.format(
ip_limit="",
gzip="",
proxy_cache="",
sub_filter="",
server_log="",
basic_auth="",
proxy_pass=get.proxy_pass,
proxy_host=get.proxy_host,
proxy_path=get.proxy_path,
SNI=sni_conf,
custom_conf="",
timeout_conf=get.proxy_timeout,
PROXY_BUFFERING="",
websocket_support=get.proxy_json_conf["websocket"]["websocket_conf"],
)
get.proxy_json_conf["proxy_info"].append({
"proxy_type": get.proxy_type,
"proxy_path": get.proxy_path,
"proxy_pass": get.proxy_pass,
"proxy_host": get.proxy_host,
"ip_limit": {
"ip_black": [],
"ip_white": [],
},
"basic_auth": {},
"proxy_cache": {
"cache_status": False,
"cache_zone": "",
"static_cache": "",
"expires": "1d",
"cache_conf": "",
},
"gzip": {
"gzip_status": False,
"gzip_min_length": "10k",
"gzip_comp_level": "6",
"gzip_types": "text/plain application/javascript application/x-javascript text/javascript text/css application/xml application/json image/jpeg image/gif image/png font/ttf font/otf image/svg+xml application/xml+rss text/x-js",
"gzip_conf": "gzip on;\n gzip_min_length 10k;\n gzip_buffers 4 16k;\n gzip_http_version 1.1;\n gzip_comp_level 2;\n gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml;\n gzip_vary on;\n gzip_proxied expired no-cache no-store private auth;\n gzip_disable \"MSIE [1-6]\.\";",
},
"sub_filter": {
"sub_filter_str": [],
},
"websocket": {
"websocket_status": True,
"websocket_conf": "proxy_http_version 1.1;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection $connection_upgrade;",
},
"proxy_log": {
"log_type": "off",
"log_conf": "",
},
"timeout": {
"proxy_connect_timeout": "60",
"proxy_send_timeout": "600",
"proxy_read_timeout": "600",
"timeout_conf": "proxy_connect_timeout 60s;\n proxy_send_timeout 600s;\n proxy_read_timeout 600s;",
},
"custom_conf": "",
"proxy_conf": get.proxy_conf,
"remark": get.remark,
"template_proxy_conf": self._template_proxy_conf,
})
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="添加成功!")
# 2024/4/22 下午9:34 删除指定网站指定URL的反向代理
def del_url_proxy(self, get):
'''
@name 删除指定网站指定URL的反向代理
@param get:
@return:
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.proxy_path = get.get("proxy_path", "")
if get.proxy_path == "":
return public.returnResult(status=False, msg="proxy_path不能为空!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
for info in get.proxy_json_conf["proxy_info"]:
if info["proxy_path"] == get.proxy_path:
get.proxy_json_conf["proxy_info"].remove(info)
break
else:
return public.returnResult(status=False, msg="未找到此URL【{}】的代理信息!".format(get.proxy_path))
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="删除成功!")
# 2024/4/22 下午9:36 设置指定网站指定URL反向代理的备注
def set_url_remark(self, get):
'''
@name 设置指定网站指定URL反向代理的备注
@param get:
@return:
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.proxy_path = get.get("proxy_path", "")
if get.proxy_path == "":
return public.returnResult(status=False, msg="proxy_path不能为空!")
get.remark = get.get("remark", "")
if get.remark != "":
get.remark = public.xssencode2(get.remark)
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
for info in get.proxy_json_conf["proxy_info"]:
if info["proxy_path"] == get.proxy_path:
info["remark"] = get.remark
break
else:
return public.returnResult(status=False, msg="未找到此URL【{}】的代理信息!".format(get.proxy_path))
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/4/22 下午9:40 添加指定网站指定URL的内容替换
def add_sub_filter(self, get):
'''
@name 添加指定网站指定URL的内容替换
@param get:
@return:
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.proxy_path = get.get("proxy_path", "")
if get.proxy_path == "":
return public.returnResult(status=False, msg="proxy_path不能为空!")
get.oldstr = get.get("oldstr", "")
get.newstr = get.get("newstr", "")
if get.oldstr == "" and get.newstr == "":
return public.returnResult(status=False, msg="oldstr和newstr不能同时为空!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
get.sub_type = get.get("sub_type", "g")
if get.sub_type == "":
get.sub_type = "g"
import re
if not re.match(r'^[ior]+$|^g(?!.*o)|^o(?!.*g)$', get.sub_type):
return public.returnResult(status=False,
msg="get.sub_type 只能包含 'g'、'i'、'o' 或 'r' 中的字母组合,并且 'g' 和 'o' 不能同时存在!")
is_subs = public.ExecShell("nginx -V 2>&1|grep 'ngx_http_substitutions_filter' -o")[0]
if not is_subs and re.search(u'[\u4e00-\u9fa5]', get.oldstr + get.newstr):
return public.returnResult(status=False,
msg="您输入的内容包含中文,检测到当前nginx版本不支持,请尝试重新安装nginx 1.20以上的版本后重试!")
if get.sub_type != "g" and not is_subs:
return public.returnResult(status=False,
msg="检测到当前nginx版本仅支持默认替换类型,请尝试重新安装nginx 1.20以上的版本后重试!")
if not "g" in get.sub_type and not "o" in get.sub_type:
get.sub_type = "g" + get.sub_type
for info in get.proxy_json_conf["proxy_info"]:
if info["proxy_path"] == get.proxy_path:
for sub in info["sub_filter"]["sub_filter_str"]:
if get.oldstr == sub["oldstr"]:
return public.returnResult(status=False,
msg="替换前内容:【{}】的配置信息已存在,请勿重复添加!".format(
get.oldstr))
info["sub_filter"]["sub_filter_str"].append(
{
"sub_type": get.sub_type,
"oldstr": get.oldstr,
"newstr": get.newstr
}
)
break
else:
return public.returnResult(status=False, msg="未找到此URL【{}】的代理信息!".format(get.proxy_path))
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/4/22 下午10:00 删除指定网站指定URL的内容替换
def del_sub_filter(self, get):
'''
@name 删除指定网站指定URL的内容替换
@param get:
@return:
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.proxy_path = get.get("proxy_path", "")
if get.proxy_path == "":
return public.returnResult(status=False, msg="proxy_path不能为空!")
get.oldstr = get.get("oldstr", "")
get.newstr = get.get("newstr", "")
if get.oldstr == "" and get.newstr == "":
return public.returnResult(status=False, msg="oldstr和newstr不能同时为空!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
for info in get.proxy_json_conf["proxy_info"]:
if info["proxy_path"] == get.proxy_path:
for sub in info["sub_filter"]["sub_filter_str"]:
if get.oldstr == sub["oldstr"]:
info["sub_filter"]["sub_filter_str"].remove(sub)
break
else:
return public.returnResult(status=False,
msg="未找到替换前内容:【{}】的配置信息!".format(get.oldstr))
break
else:
return public.returnResult(status=False, msg="未找到此URL【{}】的代理信息!".format(get.proxy_path))
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="删除成功!")
# 2024/4/22 下午10:03 设置指定网站指定URL的内容压缩
def set_url_gzip(self, get):
'''
@name 设置指定网站指定URL的内容压缩
@param get:
@return:
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.proxy_path = get.get("proxy_path", "")
if get.proxy_path == "":
return public.returnResult(status=False, msg="proxy_path不能为空!")
get.gzip_status = get.get("gzip_status/d", 999)
if get.gzip_status == 999:
return public.returnResult(status=False, msg="gzip_status不能为空,请传number 1或0!")
get.gzip_min_length = get.get("gzip_min_length", "10k")
get.gzip_comp_level = get.get("gzip_comp_level", "6")
if get.gzip_min_length[0] == "0" or get.gzip_min_length.startswith("-"):
return public.returnResult(status=False, msg="gzip_min_length参数不合法,请输入大于0的数字!")
if get.gzip_comp_level == "0" or get.gzip_comp_level.startswith("-"):
return public.returnResult(status=False, msg="gzip_comp_level参数不合法,请输入大于0的数字!")
get.gzip_types = get.get(
"gzip_types",
"text/plain application/javascript application/x-javascript text/javascript text/css application/xml application/json image/jpeg image/gif image/png font/ttf font/otf image/svg+xml application/xml+rss text/x-js"
)
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
for info in get.proxy_json_conf["proxy_info"]:
if info["proxy_path"] == get.proxy_path:
info["gzip"]["gzip_status"] = True if get.gzip_status == 1 else False
if get.gzip_status == 1:
info["gzip"]["gzip_types"] = get.gzip_types
info["gzip"]["gzip_min_length"] = get.gzip_min_length
info["gzip"]["gzip_comp_level"] = get.gzip_comp_level
info["gzip"]["gzip_conf"] = ("gzip on;"
"\n gzip_min_length {gzip_min_length};"
"\n gzip_buffers 4 16k;"
"\n gzip_http_version 1.1;"
"\n gzip_comp_level {gzip_comp_level};"
"\n gzip_types {gzip_types};"
"\n gzip_vary on;"
"\n gzip_proxied expired no-cache no-store private auth;"
"\n gzip_disable \"MSIE [1-6]\.\";").format(
gzip_min_length=get.gzip_min_length,
gzip_comp_level=get.gzip_comp_level,
gzip_types=get.gzip_types,
)
else:
info["gzip"]["gzip_conf"] = ""
break
else:
return public.returnResult(status=False, msg="未找到此URL【{}】的代理信息!".format(get.proxy_path))
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/4/22 下午10:15 添加指定网站指定URL的IP黑白名单
def add_url_ip_limit(self, get):
'''
@name 添加指定网站指定URL的IP黑白名单
@author wzz <2024/4/22 下午10:16>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.proxy_path = get.get("proxy_path", "")
if get.proxy_path == "":
return public.returnResult(status=False, msg="proxy_path不能为空!")
get.ip_type = get.get("ip_type", "black")
if get.ip_type not in ["black", "white"]:
return public.returnResult(status=False, msg="ip_type参数错误,必须传black或white!")
get.ips = get.get("ips", "")
if get.ips == "":
return public.returnResult(status=False, msg="ips不能为空,请输入IP,一行一个!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
get.ips = get.ips.split("\n")
for info in get.proxy_json_conf["proxy_info"]:
if info["proxy_path"] == get.proxy_path:
for ip in get.ips:
if get.ip_type == "black":
if not ip in info["ip_limit"]["ip_black"]:
info["ip_limit"]["ip_black"].append(ip)
else:
if not ip in info["ip_limit"]["ip_white"]:
info["ip_limit"]["ip_white"].append(ip)
break
else:
return public.returnResult(status=False, msg="未找到此URL【{}】的代理信息!".format(get.proxy_path))
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/4/22 下午10:21 删除指定网站指定URL的IP黑白名单
def del_url_ip_limit(self, get):
'''
@name 删除指定网站指定URL的IP黑白名单
@param get:
@return:
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.proxy_path = get.get("proxy_path", "")
if get.proxy_path == "":
return public.returnResult(status=False, msg="proxy_path不能为空!")
get.ip_type = get.get("ip_type", "black")
if get.ip_type not in ["black", "white"]:
return public.returnResult(status=False, msg="ip_type参数错误,必须传black或white!")
get.ip = get.get("ip", "")
if get.ip == "":
return public.returnResult(status=False, msg="ip不能为空,请输入IP!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
for info in get.proxy_json_conf["proxy_info"]:
if info["proxy_path"] == get.proxy_path:
if get.ip in info["ip_limit"]["ip_{ip_type}".format(ip_type=get.ip_type)]:
info["ip_limit"]["ip_{ip_type}".format(ip_type=get.ip_type)].remove(get.ip)
break
else:
return public.returnResult(status=False, msg="未找到此URL【{}】的代理信息!".format(get.proxy_path))
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/4/24 上午11:21 批量删除指定网站指定URL的IP黑白名单
def batch_del_url_ip_limit(self, get):
'''
@name 批量删除指定网站指定URL的IP黑白名单
@author wzz <2024/4/24 上午11:22>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.ip_type = get.get("ip_type", "black")
if get.ip_type not in ["black", "white", "all"]:
return public.returnResult(status=False, msg="ip_type参数错误,必须传black或white!")
get.ips = get.get("ips", "")
if get.ips == "":
return public.returnResult(status=False, msg="ips不能为空,请输入IP,一行一个!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
for info in get.proxy_json_conf["proxy_info"]:
if info["proxy_path"] == get.proxy_path:
get.ips = get.ips.split("\n")
if get.ip_type == "all":
for ip in get.ips:
if ip in info["ip_limit"]["ip_black"]:
info["ip_limit"]["ip_black"].remove(ip)
if ip in info["ip_limit"]["ip_white"]:
info["ip_limit"]["ip_white"].remove(ip)
else:
for ip in get.ips:
if ip in info["ip_limit"]["ip_{ip_type}".format(ip_type=get.ip_type)]:
info["ip_limit"]["ip_{ip_type}".format(ip_type=get.ip_type)].remove(ip)
break
else:
return public.returnResult(status=False, msg="未找到此URL【{}】的代理信息!".format(get.proxy_path))
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="删除成功!")
# 2024/4/22 下午8:14 设置指定网站指定URL的缓存
def set_url_cache(self, get):
'''
@name 设置指定网站指定URL的缓存
@param get:
@return:
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.cache_status = get.get("cache_status/d", 999)
if get.cache_status == 999:
return public.returnResult(status=False, msg="cache_status不能为空,请传number 1或0!")
get.expires = get.get("expires", "1d")
if get.expires[0] == "0" or get.expires.startswith("-"):
return public.returnResult(status=False, msg="expires参数不合法,请输入大于0的数字!")
expires = "expires {}".format(get.expires)
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
static_cache = ("\n location ~ .*\\.(css|js|jpe?g|gif|png|webp|woff|eot|ttf|svg|ico|css\.map|js\.map)$"
"\n {{"
"\n {expires};"
"\n error_log /dev/null;"
"\n access_log /dev/null;"
"\n }}").format(
expires=expires,
)
for info in get.proxy_json_conf["proxy_info"]:
if info["proxy_path"] == get.proxy_path:
info["proxy_cache"]["cache_status"] = True if get.cache_status == 1 else False
info["proxy_cache"]["expires"] = get.expires
if get.cache_status == 1:
info["proxy_cache"]["cache_conf"] = ("\n proxy_cache {cache_zone};"
"\n proxy_cache_key $host$uri$is_args$args;"
"\n proxy_ignore_headers Set-Cookie Cache-Control expires X-Accel-Expires;"
"\n proxy_cache_valid 200 304 301 302 {expires};"
"\n proxy_cache_valid 404 1m;"
"{static_cache}").format(
cache_zone=get.proxy_json_conf["proxy_cache"]["cache_zone"],
expires=get.expires,
static_cache=static_cache,
)
else:
info["proxy_cache"]["cache_conf"] = ""
break
else:
return public.returnResult(status=False, msg="未找到此URL【{}】的代理信息!".format(get.proxy_path))
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/4/24 上午9:57 设置指定网站指定URL的自定义配置
def set_url_custom_conf(self, get):
'''
@name 设置指定网站指定URL的自定义配置
@author wzz <2024/4/24 上午9:58>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.proxy_path = get.get("proxy_path", "")
if get.proxy_path == "":
return public.returnResult(status=False, msg="proxy_path不能为空!")
get.custom_conf = get.get("custom_conf", "")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
for info in get.proxy_json_conf["proxy_info"]:
if info["proxy_path"] == get.proxy_path:
info["custom_conf"] = get.custom_conf
break
else:
return public.returnResult(status=False, msg="未找到此URL【{}】的代理信息!".format(get.proxy_path))
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/4/24 下午5:39 获取指定网站的网站日志
def GetSiteLogs(self, get):
'''
@name 获取指定网站的网站日志
@author wzz <2024/4/24 下午5:39>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.type = get.get("type", "access")
log_name = get.site_name
if get.type != "access":
log_name = get.site_name + ".error"
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
if get.proxy_json_conf["proxy_log"]["log_type"] == "default":
log_file = public.get_logs_path() + "/" + log_name + '.log'
elif get.proxy_json_conf["proxy_log"]["log_type"] == "file":
log_file = get.proxy_json_conf["proxy_log"]["log_path"] + "/" + log_name + '.log'
else:
return public.returnResult(data={"msg": "", "size": 0})
if os.path.exists(log_file):
return public.returnResult(
data={
"msg": self.xsssec(public.GetNumLines(log_file, 1000)),
"size": public.to_size(os.path.getsize(log_file))
}
)
return public.returnResult(data={"msg": "", "size": 0})
# 2024/4/25 上午10:51 清理指定网站的反向代理缓存
def clear_cache(self, get):
'''
@name 清理指定网站的反向代理缓存
@author wzz <2024/4/25 上午10:51>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
cache_dir = "{sites_config_path}/{site_name}/proxy_cache_dir".format(sites_config_path=self.sites_config_path, site_name=get.site_name)
if os.path.exists(cache_dir):
public.ExecShell("rm -rf {cache_dir}/*".format(cache_dir=cache_dir))
public.serviceReload()
return public.returnResult(msg="清理成功!")
return public.returnResult(msg="清理失败,缓存目录不存在!")
# 2024/4/25 下午9:24 设置指定网站的https端口
def set_https_port(self, get):
'''
@name 设置指定网站的https端口
@author wzz <2024/4/25 下午9:24>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.https_port = get.get("https_port", "443")
if not public.checkPort(get.https_port) and get.https_port != "443":
return public.returnResult(status=False, msg="https端口【{}】不合法!".format(get.https_port))
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
get.proxy_json_conf["https_port"] = get.https_port
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/4/20 下午2:38 保存额外的配置文件
def save_block_config(self, get):
'''
@name 保存配置文件
@param get:
@return:
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.conf_type = get.get("conf_type", "")
if get.conf_type == "":
return public.returnResult(status=False, msg="conf_type不能为空!")
get.body = get.get("body", "")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
if get.conf_type == "http_block":
get.proxy_json_conf["http_block"] = get.body
else:
get.proxy_json_conf["server_block"] = get.body
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="保存成功!")
# 2024/4/20 下午2:22 获取配置文件
def get_nginx_config(self, get):
'''
@name
@author wzz <2024/4/20 下午2:22>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
site_conf = public.readFile(public.get_setup_path() + '/panel/vhost/nginx/' + get.site_name + '.conf')
ssl_conf = get.proxy_json_conf["ssl_info"]["ssl_conf"].format(
site_name=get.site_name,
)
if get.proxy_json_conf["ssl_info"]["force_https"]:
ssl_conf = get.proxy_json_conf["ssl_info"]["force_ssl_conf"].format(
site_name=get.site_name,
force_conf=get.proxy_json_conf["ssl_info"]["force_ssl_conf"],
)
if "如果反代网站访问异常且这里已经配置了内容,请优先排查此处的配置是否正确" in get.proxy_json_conf[
"http_block"]:
http_block = get.proxy_json_conf["http_block"]
else:
http_block = '''# 可设置server|upstream|map等所有http字段,如:
# server {{
# listen 10086;
# server_name ...
# }}
# upstream stream_ser {{
# server back_test.com;
# server ...
# }}
{default_describe}
{http_block}'''.format(
default_describe=self.init_site_json["default_describe"],
http_block=get.proxy_json_conf["http_block"],
)
if "如果反代网站访问异常且这里已经配置了内容,请优先排查此处的配置是否正确" in get.proxy_json_conf[
"server_block"]:
server_block = get.proxy_json_conf["server_block"]
else:
server_block = '''# 可设置server|location等所有server字段,如:
# location /web {{
# try_files $uri $uri/ /index.php$is_args$args;
# }}
# error_page 404 /diy_404.html;
{default_describe}
{server_block}'''.format(
default_describe=self.init_site_json["default_describe"],
server_block=get.proxy_json_conf["server_block"],
)
data = {
"site_conf": site_conf if not site_conf is False else "",
"http_block": http_block,
"server_block": server_block,
"ssl_conf": ssl_conf,
}
return public.returnResult(data=data)
# 2024/4/20 上午9:17 获取域名列表和https端口
def get_domain_list(self, get):
'''
@name 获取域名列表和https端口
@param get:
@return:
'''
get.id = get.get("id", "")
if get.id == "":
return public.returnResult(status=False, msg="id不能为空!")
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
select_result = dp.sql("docker_domain").where("pid=?", get.id).select()
if not select_result:
return public.returnResult(status=False, msg="未找到此ID【{}】的域名信息!".format(get.id))
# 2024/4/20 上午12:02 更新json文件
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
result_data = {}
result_data["domain_list"] = select_result
if get.proxy_json_conf["ssl_info"]["ssl_status"]:
if not "https_port" in get.proxy_json_conf or get.proxy_json_conf["https_port"] == "":
get.proxy_json_conf["https_port"] = "443"
result_data["https_port"] = get.proxy_json_conf["https_port"]
else:
result_data["https_port"] = "未开启HTTPS"
# 2024/4/20 上午9:21 domain_list里面没有的域名健康状态显示为0
for domain in result_data["domain_list"]:
domain["healthy"] = 1
if domain["name"] not in get.proxy_json_conf["domain_list"]:
domain["healthy"] = 0
return public.returnResult(data=result_data)
# 2024/11/7 17:05 设置指定网站的伪静态
def set_site_rewrite(self, get):
'''
@name 设置指定网站的伪静态
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.rewrite_conf = get.get("rewrite_conf", "")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
get.proxy_json_conf["rewrite_conf"] = get.rewrite_conf
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/11/7 17:08 获取指定网站的伪静态
def get_site_rewrite(self, get):
'''
@name 获取指定网站的伪静态
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
return public.returnResult(data=get.proxy_json_conf["rewrite_conf"])
# 2024/10/31 10:29 设置指定网站监听IPv6
def set_site_ipv6(self, get):
'''
@name 设置指定网站监听IPv6
'''
get.site_name = get.get("site_name", "")
if get.site_name == "":
return public.returnResult(status=False, msg="site_name不能为空!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
get.ipv6_status = get.get("ipv6_status/d", 0)
get.proxy_json_conf["ipv6_status"] = True if get.ipv6_status == 1 else False
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/10/31 10:26 获取指定网站的默认文档
def get_index(self, get):
'''
@name 获取指定网站的默认文档
'''
get.id = get.get("id", None)
if get.id is None: return public.returnResult(status=False, msg="id不能为空!")
get.site_name = get.get("site_name", None)
if get.site_name is None: return public.returnResult(status=False, msg="site_name不能为空!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
return public.returnResult(True, data=get.proxy_json_conf["index_conf"].replace(" ", "\n"))
# 2024/10/31 10:26 设置指定网站的默认文档
def set_index(self, get):
'''
@name 设置指定网站的默认文档
'''
get.id = get.get("id", None)
if get.id is None: return public.returnResult(status=False, msg="id不能为空!")
get.site_name = get.get("site_name", None)
if get.site_name is None: return public.returnResult(status=False, msg="site_name不能为空!")
get.index = get.get("index", None)
if get.index is None: return public.returnResult(status=False, msg="index不能为空!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
get.proxy_json_conf["index_conf"] = get.index.replace("\n", " ")
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
def read_file(self, path):
'''
@name
'''
data = {}
try:
fp = open(path, 'rb')
if fp:
srcBody = fp.read()
fp.close()
try:
data['encoding'] = 'utf-8'
data['data'] = srcBody.decode(data['encoding'])
except:
try:
data['encoding'] = 'GBK'
data['data'] = srcBody.decode(data['encoding'])
except:
try:
data['encoding'] = 'BIG5'
data['data'] = srcBody.decode(data['encoding'])
except:
return public.returnResult(False, '文件编码不被兼容,无法正确读取文件!')
except OSError as e:
return public.returnResult(False, '打开文件失败,文件可能被其它进程占用!')
except Exception as e:
return public.returnResult(False, '打开文件失败,{}'.format(str(e)))
return data
# 2024/11/8 14:54 获取指定默认页面内容
def get_default_body(self, get):
'''
@name 获取指定默认页面内容
'''
get.default_type = get.get("default_type", "all")
if not get.default_type in ("all", "index", "404", "not_found", "stop"):
return public.returnResult(status=False, msg="default_type参数错误!")
pl_path = os.path.join(self.sites_config_path, "no_auto_create_404.pl")
auto_create_404 = True if not os.path.exists(pl_path) else False
if get.default_type == "not_found":
not_found_body = self.read_file("/www/server/nginx/html/index.html")
if not "encoding" in not_found_body:
public.writeFile("/www/server/nginx/html/index.html", getattr(self, "default_not_found_body"))
not_found_body = {"default_not_found_body": getattr(self, "default_not_found_body"), "encoding": "utf-8"}
return public.returnResult(True, data={"not_found": not_found_body, "auto_create_404": auto_create_404})
if get.default_type != "all":
diy_filename = os.path.join(self.sites_config_path, "default_{}.html".format(get.default_type))
if not os.path.exists(diy_filename):
if os.path.isfile("/www/dk_project/runtime/templates/html/default_{}.html".format(get.default_type)):
public.writeFile(diy_filename, public.readFile("/www/dk_project/runtime/templates/html/default_{}.html".format(get.default_type)))
else:
public.writeFile(diy_filename, getattr(self, "default_{}_body".format(get.default_type)))
diy_body = self.read_file(diy_filename)
if not "encoding" in diy_body:
public.writeFile(diy_filename, getattr(self, "default_{}_body".format(get.default_type)))
return public.returnResult(True, data={"default_{}_body".format(get.default_type): getattr(self, "default_{}_body".format(get.default_type)), "encoding": "utf-8"})
return public.returnResult(True, data={get.default_type: diy_body, "auto_create_404": auto_create_404})
else:
return_result = {}
for default_type in ("index", "404", "stop"):
diy_filename = os.path.join(self.sites_config_path, "default_{}.html".format(default_type))
if not os.path.exists(diy_filename):
if os.path.isfile("/www/dk_project/runtime/templates/html/default_{}.html".format(default_type)):
public.writeFile(diy_filename, public.readFile("/www/dk_project/runtime/templates/html/default_{}.html".format(default_type)))
else:
public.writeFile(diy_filename, getattr(self, "default_{}_body".format(default_type)))
diy_body = self.read_file(diy_filename)
if not "encoding" in diy_body:
public.writeFile(diy_filename, getattr(self, "default_{}_body".format(default_type)))
return_result[default_type] = {"default_{}_body".format(default_type): getattr(self, "default_{}_body".format(default_type)), "encoding": "utf-8"}
else:
return_result[default_type] = diy_body
not_found_body = self.read_file("/www/server/nginx/html/index.html")
if not "encoding" in not_found_body:
public.writeFile("/www/server/nginx/html/index.html", getattr(self, "default_not_found_body"))
not_found_body = {"default_not_found_body": getattr(self, "default_not_found_body"), "encoding": "utf-8"}
return_result["not_found"] = not_found_body
return_result["auto_create_404"] = auto_create_404
return public.returnResult(True, data=return_result)
# 2024/11/8 15:33 修改指定默认页面内容
def set_default_body(self, get):
'''
@name 修改指定默认页面内容
'''
get.default_type = get.get("default_type", None)
if not get.default_type in ("index", "404", "not_found", "stop"):
return public.returnResult(status=False, msg="default_type参数错误!")
get.encoding = get.get("encoding", "utf-8")
get.default_body = get.get("default_body", None)
if not get.default_body:
return public.returnResult(status=False, msg="default_body不能为空!")
# 2024/11/8 15:35 检测是不是html内容
if not re.match(r"<html.*?>.*?</html>", get.default_body, re.S) and not re.match(r"<.*?doctype.*?html>", get.default_body, re.S):
return public.returnResult(status=False, msg="必须输入html内容!")
if get.default_type == "not_found":
public.writeFile("/www/server/nginx/html/index.html", get.default_body)
return public.returnResult(msg="设置成功!")
diy_filename = os.path.join(self.sites_config_path, "default_{}.html".format(get.default_type))
get.path = diy_filename
get.data = get.default_body
import files
f = files.files()
return f.SaveFileBody(get)
# 2024/11/8 15:44 设置是否在创建网站时自动创建404.html页面
def set_auto_create_404(self, get):
'''
@name 设置是否在创建网站时自动创建404.html页面
'''
get.auto_create = get.get("auto_create", 1)
pl_path = os.path.join(self.sites_config_path, "no_auto_create_404.pl")
if int(get.auto_create) == 0:
public.writeFile(pl_path, "False")
else:
public.ExecShell("rm -f {}".format(pl_path))
return public.returnResult(msg="设置成功!")
# 2024/11/8 15:51 设置指定网站404页面的开启状态
def set_404_status(self, get):
'''
@name 设置指定网站404页面的开启状态
'''
get.site_name = get.get("site_name", None)
if not get.site_name:
return public.returnResult(status=False, msg="site_name不能为空!")
get.status = get.get("status", 0)
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
if int(get.status) == 1:
err_age_404 = "error_page 404 /404.html;"
else:
err_age_404 = "#error_page 404 /404.html;"
get.proxy_json_conf["err_age_404"] = err_age_404
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/11/8 15:54 设置指定网站的404.html页面内容
def set_404_body(self, get):
'''
@name 设置指定网站的404.html页面内容
'''
get.site_name = get.get("site_name", None)
if not get.site_name:
return public.returnResult(status=False, msg="site_name不能为空!")
get.file_body = get.get("file_body", "")
get.encoding = get.get("encoding", "utf-8")
# 2024/11/8 15:35 检测是不是html内容
if not re.match(r"<html.*?>.*?</html>", get.file_body, re.S) and not re.match(r"<.*?doctype.*?html>", get.file_body, re.S):
return public.returnResult(status=False, msg="必须输入html内容!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
get.site_path = get.proxy_json_conf["site_path"]
get.run_path = get.proxy_json_conf["run_path"]
if get.run_path == "/":
file_path = os.path.join(get.site_path, "404.html")
else:
file_path = os.path.join(get.site_path, get.run_path, "404.html")
get.path = file_path
get.data = get.file_body
import files
f = files.files()
return f.SaveFileBody(get)
# 2024/11/14 14:56 获取指定网站的404.html页面内容
def get_404_body(self, get):
'''
@name 获取指定网站的404.html页面内容
'''
get.site_name = get.get("site_name", None)
if not get.site_name:
return public.returnResult(status=False, msg="site_name不能为空!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
get.site_path = get.proxy_json_conf["site_path"]
get.run_path = get.proxy_json_conf["run_path"]
if get.run_path == "/":
file_path = os.path.join(get.site_path, "404.html")
else:
file_path = os.path.join(get.site_path, get.run_path, "404.html")
get.path = file_path
import files
f = files.files()
read_result = f.GetFileBody(get)
if not read_result["status"]:
return {
"auto_save": None,
"data": "",
"encoding": "utf-8",
"historys": [],
"only_read": False,
"size": 0,
"st_mtime": str(int(time.time())),
"status": True,
}
return read_result
# 2024/11/8 14:42 创建默认html文件
def create_default_html(self, get):
'''
@name 创建默认html文件
'''
self.get_default_body(get)
if not os.path.exists(os.path.join(get.site_path, 'index.html')):
public.writeFile(os.path.join(get.site_path, 'index.html'), public.readFile(os.path.join(self.sites_config_path, "default_index.html")))
public.ExecShell('chown www:www {}'.format(os.path.join(get.site_path, 'index.html')))
public.ExecShell('chmod 755 {}'.format(os.path.join(get.site_path, 'index.html')))
if not os.path.exists(os.path.join(self.sites_config_path, "no_auto_create_404.pl")):
if not os.path.exists(os.path.join(get.site_path, '404.html')):
public.writeFile(os.path.join(get.site_path, '404.html'), public.readFile(os.path.join(self.sites_config_path, "default_404.html")))
public.ExecShell('chown www:www {}'.format(os.path.join(get.site_path, '404.html')))
public.ExecShell('chmod 755 {}'.format(os.path.join(get.site_path, '404.html')))
if not os.path.isdir(os.path.join(self.sites_config_path, "stop")):
os.makedirs(os.path.join(self.sites_config_path, "stop"))
public.ExecShell('chown -R www:www {}'.format(os.path.join(self.sites_config_path, "stop")))
public.ExecShell('chmod -R 755 {}'.format(os.path.join(self.sites_config_path, "stop")))
if not os.path.isfile(os.path.join(self.sites_config_path, "stop/index.html")):
public.writeFile(os.path.join(self.sites_config_path, "stop/index.html"), public.readFile(os.path.join(self.sites_config_path, "default_stop.html")))
public.ExecShell('chown www:www {}'.format(os.path.join(self.sites_config_path, "stop/index.html")))
public.ExecShell('chmod 755 {}'.format(os.path.join(self.sites_config_path, "stop/index.html")))
# 2024/11/8 16:23 获取默认站点
def get_default_site(self, get):
'''
@name 获取默认站点
'''
site_names = dp.sql("docker_sites").where("status=?", 1).field("name").order("id desc").select()
default_site = public.readFile('/www/server/panel/data/defaultSite.pl')
return public.returnResult(True, data={"sites": site_names, "defaultSite": default_site})
# 2024/11/8 16:30 设置默认站点
def set_default_site(self, get):
'''
@name 设置默认站点
'''
get.site_name = get.get("site_name", "")
if not get.site_name:
return public.returnResult(status=False, msg="site_name不能为空!")
old_default_site = public.readFile('/www/server/panel/data/defaultSite.pl')
if not old_default_site:
if get.site_name == "0":
public.ExecShell("rm -f /www/server/panel/data/defaultSite.pl")
return public.returnResult(msg="设置成功!")
if old_default_site == get.site_name:
return public.returnResult(status=False, msg="此站点已经是默认站点!")
else:
public.ExecShell("rm -f /www/server/panel/data/defaultSite.pl")
args = public.dict_obj()
args.site_name = old_default_site
args.proxy_json_conf = self.read_json_conf(args)
if args.proxy_json_conf:
update_result = self.update_nginx_conf(args)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
if get.site_name == "0":
public.ExecShell("rm -f /www/server/panel/data/defaultSite.pl")
return public.returnResult(msg="设置成功!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
public.writeFile('/www/server/panel/data/defaultSite.pl', get.site_name)
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/11/8 17:13 将原来反代项目里面所有docker的反代写入新的docker_sites数据库中
def sync_docker_sites(self, get):
'''
@name 将原来反代项目里面所有docker的反代写入新的docker_sites数据库中
@param get:
@return:
'''
# 2024/11/8 17:15 获取所有sites数据库中proxy类型的数据
old_proxy_sites = public.M("sites").where("project_type=?", ("proxy",)).select()
from safeModel.firewallModel import main as firewall_main
from mod.project.proxy.comMod import main as proxy_main
for old_site in old_proxy_sites:
p_json_file = "/www/server/proxy_project/sites/{site_name}/{site_name}.json".format(site_name=old_site["name"])
if not os.path.exists(p_json_file): continue
args = public.dict_obj()
args.site_name = old_site["name"]
get.proxy_json_conf = proxy_main().read_json_conf(args)
if not get.proxy_json_conf: continue
if not "proxy_info" in get.proxy_json_conf: continue
if len(get.proxy_json_conf["proxy_info"]) < 1: continue
public.writeFile(os.path.join(self.sites_config_path, "{site_name}.json".format(site_name=old_site["name"])), json.dumps(get.proxy_json_conf))
for proxy_info in get.proxy_json_conf["proxy_info"]:
if not "proxy_pass" in proxy_info: continue
if not proxy_info["proxy_pass"]: continue
proxy_port = proxy_info["proxy_pass"].split(":")[-1]
args = public.dict_obj()
args.port = proxy_port
res_dict = firewall_main().get_listening_processes(args)
if not "process_name" in res_dict: continue
if not res_dict["process_name"]: continue
if "docker" in res_dict["process_name"]:
container_id = None
project_name = None
dk_site_info = dp.sql('dk_sites').where('name=?', (old_site["name"],)).find()
if dk_site_info:
container_id = dk_site_info["container_id"]
project_name = dk_site_info["container_name"]
get.service_info = {
"name": old_site["name"],
"port": args.port,
"project_name": project_name,
"project_path": None,
}
get.old_info = json.dumps(old_site)
pdata = {
"name": old_site["name"],
"path": old_site["path"],
"run_path": "/",
"remark": public.xssencode2(old_site["ps"]),
"type": "proxy",
"service_info": json.dumps(get.service_info),
"old_info": get.old_info,
"addtime": old_site["addtime"],
"container_id": container_id,
}
get.pid = dp.sql("docker_sites").insert(pdata)
if not get.pid:
break
domain_list = public.M("domain").where("pid=?", (old_site["id"],)).field("name").find()
for domain in domain_list:
dp.sql("docker_domain").insert({
"name": domain,
"pid": get.pid,
"port": "80" if ":" not in domain else domain.split(":")[1],
"addtime": old_site["addtime"],
})
break
public.writeFile("{}/synced_docker_sites.pl".format(self.sites_config_path), "True")
return public.returnResult(True)
# 2024/11/13 14:59 获取分类列表
def get_site_types(self, get):
'''
@name 获取分类列表
'''
now_time = public.getDate()
check_default_result = dp.sql("docker_site_classifys").where("name=?", ("默认分类",)).find()
if not check_default_result:
dp.sql("docker_site_classifys").insert({
"id": 0,
"name": "默认分类",
"ps": "默认分类",
"addtime": now_time
})
check_stop_result = dp.sql("docker_site_classifys").where("name=?", ("已停止的网站",)).find()
if not check_stop_result:
dp.sql("docker_site_classifys").insert({
"id": -2,
"name": "已停止的网站",
"ps": "已停止的网站",
"addtime": now_time
})
# 查询所有分类
classify_list = dp.sql("docker_site_classifys").order("id desc").select()
# 2024/11/28 15:09 排序,id为0的默认分类排在最前面,-2为已停止的网站排在第二
new_classify_list = []
for classify in classify_list:
if classify["id"] == 0:
new_classify_list.insert(0, classify)
elif classify["id"] == -2:
new_classify_list.insert(1, classify)
else:
new_classify_list.append(classify)
return public.returnResult(True, data=new_classify_list)
# 2024/11/13 15:19 添加分类
def add_site_type(self, get):
'''
@name 添加分类
'''
get.name = get.get("name", "")
if not get.name:
return public.returnResult(status=False, msg="name不能为空!")
get.ps = get.get("ps", "")
now_time = public.getDate()
get.id = dp.sql("docker_site_classifys").insert({
"name": public.xssencode2(get.name),
"ps": public.xssencode2(get.ps),
"addtime": now_time
})
return public.returnResult(msg="添加成功!")
# 2024/11/13 15:20 编辑分类
def edit_site_type(self, get):
'''
@name 编辑分类
'''
get.id = get.get("id", "")
if not get.id:
return public.returnResult(status=False, msg="id不能为空!")
get.name = get.get("name", "")
if not get.name:
return public.returnResult(status=False, msg="name不能为空!")
get.ps = get.get("ps", "")
now_time = public.getDate()
dp.sql("docker_site_classifys").where("id=?", (get.id,)).update({
"name": public.xssencode2(get.name),
"ps": public.xssencode2(get.ps),
"addtime": now_time
})
return public.returnResult(msg="编辑成功!")
# 2024/11/13 15:20 删除分类
def del_site_type(self, get):
'''
@name 删除分类
'''
get.id = get.get("id", "")
if not get.id:
return public.returnResult(status=False, msg="id不能为空!")
dp.sql("docker_site_classifys").where("id=?", (get.id,)).delete()
# 2024/11/13 15:21 将所有docker_sites里面的classify字段设置为0
dp.sql("docker_sites").where("classify=?", (get.id,)).update({"classify": 0})
return public.returnResult(msg="删除成功!")
# 2024/11/13 15:24 为指定网站设置分类
def set_site_type(self, get):
'''
@name 为指定网站设置分类
'''
get.id = get.get("id", None)
if get.id is None:
return public.returnResult(status=False, msg="id不能为空!")
get.classify = get.get("classify", 0)
if type(get.id) == str:
try:
get.id = json.loads(get.id)
except:
return public.returnResult(status=False, msg="id参数错误!")
for id in get.id:
dp.sql("docker_sites").where("id=?", (id,)).update({"classify": get.classify})
return public.returnResult(msg="设置成功!")
def GetSiteDomain(self,get):
"""
@name 获取网站域名对应的站点名
@param cert_list 证书域名列表
@auther hezhihong
return 证书域名对应的站点名字典,如证书域名未绑定则为空
"""
all_site=[] #所有站点名列表
cert_list=[] #证书域名列表
site_list=[] #证书域名列表对应的站点名列表
all_domain = [] #所有域名列表
try:
cert_list=json.loads(get.cert_list)
except:pass
result={}
#取所有站点名和所有站点的绑定域名
all_sites=public.M('docker_sites').field('name').select()
for site in all_sites:
all_site.append(site['name'])
if not cert_list:continue
tmp_dict={}
tmp_dict['name']=site['name']
pid = public.M('docker_sites').where("name=?",(site['name'],)).getField('id')
domain_list=public.M('docker_domain').where("pid=?",(pid,)).field('name').select()
for domain in domain_list:
all_domain.append(domain['name'])
#取证书域名所在的所有域名列表
site_domain=[]#证书域名对应的站点名列表
if cert_list and all_domain:
for cert in cert_list:
d_cert=''
if re.match("^\*\..*",cert):
d_cert=cert.replace('*.','')
for domain in all_domain:
if cert == domain:
site_domain.append(domain)
else:
replace_str=domain.split('.')[0]+'.'
if d_cert and d_cert==domain.replace(replace_str,''):
site_domain.append(domain)
#取证书域名对应的站点名
for site in site_domain:
site_id=public.M('docker_domain').where("name=?",(site,)).getField('pid')
site_name=public.M('docker_sites').where("id=?",(site_id,)).getField('name')
site_list.append(site_name)
site_list=sorted(set(site_list),key=site_list.index)
result['all']=all_site
result['site']=site_list
return result
# 2024/11/18 09:30 获取防跨站状态和运行目录信息
def GetDirUserINI(self, get):
'''
@name 获取防跨站状态和运行目录信息
'''
get.id = get.get("id", None)
if not get.id:
return public.returnResult(status=False, msg="id不能为空!")
find_result = dp.sql("docker_sites").where("id=?", get.id).find()
if not find_result:
return public.returnResult(status=False, msg="未找到此ID【{}】的站点信息!".format(get.id))
data = {'userini': False}
user_ini_file = os.path.join(find_result["path"], ".user.ini")
try:
user_ini_conf = public.readFile(user_ini_file)
except OSError:
user_ini_conf = {}
if user_ini_conf and "open_basedir" in user_ini_conf:
data['userini'] = True
# 2024/11/18 09:35 获取runpath
p_data = {}
path = find_result["path"]
filename = os.path.join(public.get_setup_path(), 'panel/vhost/nginx', find_result["name"] + '.conf')
if os.path.exists(filename):
conf = public.readFile(filename)
rep = '\s*root\s+(.+);'
tmp1 = re.search(rep, conf)
if tmp1: path = tmp1.groups()[0]
if find_result["path"] == path:
p_data['runPath'] = '/'
else:
p_data['runPath'] = path.replace(find_result["path"], '')
dirnames = []
dirnames.append('/')
if not os.path.exists(find_result["path"]): os.makedirs(find_result["path"])
dirnames = []
if os.path.exists(find_result["path"]):
dirnames = ['/' + entry.name for entry in os.scandir(find_result["path"]) if entry.is_dir() and not entry.is_symlink() and entry.name != '.well-known' and entry.name != "proxy_cache_dir"]
p_data['dirs'] = ['/'] + dirnames
data['runPath'] = p_data
return public.returnResult(True, data=data)
# 2024/11/18 10:43 设置防跨站
def SetDirUserINI(self, get):
'''
@name 设置防跨站
'''
get.id = get.get("id", None)
if not get.id:
return public.returnResult(status=False, msg="id不能为空!")
get.status = get.get("status", 0)
find_result = dp.sql("docker_sites").where("id=?", get.id).find()
if not find_result:
return public.returnResult(status=False, msg="未找到此ID【{}】的站点信息!".format(get.id))
user_ini_file = os.path.join(find_result["path"], ".user.ini")
conf = public.readFile(user_ini_file)
if os.path.exists(user_ini_file): public.ExecShell("chattr -i " + user_ini_file)
if int(get.status) == 0:
if conf and "open_basedir" in conf:
rep = "\n*open_basedir.*"
conf = re.sub(rep, "", conf)
if not conf:
os.remove(user_ini_file)
else:
public.writeFile(user_ini_file, conf)
if os.path.exists(user_ini_file): public.ExecShell("chattr +i " + user_ini_file)
else:
if conf and "session.save_path" in conf:
rep = "session.save_path\s*=\s*(.*)"
s_path = re.search(rep, conf).groups(1)[0]
public.writeFile(user_ini_file, conf + '\nopen_basedir={}/:/tmp/:{}'.format(find_result["path"], s_path))
else:
public.writeFile(user_ini_file, 'open_basedir={}/:/tmp/'.format(find_result["path"]))
if os.path.exists(user_ini_file): public.ExecShell("chattr +i " + user_ini_file)
return public.returnResult(msg="设置成功!")
# 2024/11/18 16:32 刷新nginx_conf
def reload_nginx_conf(self, get):
'''
@name 刷新nginx_conf
'''
get.siteName = get.get("siteName", None)
if get.siteName is None:
site_names = dp.sql("docker_sites").field("name").select()
reload_result = []
for site_name in site_names:
get.site_name = site_name["name"]
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
reload_result.append(
{"site_name": get.site_name, "status": False, "msg": "读取配置文件失败,请删除网站重新添加!"})
continue
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
reload_result.append({"site_name": get.site_name, "status": False, "msg": update_result["msg"]})
else:
get.site_name = get.siteName
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置网站目录成功")
# 2024/11/20 10:56 获取指定网站的PHP信息
def get_php_project_info(self, get):
'''
@name 获取指定网站的PHP信息
'''
get.id = get.get("id", None)
if not get.id:
return public.returnResult(status=False, msg="id不能为空!")
find_result = dp.sql("docker_sites").where("id=?", get.id).find()
if not find_result:
return public.returnResult(status=False, msg="未找到此ID【{}】的站点信息!".format(get.id))
try:
service_info = json.loads(find_result["service_info"])
except:
return public.returnResult(status=False, msg="ID【{}】站点的service_info读取失败,请重新添加网站再试!".format(get.id))
php_name = service_info["name"].split(":")[0]
php_version = service_info["name"].split(":")[1]
php_project_info = {
"used": {"name": php_name, "version": php_version},
}
# 2024/11/20 11:00 获取php运行环境列表
from mod.project.docker.runtime.runtimeManage import RuntimeManage
runtimeManage = RuntimeManage()
get.runtime_type = "php"
get.row = 20000
php_runtime_list = runtimeManage.get_runtime_list(get)
if not php_runtime_list["status"]: return php_runtime_list
runtime_list = php_runtime_list["data"]
runtime_names = []
for runtime in runtime_list:
if runtime["status"] != "normal": continue
runtime_names.append({"name": runtime["name"], "version": runtime["version"]})
php_project_info["runtime_list"] = runtime_names
return public.returnResult(True, data=php_project_info)
# 2024/11/20 11:10 切换指定网站的PHP版本
def switch_php_version(self, get):
'''
@name 切换指定网站的PHP版本
'''
get.id = get.get("id", None)
if not get.id:
return public.returnResult(status=False, msg="id不能为空!")
get.runtime_name = get.get("runtime_name", None)
if not get.runtime_name:
return public.returnResult(status=False, msg="runtime_name不能为空!")
find_result = dp.sql("docker_sites").where("id=?", get.id).find()
if not find_result:
return public.returnResult(status=False, msg="未找到此ID【{}】的站点信息!".format(get.id))
try:
service_info = json.loads(find_result["service_info"])
except:
return public.returnResult(status=False, msg="ID【{}】站点的service_info读取失败,请重新添加网站再试!".format(get.id))
service_info["name"] = get.runtime_name
dp.sql("docker_sites").where("id=?", get.id).update({"service_info": json.dumps(service_info)})
# 2024/11/20 11:14 替换项目env里面的IMAGE_NAME,
public.ExecShell("sed -i 's/^IMAGE_NAME=.*/IMAGE_NAME={}/' {}/.env".format(get.runtime_name, service_info["project_path"]))
public.ExecShell("docker-compose -f {}/docker-compose.yml down".format(service_info["project_path"]))
public.ExecShell("docker-compose -f {}/docker-compose.yml up -d".format(service_info["project_path"]))
public.serviceReload()
return public.returnResult(msg="设置成功!")
# 2024/11/22 12:02 获取指定网站的所有域名
def GetSiteDomains(self, get):
'''
@name 获取指定网站的所有域名
'''
get.id = get.get("id", None)
if not get.id:
return public.returnResult(status=False, msg="id不能为空!")
data = {}
n_list = []
from sslModel import dataModel
get.docker_site_id = get.id
dns_data = dataModel.main().get_domain_dns_config(get)
for domain in dns_data:
tmp = {'id': domain['domain_id'], 'name': domain['name'], 'binding': False, 'apply_ssl': 1, 'dns_status': domain['status'], 'root_domain_id': domain['domain_id']}
if public.checkIp(domain['name']): tmp['apply_ssl'] = 0
n_list.append(tmp)
data['domains'] = n_list
return data
def get_domian_dns_dic(self):
try:
from sslModel import dataModel
data = dataModel.main().get_domain_dns_config(public.dict_obj())
return {i["name"]: {"dns_status": i["status"], "root_domain_id": i["domain_id"]} for i in data}
except:
return {}
# 2024/11/26 09:17 部署指定let's encrypt证书
def set_cert_to_site(self, get):
'''
@name
'''
from mod.project.docker.sites.sslManage import Acme_V2
acme = Acme_V2()
exclude_data = acme.get_exclude_hash(get)
ssl_hash = exclude_data['exclude_hash_let'].get(get.index)
if not ssl_hash:
return public.returnResult(False, "未找到此证书")
get.ssl_hash = ssl_hash
from mod.project.docker.sites.sslManage import SslManage
ssl_manage = SslManage()
return ssl_manage.SetCertToSite(get)
# 2024/11/28 16:50 设置proxy_buffering状态
def set_proxy_buffering(self, get):
'''
@name 设置proxy_buffering状态
'''
get.site_name = get.get("site_name", None)
if not get.site_name:
return public.returnResult(status=False, msg="site_name不能为空!")
get.status = get.get("status", 0)
get.proxy_path = get.get("proxy_path", None)
if not get.proxy_path:
return public.returnResult(status=False, msg="proxy_path不能为空!")
get.proxy_json_conf = self.read_json_conf(get)
if not get.proxy_json_conf:
return public.returnResult(status=False, msg="读取配置文件失败,请删除网站重新添加!")
for proxy_info in get.proxy_json_conf["proxy_info"]:
if not "proxy_pass" in proxy_info: continue
if not proxy_info["proxy_pass"]: continue
if get.proxy_path == proxy_info["proxy_path"]:
print(get.proxy_path)
print(proxy_info["proxy_path"])
if int(get.status) == 1:
proxy_info["proxy_buffering"] = True
else:
proxy_info["proxy_buffering"] = False
break
update_result = self.update_nginx_conf(get)
if not update_result["status"]:
return public.returnResult(status=False, msg=update_result["msg"])
public.serviceReload()
return public.returnResult(msg="设置成功!")