Flask应用与Flarum论坛同时运行冲突问题求助
Flask与Flarum共存时访问冲突问题解决方案
问题概述
Flask脚本后台运行时,同域名下的Flarum论坛无法访问,提示“Not Found”;停止Flask进程后论坛恢复正常。已确认两者无共享数据库连接,日志未发现明确错误,仅在关闭Python脚本后论坛恢复服务。
核心冲突原因
从代码和部署方式分析,Flask直接占用了主域名的根路径与web端口,导致本该路由到Flarum的请求被Flask拦截,而Flask没有对应路由,因此返回404错误。具体来说:
- PHP脚本请求的是主域名根路径
https://neei-utad.pt/,而Flask的路由恰好是根路径@app_s.route('/', methods=['POST']); - Flask默认使用
app.run()启动开发服务器,会直接绑定端口(如80/443),抢占cPanel自带web服务器(Apache/Nginx)的请求处理权,导致Flarum的PHP请求无法被正常转发。
解决步骤
1. 调整Flask路由至子路径,避免根路径冲突
将Flask应用的处理路由改为子路径(如/submit),修改submit.py中的路由定义:
@app_s.route('/submit', methods=['POST']) @csrf.exempt def execute(): # 原业务逻辑保持不变 ...
同时更新PHP脚本中的请求URL,指向Flask的子路径:
$url = 'https://neei-utad.pt/submit'; // 修改为Flask部署的子路径
2. 用WSGI服务器部署Flask(替代开发服务器)
cPanel环境下禁止直接使用Flask开发服务器,改用Gunicorn配合Passenger部署:
- 安装Gunicorn:
pip install gunicorn - 创建
passenger_wsgi.py作为Passenger的入口文件:
import sys import os # 将Flask应用所在目录添加到Python路径 sys.path.insert(0, os.path.dirname(__file__)) from submit import app_s as application # 导入Flask应用实例
- 在cPanel的「Python应用」面板中创建新应用,选择对应Python版本,指定应用根目录和启动文件为
passenger_wsgi.py,设置部署路径为/submit。
3. 停止手动运行的Flask开发服务器
在cPanel中关闭后台运行的Flask脚本,确保仅保留通过Passenger部署的WSGI版本,彻底避免端口冲突。
代码修正示例
修改后的Flask路由(submit.py)
@app_s.route('/submit', methods=['POST']) @csrf.exempt def execute(): try: caminho_arquivo_para_upload = bleach.clean(request.form['target_file']) nome_pasta = bleach.clean(request.form['folder_name']) nome = bleach.clean(request.form['name']) email = bleach.clean(request.form['email']) logger.info("target_file=%s, folder_name=%s, name=%s, email=%s", caminho_arquivo_para_upload, nome_pasta, nome, email) if not caminho_arquivo_para_upload or not nome_pasta or not nome or not email: logger.error("Dados em falta: target_file=%s, folder_name=%s, name=%s, email=%s", caminho_arquivo_para_upload, nome_pasta, nome, email) return jsonify({'status': 'FALHA', 'erro': 'Dados em falta'}), 400 if caminho_arquivo_para_upload.startswith('python/'): caminho_arquivo_para_upload = caminho_arquivo_para_upload[len('python/'):] caminho_absoluto_arquivo = os.path.join(diretorio_atual, caminho_arquivo_para_upload) logger.info(f"Caminho absoluto do arquivo recebido: {caminho_absoluto_arquivo}, nome da pasta: {nome_pasta}, nome: {nome}, email: {email}") if servico is None: enviar_email(nome, email, False) remover_da_base_de_dados(nome_pasta) return jsonify({'status': 'FALHA', 'erro': 'Serviço não disponível'}), 400 try: scan_result = scan_file_with_virustotal(api_key, caminho_absoluto_arquivo) if 'scan_id' in scan_result: logger.info("ID do Scan: %s", scan_result['scan_id']) logger.info("Resultado do Scan: %s", scan_result['verbose_msg']) if 'positives' in scan_result: logger.error("Número de positivos: %s", scan_result['positives']) logger.info("Caminho do arquivo recebido: %s", caminho_absoluto_arquivo) diretorio_uploads = os.path.join(diretorio_atual, 'uploads') deletar_arquivo_especifico(diretorio_uploads, caminho_absoluto_arquivo) verificar_e_deletar_se_necessario(diretorio_uploads) enviar_email(nome, email, True) remover_da_base_de_dados(nome_pasta) logger.error("O script será encerrado devido à detecção de vírus") return jsonify({'status': 'FALHA', 'erro': 'Vírus detectados'}), 400 else: logger.info("Nenhum vírus encontrado: %s", scan_result['verbose_msg']) except Exception as e: logger.exception("Erro durante o processo de escaneamento") return jsonify({'status': 'FALHA', 'erro': str(e)}), 400 try: id_pasta = criar_pasta(servico, id_pai, nome_pasta) logger.info(f"Pasta criada com ID '{id_pasta}'") if not os.path.isfile(caminho_absoluto_arquivo): raise FileNotFoundError(f"Arquivo não encontrado: {caminho_absoluto_arquivo}") fazer_upload_arquivo_drive(servico, caminho_absoluto_arquivo, id_pasta) criar_arquivo_texto(nome, email, id_pasta) logger.info(f"Arquivos enviados com sucesso para a pasta com ID '{id_pasta}'.") except Exception as e: enviar_email(nome, email, False) remover_da_base_de_dados(nome_pasta) logger.exception("Erro durante o processo de upload") return jsonify({'status': 'FALHA', 'erro': str(e)}), 400 logger.info("Caminho do arquivo recebido: %s", caminho_absoluto_arquivo) diretorio_uploads = os.path.join(diretorio_atual, 'uploads') deletar_arquivo_especifico(diretorio_uploads, caminho_absoluto_arquivo) verificar_e_deletar_se_necessario(diretorio_uploads) return jsonify({'status': 'SUCESSO'}) except Exception as e: logger.exception("Erro ao executar o script") return jsonify({'status': 'FALHA', 'erro': str(e)}), 400
修改后的PHP调用脚本
function executar_script_python($target_file, $folder_name, $nome, $email) { $url = 'https://neei-utad.pt/submit'; // 更新为Flask的子路径 $data = array( 'target_file' => $target_file, 'folder_name' => $folder_name, 'name' => $nome, 'email' => $email ); escrever_log("Dados enviados para o script Python: " . json_encode($data)); $options = array( 'http' => array( 'header' => "Content-type: application/x-www-form-urlencoded ", 'method' => 'POST', 'content' => http_build_query($data), ), ); $context = stream_context_create($options); $result = @file_get_contents($url, false, $context); if ($result === FALSE) { $error = error_get_last(); escrever_log("Erro ao executar o script Python: " . $error['message']); redirecionar_para('../Apontamentos/ConfirmacionFail.html'); } escrever_log("Resposta recebida do script Python: " . $result); $response = json_decode($result, true); if ($response === null) { escrever_log("Erro ao decodificar a resposta JSON do script Python"); redirecionar_para('../Apontamentos/ConfirmacionFail.html'); } if ($response['status'] === 'SUCESSO') { redirecionar_para('../Apontamentos/ConfirmacionSuccesfully.html'); } else { escrever_log("O script Python reportou falha: " . (isset($response['erro']) ? $response['erro'] : 'Erro desconhecido')); redirecionar_para('../Apontamentos/ConfirmacionFail.html'); } }
内容的提问来源于stack exchange,提问作者NEEI UTAD
相关产品推荐
相关产品推荐

