Http请求转发服务器实现

devtools/2024/10/19 10:57:17/
http://www.w3.org/2000/svg" style="display: none;">

Http请求转发服务器实现

需求场景

服务器通过VPN连接了现场的n台工控机,每台工控机上都在跑web程序,现在我想通过公网直接访问工控机上的web服务,给客户查看现场的具体运行情况,而不是让客户再装一个VPN,简化操作。

现在我们有以下几种方案可以实现:

1.使用代理,将每台工控机的web服务端口代理到云服务器上的一个空闲端口,这种方式的优点是不需要额外写代码实现,只需要通过配置代理即可,缺点是云服务器上端口占用过多,每打开现场的网址url上面都会带一个端口号。

2.使用Http请求转发服务器,将现场和他对应的VPN的ip地址映射起来存到数据库里,前端先请求服务器本地IP地址(127.0.0.1),当通过主界面跳转到某个现场时,通过数据库查询现场VPN的IP地址,然后将之后的请求都转发到对应的VPN地址,即可获取对应现场的数据

具体实现

使用Python实现请求转发服务器
  1. 使用Python实现请求转发服务器非常简单,用flask库即可轻松实现

    import queue
    import threadingimport requests
    from flask import Flask, request, jsonifyfrom log import log# 初始化Flask应用
    app = Flask(__name__, static_folder="dist")# 捕获所有请求并转发
    @app.route("/", defaults={"path": ""}, methods=["GET", "POST", "PUT", "DELETE"])
    @app.route("/<path:path>", methods=["GET", "POST", "PUT", "DELETE"])
    def catch_all(path):# 构建转发的目标 URL,我这里将请求都转发到10.8.0.126服务器forward_url = f"http://10.8.0.126/{path}"# 转发请求,并传递请求头、数据以及文件(如果有)headers = {key: value for key, value in request.headers if key != "Host"}# 获取请求的数据,根据请求方法选择适当的数据处理方式data = request.get_json() if request.is_json else request.form or request.datajson_data = data or {}try:response = requests.request(method=request.method,url=forward_url,headers=headers,json=json_data,files=request.files,params=request.args,)except requests.RequestException as e:return str(e), 500# 返回转发请求的响应return response.content, response.status_code, response.headers.items()if __name__ == "__main__":app.run(debug=False, host="0.0.0.0", port=9095)
    
  2. 安装gunicorn库,部署转发服务程序(普通运行只供调试使用,不适用于生产环境)

    pip install gunicorn
    
  3. 运行转发服务程序

    gunicorn -b 0.0.0.0 -w 4 main:app
    

    https://i-blog.csdnimg.cn/direct/a2a135c639084dbba09c1cb75672c7a3.png#pic_center" alt="在这里插入图片描述" />

使用C++实现请求转发服务器

在用Python完成请求转发服务器的开发后,方案却被领导否决了,因为后台程序都是用C++写的,用Python写不好融合,然后我继续开始研究C++服务端的方案,先采用cpp-httplib库实现。

  1. 代码实现,这里捕获所有请求使用了正则表达式,刚开始因为对这个库和正则不熟悉,卡了较长时间。

    #include <iostream>
    #include <httplib.h>
    #include <string>// 定义一个简单的路由处理器
    void catch_all(const httplib::Request& req, httplib::Response& res)
    {// 构建转发的目标 URLstd::string path = req.path;std::cout << "path: " << path << std::endl;std::cout << "method: " << req.method << std::endl;std::string forward_url = "http://10.8.0.126/" + path;// 转发请求,并传递请求头、数据以及文件(如果有)httplib::Headers headers;headers = req.headers;headers.erase("Host");// 获取请求的数据,根据请求方法选择适当的数据处理方式std::string data;data = req.body;// 使用 httplib 客户端进行转发httplib::Client client("10.10.112.139", 9092);httplib::Result result;if (req.method == "GET") {result = client.Get(path, headers);} else if (req.method == "POST") {result = client.Post(path, headers, data, "application/json");std::cout << result->body << std::endl;} else if (req.method == "PUT") {result = client.Put(path, headers, data, "application/json");} else if (req.method == "DELETE") {result = client.Delete(path, headers);} else {res.set_content("Unsupported method", "text/plain");res.status = 405;return;}if (result && result->status == 200) {res.set_content(result->body, result->get_header_value("Content-Type"));res.status = result->status;for (const auto& header : result->headers) {res.headers.emplace(header.first, header.second);}} else {res.set_content("Forward request failed", "text/plain");res.status = 500;}
    }int main()
    {httplib::Server svr;// 捕获所有请求并转发svr.Get(R"(/.*)", &catch_all);svr.Post(R"(/.*)", &catch_all);auto ret = svr.set_mount_point("/", "/home/narada/ems/www");svr.listen("0.0.0.0", 8080);return 0;
    }
    

