Nginx 与 Flask 搭建 HTTP/HTTPS 服务器

环境搭建

1、Nginx 安装

sudo apt install nginx

安装完毕,浏览器或者curl访问 http://<Nginx服务器IP> ,测试Nginx服务是否正常。

2、Flask 安装

# 安装 python3 与 pip3 工具
sudo apt install python3 python3-pip
# 使用 pip3 安装 flask
pip3 install flask

3、OpenSSL 生成 https 所需秘钥与证书

# 创建一个私钥
sudo openssl genrsa -des3 -out server.key 2048
# 移除私钥中的密码短语(可选,但推荐在测试环境中这样做)
sudo openssl rsa -in server.key -out server_no_pass.key
# 生成自签名证书请求
sudo openssl req -new -key server_no_pass.key -out server.csr
# 生成自签名证书,有效期为 365 天 
sudo openssl x509 -req -days 365 -in server.csr -signkey server_no_pass.key -out server.crt

4、配置 Nginx 代理到 Flask

备份 /etc/nginx/sites-available/default 文件,超级权限修改 default 文件,支持 http/https 代理。

# 备份 Nginx 配置文件
sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak
# 配置代理
sudo vim /etc/nginx/sites-available/default

添加以下内容至 default 文件

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name localhost.linux;

    location / {
        # 代理到 Flask 应用
        proxy_pass http://localhost:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

server {  
    listen 443 ssl;  
    server_name localhost.linux;  
  
    # SSL 配置,包括证书和私钥  
    ssl_certificate /etc/nginx/certificate/server.crt;
    ssl_certificate_key /etc/nginx/certificate/server_no_pass.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    location / {
        # 代理到 Flask 应用
        proxy_pass http://127.0.0.1:5000;  
        proxy_set_header Host $host;  
        proxy_set_header X-Real-IP $remote_addr;  
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  
        proxy_set_header X-Forwarded-Proto $scheme;  
    }  
}

5、重启 Nginx 服务

# 重启 Nginx 服务
sudo service nginx reload
# 或者使用以下命令
sudo nginx -s reload

6、Flask Demo 程序

  • 在项目目录下创建 demo.py 测试 Flask 服务器
    from flask import Flask, request, render_template, jsonify, Response
    from werkzeug.middleware.proxy_fix import ProxyFix
    
    app = Flask(__name__)
    
    # 应用 ProxyFix 中间件来修复代理环境中的请求信息,没有该行内容则Flask获取的请求IP 为 Nginx 代理 ip 127.0.0.1
    app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_host=1, x_proto=1)
    
    @app.route("/", methods=["GET", "PUT"])
    def index():
        # 打印请求头
        headers = request.headers
        for header, value in headers.items():
            print(f"{header}: {value}")
    
        # 打印请求 IP
        print(request.remote_addr)
        xml_string = '<html><h1>Flask Demo</h1><p>这是一个Flask APP 示例</p></html>'
        response = Response(xml_string, status=200)
        return response
    
    if __name__ == "__main__":
        print("flask starting ...", flush=True)
    app.run(debug=True) # 如果不使用 5000端口,可以使用 port=1234切换端口
    
  • 执行 demo 测试效果
    # 运行 demo
    python3 demo.py &
    # curl get 内容
    curl -X GET http://127.0.0.1
    

7、服务器开机自启动

  • python 代码所在目录创建 start.sh
    python3 ~/nginx/autopic/demo.py &
    
  • 使用 cron 开机执行任务
    crontab -e
    # flask 开机自启动 以绝对路径启动服务,保证日志在预期目录生成
    @reboot cd /home/username/nginx/autopic && /home/username/nginx/autopic/start.sh
    

8、简单的网页服务器

from flask import Flask, request, render_template, jsonify, Response, send_from_directory,send_file,abort
from pathlib import Path 
from werkzeug.middleware.proxy_fix import ProxyFix
import xml.etree.ElementTree as ET # xml
import logging
import jwt
import datetime
import secrets
import os
import base64  
from xml.etree import ElementTree
import binascii
import timetool
import master_camera
from csvmode import csv_file

# 配置 模板文件(html)目录为 html;后续 html 文件放在对应目录下即可
app = Flask(__name__, template_folder='html')

# 应用 ProxyFix 中间件来修复代理环境中的请求信息,没有该行内容则Flask获取的请求IP 为 Nginx 代理 ip 127.0.0.1
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_host=1, x_proto=1)

# 配置日志系统
log_file = "app.log"  # 日志文件名
logging.basicConfig(
    filename=log_file,
    level=logging.INFO,
    format="%(asctime)s:%(levelname)s:%(message)s",
)

@app.route("/xxx", methods=["GET"])
def index():
    xml_string = "<html><h1>Flask Demo</h1><p>这是一个Flask APP 示例</p><p>阴云不蔽月,依旧照我心。何须念桑梓,心安即吾乡。</p></html>"
    response = Response(xml_string, status=200)
    logging.info(xml_string)
    return response

@app.route("/", methods=["GET"])
@app.route("/home", methods=["GET"])
def home():
    logging.info("/HOME")
    # 前面初始化 Flask 时配置了 template_folder ,访问的 home/index.html 在 html/home/index.html
    return render_template('home/index.html'), 200

@app.route("/360", methods=["GET"])
def T360():
    return render_template('test/360.html'), 200

@app.route("/code", methods=["GET"])
def code_flask():
    return render_template('code/index.html'), 200

@app.route("/demo", methods=["GET"])
def demo_flask():
    return render_template('demo/index.html'), 200

@app.route("/about", methods=["GET"])
def about_flask():
    return render_template('about/index.html'), 200

# 设置视频文件的目录
VIDEO_DIR = '.'  
BASE_DIR = Path(__file__).resolve().parent

# 创建一个路由来服务视频文件
@app.route('/<path:filepath>')
def serve_file(filepath):  
    # 构建文件的完整路径  
    file_path = BASE_DIR / filepath  
      
    # 确保文件存在且是文件而不是目录  
    if not file_path.exists() or not file_path.is_file():  
        abort(404)  

    # 禁止访问某些敏感目录或文件  
    # 例如,不允许访问'.env'文件或任何隐藏文件  
    if any(file_path.parts[-1].startswith(prefix) for prefix in ('.', '_')):  
        abort(403)  
      
    # 使用send_file发送文件  
    # return send_file(str(file_path), as_attachment=False, mimetype='video/mp4')
    return send_file(str(file_path), as_attachment=False)

@app.errorhandler(404)  
def page_not_found(e):  
    return render_template('404/index.html'), 404

if __name__ == "__main__":
    # 在生产环境中,应该使用 WSGI 服务器(如Gunicorn)和反向代理(如Nginx)
    # 这里仅用于开发和测试目的
    print("flask starting ...", flush=True)
    app.run(debug=True)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值