如题,记录告警平台从原来的layui升级到Vue,并实现Flask+Vue前后端分离,记录前后端三种解决跨域的方式(有点像茴香豆的四种写法?没事,技多不压身)
Flask解决跨域
不需要render_template了,只需要提供API给前端提供数据,需要解决跨域的问题,或者通过前端代理解决,或者通过Nginx代理解决(一共三种)
from flask import Flask, render_template
from flask_cors import *
"""flask-cors解决跨域问题的主角"""
from models import model_to_dict
from models import Alarm, AlarmGroup, db
from fake_data_generator import generate_fake_data
app = Flask(__name__)
CORS(app, resources={r'/*': {'origins': 'http://localhost:5173'}})
# CORS(app, resources={r'/*': {'origins': '*'}})
"""将导入的CORS应用,指定来源为任意,或者本地的5173"""
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:123456@localhost:5432/yinyu'
db.init_app(app)
@app.route('/')
def hello_world():
## 测试数据库连接成功
alarm = Alarm.query.first()
print(alarm.name)
return alarm.name
"""为了避免有时候容器没起,数据库没连上,这里做个测试,连上了,页面就会显示数据库中的一个名字"""
@app.route('/api/alarm',methods=['GET'])
def get_alarms():
alarms = Alarm.query.all()
alarms_list = [model_to_dict(a) for a in alarms]
"""query查到的是一个ORM对象,在model.py里面有model_to_dict的方案,在头部导入了"""
return alarms_list
if __name__ == '__main__':
with app.app_context():
db.create_all()
generate_fake_data()
"""携带上下文,清空数据库,重新生成数据"""
app.run()
Vue操作
通过axios模块,安装npm install axios
,在src路径下创建axios.js
import axios from 'axios'
const instance = axios.create({
baseURL: 'http://localhost:5000'
//指定请求的基本地址,也就是后面的api会接在这个的后面的
})
export default instance
//还有一些额外的配置可以添加,本次不深究
app.vue
是Vue的程序入口文件,配置axios请求后端
<template>
<div>
<h1>{{ message }}</h1>
</div>
</template>
<script>
import axios from "./axios"
//注意,这里需要引入上一步的axiox,同级目录
export default {
data() {
return {
message: ''
}
},
mounted() {
//使用axios请求/api/alarm,也就是请求baseURL+/api/alarm
axios.get('/api/alarm', {
})
.then(response => {
console.log(response.data); // 打印响应数据
this.message = response.data; // 将响应数据存储在 message 中
})
.catch(error => {
console.log(error); // 打印错误信息
})
}
}
</script>
<style lang="scss" scoped>
.logo {
width: 120px;
height: 120px;
}
nav {
padding: 10px;
a {
padding: 10px;
}
}
</style>
Vue 代理解决跨域
vite.config.js
是vite的配置文件,可以在这里配置一个代理,从而解决跨域问题
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
server: {
//
// proxy: {
// "^/api": {
// target: "http://localhost:5000",
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api/, ""),
// },
// },
//以上被注释掉的部分就是有效内容,为了避免冲突,使用Flask即可。
},
plugins: [
vue(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
在经历过404(链接错了)、500(请求不到后端,本质还是链接错了),ERR_SSL_PROTOCOL_ERROR(AI补全补了个https,没注意到),和跨域错误后
完事,收工!
Nginx解决跨域
server {
listen 80;
server_name api.example.com;
location / {
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;
# 上面的set_header就是解决跨域的配置
}
}
server {
listen 80;
server_name app.example.com;
location /api {
rewrite ^/api/(.*) /$1 break;
proxy_pass http://api.example.com;
}
location / {
root /var/www/app;
try_files $uri $uri/ /index.html;
}
}