python web bottle ajax请求 和 websocket

解决问题:
1、bottle版本支持 ajax 请求处理:发现最新的13好像是可以的
2、websocket 复用 web 服务端口:

操作步骤:
1、将下边 test.py test.html 两个文件放在一个目录下。
2、运行python test.py
3、浏览器打开地址 http://localhost:8080
4、打开浏览器调试工具。

数据
python test.py

import json
import time

from gevent import queue
from bottle import route, run, static_file, request, Bottle, abort
from gevent.pywsgi import WSGIServer
from geventwebsocket import WebSocketError
from geventwebsocket.handler import WebSocketHandler


class HTTP_APP(Bottle):
    def __init__(self, user="admin", ip="127.0.0.1", port=8080):
        """

        :param user:
        :param ip: 服务地址
        :param port: 服务端口
        """
        Bottle.__init__(self)
        self.ip = ip
        self.port = port

        # 测试websocket,添加信息字典
        self._testUsers = {
    
    }

    def __del__(self):
        try:
            if self.server != None:
                self.server.close()
                # self.server.close_server()
        except:
            pass

    def start_server(self):
        """
        启动websocket 服务
        :return:
        """
        self.server = WSGIServer(("0.0.0.0", self.port), self, handler_class=WebSocketHandler)
        self.server.serve_forever()

    def close_server(self):
        if self.server != None:
            self.server.close()
            self.server = None

    def register_http(self):
        """
        web 服务注册
        :return:
        """

        @self.error(404)
        def error404(error):
            return u'404'


        @self.route('/res/<resname:path>')
        def res(resname):
            """
             加载资源数据的路由
            :param resname:
            :return:
            """
            return static_file(resname, root="./res")


        @self.route('/')
        def vote():
            """
            主页面的路由
            :return:
            """
            return static_file("test.html", root="./")

        # @self.hook('before_request')
        # 网上说的要用到hoot方式
        # def validate():
        #     """使用勾子处理页面或接口访问事件"""
        #     # 让bottle框架支持jquery ajax的RESTful风格的PUT和DELETE等请求
        #     """使用勾子处理页面或接口访问事件"""
        #     if request.method == 'POST' and request.POST.get('_method'):
        #         request.environ['REQUEST_METHOD'] = request.POST.get('_method', '').upper()
        #         if request.POST.get('_form'):
        #             request.environ['REQUEST_FORM'] = request.POST.get('_form', '')
        #

        # 处理ajax 请求。这个需要指定method
        @self.route('/api/<apiname>', method='POST')
        def asyncApi(apiname):
            print(apiname)
            # print(request.json)
            a = request

            # 读取通过表单提交的数据,我一般不用表单方式
            # username = request.forms.get('username')
            # password = request.forms.get('password')

            # 读取post的参数,其他方式需要查看,a 的字典值。
            postdata =request.body.readline()
            req_data = json.loads(postdata)

            print("request: ", req_data)
            res = {
    
    
                "code" : 0,
                "msg" : "",
                "data" : []
            }

            if req_data["action"]=="get":pass

            if req_data['action']=="add":
                self._testUsers[req_data['user']]={
    
    
                "user" : req_data['user'],
                "ip" : "10.10.10.10",
                "port" :req_data['port'],
                "stopDate" : req_data['stopDate'],
                "status" : False
                }

            if req_data['action'] =="del":
                del self._testUsers[req_data['user']]

            if req_data['action'] == "start":
                self._testUsers[req_data['user']]["status"] = True

            if req_data['action'] == "stop":
                self._testUsers[req_data['user']]["status"] = False

            res["data"] = [ v for k,v in self._testUsers.items() ]

            # 返回为序列化数据,否则报500错误
            r = json.dumps(res)
            print("response:", res)
            return res

        # websocket 服务
        @self.route('/ws')
        def handle_websocket():
            # 页面打开一次,起一个请求
            wsock = request.environ.get('wsgi.websocket')

            # clientid = wsock.environ["REMOTE_ADDR"]
            clientid = wsock.handler.client_address[0]
            # print(clientid,clientid1)
            # user_socket_dict[username] = user_socket

            if not wsock:
                abort(400, 'Expected WebSocket request.')

            while True:
                try:
                    message = wsock.receive()
                    print("Your message was: %r" % message)
                    wsock.send("Your message was: %r" % message)
                except WebSocketError:
                    break