http://www.ppmy.cn/devtools/126982.html

相关文章

C#从零开始学习(面向对象)(3)

面向对象 本章所有的代码都放在 https://github.com/hikinazimi/head-first-Csharp 类包含方法,方法中包含完成动作的语句,设计良好的类要合理的命名一些方法有一个返回类型,要使用return返回对应的类型以public void为开头,可以不用return从一个类创建一个新的对象时,称为这个…

Threejs 实现3D 地图(02)创建3d 地图

"d3": "^7.9.0", "three": "^0.169.0", "vue": "^3.5.10" 地图数据来源&#xff1a; DataV.GeoAtlas地理小工具系列 <script setup> import {onMounted, ref} from vue import * as THREE from three im…

业务诊断简介

通过业务诊断功能&#xff0c;维护人员可以根据需要通过命令行创建一个诊断对象。当符合诊断对象的属性特征的用户上线时&#xff0c;设备根据诊断对象为其自动创建诊断实例&#xff0c;并对该实例在接入过程中的状态变化、协议处理结果等信息进行诊断并输出。 诊断对象是具有…

【JavaEE初阶】深入透析文件-IO关于文件内容的操作(四种文件流)

前言 &#x1f31f;&#x1f31f;本期讲解关于CAS的补充和JUC中有用的类&#xff0c;这里涉及到高频面试题哦~~~ &#x1f308;上期博客在这里&#xff1a;【JavaEE初阶】文件-IO之实现文件系统的操作如何进行实现-CSDN博客 &#x1f308;感兴趣的小伙伴看一看小编主页&…

【最新华为OD机试E卷-支持在线评测】水仙花数(100分)多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 💻 ACM金牌🏅️团队 | 大厂实习经历 | 多年算法竞赛经历 ✨ 本系列打算持续跟新华为OD-E/D卷的多语言AC题解 🧩 大部分包含 Python / C / Javascript / Java / Cpp 多语言代码 👏 感谢大家的订阅➕ 和 喜欢�…

vue + 百度地图GL版判断一个点位是否在地图可视区内

利用BMapGLLib中isPointInRect 因为没有找到官方文档因此直接下载了该工具的源码&#xff0c;复制以下部分到自己的项目中&#xff0c;避免再次引用完整的BMapGLLib脚本 关键方法 isPointInRect(point, bounds) {if (!(point.toString() "Point" || point.toString(…

三菱FX PLC设计一个电子钟程序实例

在这里介绍三菱FX系列PLC的计数器C的功能、结构&#xff0c;计数过程及工作原理。 功能&#xff1a; 对内部元件X、Y、M、S、T、C的信号进行计数。 结构&#xff1a; 线圈、触点、设定值寄存器、当前值寄存器。 地址编号&#xff1a; 字母C&#xff0b;&#xff08;…

郑州大学第一附属医院许建中教授专家团队会诊室揭牌仪式在郑州长江中医院成功举行

近日&#xff0c;郑州大学第一附属医院许建中教授专家团队会诊室揭牌仪式暨骨关节病非手术治疗技术推广计划启动仪式在郑州举行。郑州大学第一附属医院许建中教授及其专家团队&#xff0c;郑州长江中医院专家团出席了本次活动。 关节病&#xff0c;尤其是膝关节、肩关节等关节的…