You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 18:04:54