# https://blog.csdn.net/weixin_28938385/article/details/112903651

http_server = HTTP_APP()
http_server.register_http()

http_server.start_server()
# http_server.run()

http test.html

<!DOCTYPE html>
<html style="height: 100%">
	<head>
		<meta charset="utf-8">
		<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.0-alpha1/css/bootstrap.min.css" rel="stylesheet">
	</head>
	<body style="height: 100%; margin: 0" onmousedown="whichButton(event)">
	<div class="container" id="containerIdShow">

		<div class="row">
			<div class="col">
				<p class="text-left">用户单位</p>
				
			</div>		
			<div class="col">
				<p class="text-left">端口</p>
				
			</div>
			<div class="col">
				<p class="text-left">结束时间</p>
				
			</div>
			<div class="col">
				<p class="text-left">状态</p>
				
			</div>
			<div class="col">
				<p class="text-left">操作</p>
				
			</div>					
		</div>
		<div class="row">
			<div class="col">
				<input class="form-control" type="text" placeholder="" v-model="user" maxLength="64">
			</div>
			<div class="col">
				<input class="form-control" type="number" placeholder="[8800-8900]" v-model="port" maxLength="4">
			</div>
			<div class="col">
				<input class="form-control" type="date" placeholder="" v-model="stopDate" :min="dateXiaXian">
			</div>
			<div class="col">
			</div>
			<div class="col">
				<button type="button" class="btn btn-outline-primary btn-sm"  @click="addUser();console.log(123)" >添加</button>
			</div>					
		</div>
		<li class="list-group-item nav-item" >说明:web端php只能起一个进程,在linux环境下执行系统命令出于安全考虑不开放。请手动进入到目录启动</li>
			<div class="row" v-for="(item,index) in userList">
				<div class="col">
					<p>
						<span v-text='item.user'></span>
						<a :href="'./index.html?ip='+item.ip+'&port='+item.port"  target="_blank" class="btn btn-outline-warning btn-sm" >投屏</a>
						<a :href="'./manage.html?ip='+item.ip+'&port='+item.port" target="_blank" class="btn btn-outline-warning btn-sm" >管理</a>
					</p>
				</div>		
				<div class="col">
					<p><span v-text='item.port'></span></p>
				</div>		
				<div class="col">
					<p><span v-text='item.stopDate'></span></p>
				</div>		
				<div class="col">
					<p v-if="item.status">运行</p><p v-else>未运行</p>
				</div>		
				<div class="col">
					<button type="button" class="btn btn-outline-warning btn-sm" @click="exitUser(item.user, item.port)" >删除</button>
					<button type="button" class="btn btn-outline-success btn-sm" :disabled="item.status" @click="startUser(item.user)" >启动</button>
					<button type="button" class="btn btn-outline-secondary btn-sm" :disabled="!item.status" @click="stopUser(item.user, item.port)" >停止</button>
				</div>					
			</div>
		
	</div>
		<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script>
		<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-gl/dist/echarts-gl.min.js"></script>
		<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-stat/dist/ecStat.min.js"></script>
		<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/extension/dataTool.min.js"></script>
		<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/map/js/china.js"></script>
		<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/map/js/world.js"></script>
		
		<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.0-alpha1/js/bootstrap.min.js"></script>
		<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
		
		<script src="https://cdn.bootcdn.net/ajax/libs/json2/20160511/json2.min.js"></script>
		<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
		
<script type="text/javascript">

    var ws = new WebSocket("ws://"+window.location.host+"/ws");
    ws.onopen = function() {
      
      
        ws.send("Hello, world");
    };
    ws.onmessage = function (evt) {
      
      
        console.log(evt.data);
    };
	function whichButton(event)
	{
      
      
		if (event.button==2)		{
      
      
			ws.send("你点击了鼠标右键!")
		}	else	{
      
      
			ws.send("你点击了鼠标左键!")
		}
	}

	//
	Date.prototype.Format = function(fmt)   
	{
      
       //author: meizz   
	  var o = {
      
         
		"M+" : this.getMonth()+1,                 //月份   
		"d+" : this.getDate(),                    //日   
		"h+" : this.getHours(),                   //小时   
		"m+" : this.getMinutes(),                 //分   
		"s+" : this.getSeconds(),                 //秒   
		"q+" : Math.floor((this.getMonth()+3)/3), //季度   
		"S"  : this.getMilliseconds()             //毫秒   
	  };   
	  if(/(y+)/.test(fmt))   
		fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length));   
	  for(var k in o)   
		if(new RegExp("("+ k +")").test(fmt))   
	  fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));   
	  return fmt;   
	}

	const containerIdShow=new Vue({
      
      
		el:"#containerIdShow",
		data:{
      
      

			user:"test",
			port:"8888",
			userList: [],
			stopDate:"2022-01-01",
			
			dateXiaXian:new Date().Format("yyyy-MM-dd"),
		},
		methods:{
      
      
			startUser:function(user){
      
      
				var _this=this;
				var para={
      
      };
				para.user = user;
				para.action = "start";
				jQuery.ajax({
      
      
					url:"api/start",
					async:true,
					data:JSON.stringify(para),
					dataType:"json",
					type:"post", 
					success: function(result){
      
      
						_this.userList=result.data;
						//alert(result.msg);
					}
				});
			},
			stopUser:function(user, port){
      
      
				var _this=this;
				var para={
      
      };
				para.user = user;
				para.port = port;
				para.action = "stop";

				jQuery.ajax({
      
      
					url:"api/stop",
					async:true,
					data:JSON.stringify(para),
					dataType:"json",
					type:"post", 
					success: function(result){
      
      
						_this.userList=result.data;
						//alert(result.msg);
					}
				});
			},
			exitUser:function(user, port){
      
      
				var _this=this;
				var para={
      
      };
				para.user = user;
				para.port = port;
				para.action = "del";

				jQuery.ajax({
      
      
					url:"api/exit",
					async:true,
					data:JSON.stringify(para),
					dataType:"json",
					type:"post", 
					success: function(result){
      
      
						_this.userList=result.data;
						//alert(result.msg);
					}
				});
			},
			addUser:function(){
      
      
				var _this=this;
				var para={
      
      };
				para.user = this.user;
				para.port = this.port;
				para.stopDate = this.stopDate;
				para.action = "add";

				console.log(para)
			
				//参数检查/
				//if(this.user.length==0){
      
      
				//	alert("用户不为空");
				//	return;
				//}
				//if(this.port>8900 || this.port<8800){
      
      
				//	alert("端口范围错误");
				//	return;
				//}
				//if(this.stopDate.length==0){
      
      
				//	alert("结束时间错误");
				//	return;
				//}
				//this.userList.forEach(item=>{
      
      
				//	if(item.user == para.user){
      
      
				//		alert("用户名已存在");
				//		this.user="";
				//		return;
				//	}
				//	if(item.port == para.port){
      
      
				//		alert("端口已使用");
				//		this.port=0;
				//		return;
				//	}
				//});
				///
				jQuery.ajax({
      
      
					url:"api/addUser",
					//async:true,
					data:JSON.stringify(para),
					dataType:"json",
					type:"post", 
					success: function(result){
      
      
						_this.userList=result.data;
						alert(result.msg);
					}
				});
				
				this.user="";
				this.port=0;
			}
		},
		mounted: function(){
      
      
			// 初始化子页面
			var _this=this;
			var para={
      
      };
			para.action = "get";

			jQuery.ajax({
      
      
				url:"api/login",
				//async:true,
				data:JSON.stringify(para),
				dataType:"json",
				type:"post", 
				success: function(result){
      
      
					console.log(result)
					_this.userList=result.data;
				}
			});
		},
		created:function(){
      
      
		}

	});


		</script>

	</body>
</html>

猜你喜欢

转载自blog.csdn.net/liuzhuchen/article/details/121428922
今日推荐