Express代理转发服务器实现

目录
  • express的代理转发
  • 项目结构
  • 转发
  • 转发记录
  • 前端页面

express的代理转发

其实我的内心关于这个Express,我的内心是拒绝的,不是说,我对这个框架有什么看法,而是因为这个大作业的问题。是的我还是一个大三老菜鸡,苦练 Java 全干开发,Python 人工智能 整整 一坤年。期间拿了几个奖,水了篇论文 而已。

那么这篇文章主要做的,其实很简单就是,做个代理转发。前端请求,先到express服务器,然后转发到flask服务器,为什么非要转发呢,原因很简单,web作业非要用node平台,没办法,但是我的服务已经用flask做好了,当然这个和我先前写的那个微信聊天的不一样哈,这个是另一个,是视觉识别算法,说到这个,我本人目前也在手写一个全新的目标检测算法,希望可以起到不错的效果,扯远了。所以没有办法,只能做一个express的代理转发。

但是呢,为了体现工作量,我在这个转发服务器里面加了点东西:

就是这个,加点curd,不然不好混。

项目结构

这个的话,更像是一个dome,所以的话,项目结构非常简单。

因为核心功能就一个,就是做转发,然后呢,加上一些配套的记录就好了。

然后就是我们的数据库还有页面之类的。当然整个项目还是使用这个生成工具先生成了一个模板工程的。

由于整个项目简单,骨架也是生成的,所以我这边就只说,它的一些核心实现了。

转发

那么首先就是我们的核心,代理转发:

const proxy = require("http-proxy-middleware").createProxyMiddleware;
app.use(
    "/",
    proxy(
        [`/api/**`], {
            target: `http://www.httpbin.org/anything/`,
            changeOrigin: true,
            onProxyReq: (proxyReq, req, res) => {
                // 在代理请求发送到目标服务器之前,对请求头进行修改
                const sourceUrl = req.originalUrl;
                const targetUrl = "your address";
                db.insertProxy(sourceUrl, targetUrl, (err, id) => {
                    if (err) {
                        console.error(err);
                    } else {
                        console.log(`New proxy request saved with ID ${id}.`);
                    }
                });
            },
            onProxyRes: (proxyRes, req, res) => {
                // 在代理服务器收到目标服务器的响应后,对响应头进行修改
                proxyRes.headers['x-custom-header'] = 'Huterox';
            }
        },
    ),
);

转发记录

然后其实就是我们的转发记录的了。这里的话我使用的是sqlite3。

这边把一些方法都封装到了db.js当中去了。

const sqlite3 = require('sqlite3').verbose();
// 创建数据库连接
const db = new sqlite3.Database('./db.sqlite', err => {
    if (err) {
        console.error(err.message);
    } else {
        console.log('Connected to the db.sqlite database.');
    }
});
// 创建表
const createTable = () => {
    db.run(
        `CREATE TABLE IF NOT EXISTS proxies (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      source_url TEXT NOT NULL,
      target_url TEXT NOT NULL,
      created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )`,
        err => {
            if (err) {
                console.error(err.message);
            } else {
                console.log('Table proxies created successfully.');
            }
        }
    );
};
//查找
const searchProxy = function(keyword, offset, limit, callback) {
    const pattern = `%${keyword}%`;
    const countSql = `SELECT COUNT(*) as count FROM proxies WHERE source_url LIKE ? OR target_url LIKE ?`;
    const sql = `SELECT * FROM proxies WHERE source_url LIKE ? OR target_url LIKE ? ORDER BY created_at DESC LIMIT ? OFFSET ?`;
    db.get(countSql, [pattern, pattern], (err, row) => {
        if (err) {
            callback(err, {});
            return;
        }
        const totalCount = row.count;
        db.all(sql, [pattern, pattern, limit, offset], (err, rows) => {
            if (err) {
                callback(err);
                return;
            }
            const proxies = rows.map(row => ({
                id: row.id,
                sourceUrl: row.source_url,
                targetUrl: row.target_url,
                createdAt: row.created_at,
            }));
            callback(null, { proxies, totalCount });
        });
    });
};
// 插入一条记录
const insertProxy = (sourceUrl, targetUrl, callback) => {
    db.run(`INSERT INTO proxies (source_url, target_url) VALUES (?, ?)`, [sourceUrl, targetUrl], err => {
        if (err) {
            console.error(err.message);
            callback(err.message, null);
        } else {
            console.log('New proxy added successfully.');
            db.get(`SELECT last_insert_rowid() as id`, (err, row) => {
                callback(null, row.id);
            });
        }
    });
};
// 根据 ID 查询代理转发记录
const getProxyById = (id, callback) => {
    db.get(`SELECT * FROM proxies WHERE id = ?`, [id], (err, row) => {
        if (err) {
            console.error(err.message);
            callback(err.message, null);
        } else {
            console.log(`Proxy with ID ${id} found.`);
            callback(null, row);
        }
    });
};
// 查询所有代理转发记录
const getAllProxies = callback => {
    db.all(`SELECT * FROM proxies ORDER BY id`, (err, rows) => {
        if (err) {
            console.error(err.message);
            callback(err.message, null);
        } else {
            console.log('All proxies fetched successfully.');
            callback(null, rows);
        }
    });
};
// 更新代理转发记录
const updateProxyById = (id, sourceUrl, targetUrl, callback) => {
    db.run(
        `UPDATE proxies SET source_url = ?, target_url = ? WHERE id = ?`, [sourceUrl, targetUrl, id],
        err => {
            if (err) {
                console.error(err.message);
                callback(err.message, null);
            } else {
                console.log(`Proxy with ID ${id} updated successfully.`);
                callback(null, true);
            }
        }
    );
};
// 根据 ID 删除代理转发记录
const deleteProxyById = (id, callback) => {
    db.run(`DELETE FROM proxies WHERE id = ?`, [id], err => {
        if (err) {
            console.error(err.message);
            callback(err.message, null);
        } else {
            console.log(`Proxy with ID ${id} deleted successfully.`);
            callback(null, true);
        }
    });
};
createTable();
module.exports = {
    insertProxy,
    getProxyById,
    getAllProxies,
    searchProxy,
    updateProxyById,
    deleteProxyById
};

当然只有这个还不够,我们还有对应的curd的接口才行。

所以在app.js里面去注册这些接口。

app.get('/logs/proxy', (req, res) => {
    const { keyword = '', offset = 0, limit = 10 } = req.query;
    db.searchProxy(keyword, Number(offset), Number(limit), (err, result) => {
        if (err) {
            console.error(err);
            res.status(500).send('Internal server error.');
        } else {
            res.json({
                rows: result.proxies,
                count: result.totalCount
            });
            console.log("当前记录条数:" + result.totalCount)
        }
    });
});
app.post('/logs/proxy', (req, res) => {
    const { sourceUrl, targetUrl } = req.body;
    db.insertProxy(sourceUrl, targetUrl, (err, row) => {
        if (err) {
            console.error(err);
            res.status(500).send('Internal server error.');
        } else {
            res.json(row);
        }
    });
});
app.delete('/logs/proxy/:id', (req, res) => {
    const id = req.params.id;
    db.deleteProxy(id, (err) => {
        if (err) {
            console.error(err);
            res.status(500).send('Internal server error.');
        } else {
            res.status(204).end();
        }
    });
});

前端页面

之后,就是我们的前端页面,这个页面的话,好办,我们就直接使用html来写了。 访问/logs 就可以访问页面:

app.get('/logs', (req, res) => {
    res.sendFile(__dirname + '/public/logs.html');
});

对应的html代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>代理日志查看</title>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css" rel="external nofollow" >
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<style>
    /* 设置全局字体和颜色 */
    #app {
        margin: 0 auto;
        width: 80%;
    }
</style>
<body>
    <div id="app">
        <h1>代理日志</h1>
        <el-form inline>
            <el-form-item label="关键字">
                <el-input v-model="keyword" placeholder="输入关键字进行搜索"></el-input>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" icon="el-icon-search" v-on:click="search">搜索</el-button>
            </el-form-item>
        </el-form>
        <el-table :data="records" stripe>
            <el-table-column prop="id" label="ID" width="100"></el-table-column>
            <el-table-column prop="sourceUrl" label="请求路径" width="300"></el-table-column>
            <el-table-column prop="targetUrl" label="目标地址" width="300"></el-table-column>
            <el-table-column prop="timestamp" label="时间" width="200">
                <template slot-scope="scope">{{ new Date(scope.row.createdAt).toLocaleString() }}</template>
            </el-table-column>
            <el-table-column label="操作" width="200">
                <template slot-scope="scope">
          <el-button type="danger" icon="el-icon-delete" v-on:click="removeRecord(scope.row.id)">删除</el-button>
        </template>
            </el-table-column>
        </el-table>
        <el-pagination layout="total, prev, pager, next" :total="total" v-on:current-change="changePage"></el-pagination>
    </div>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                records: [],
                keyword: '',
                current: 1,
                pageSize: 10,
                total: 0
            },
            methods: {
                search: function() {
                    this.current = 1;
                    this.loadRecords();
                },
                removeRecord: function(id) {
                    this.$confirm('确定删除该记录?')
                        .then(() => {
                            axios.delete(`/logs/proxy/${id}`)
                                .then(() => {
                                    this.loadRecords();
                                    this.$message.success('删除成功!');
                                })
                                .catch(() => {
                                    this.$message.error('删除失败!');
                                });
                        })
                        .catch(() => {});
                },
                changePage: function(page) {
                    this.current = page;
                    this.loadRecords();
                },
                loadRecords: function() {
                    axios.get('/logs/proxy', {
                            params: {
                                keyword: this.keyword,
                                offset: (this.current - 1) * this.pageSize,
                                limit: this.pageSize
                            }
                        })
                        .then(res => {
                            this.records = res.data.rows;
                            this.total = res.data.count;
                        })
                        .catch(err => console.error(err));
                }
            },
            mounted: function() {
                this.loadRecords();
            }
        });
    </script>
</body>
</html>

那么之后的话,这个简单的代理转发服务器就写好了。强行加上一层,服了。

以上就是Express代理转发服务器实现的详细内容,更多关于Express代理转发服务器的资料请关注我们其它相关文章!

(0)

相关推荐

  • Express框架两个内置中间件方法详解

    目录 什么是中间件 两个内置的中间件 init 方法 query 中间件 被使用 小结 什么是中间件 中间件,就是具有串联执行能力的函数,Express中两种层面的中间件.app 层面的中间件, router 层面的中甲件.在 express 中, 一般通过 use 方法和路由的方法添加中间件. 两个内置的中间件 init 中间件方法 query 中间件方法 init 方法 exports.init = function(app){ return function expressInit(req

  • react express实现webssh demo解析

    目录 正文 实现 WebSSH 的基本思路 实现 Demo 的代码 服务器端代码 前端代码 在 React 应用中使用 WebSSH 组件 效果 总结 正文 下面是一个简单的 WebSSH Demo,实现了通过浏览器连接 SSH 服务器并进行交互的功能. 实现 WebSSH 的基本思路 WebSSH 可以分成以下几个模块: 前端界面:使用 xterm.js 实现一个基于浏览器的终端界面. WebSocket 连接:使用 WebSocket 连接连接 WebSSH 服务器后端. SSH 连接:使用

  • Express框架req res对象使用详解

    目录 正文 IncomingMessage ServerResponse 请求对象 req 响应对象 设置状态码 如何来快速测试这些属性和方法呢? 下面给出一些示例代码 目录结构 安装依赖 小结 正文 Express 请求 req 和响应 res 对象定义: var req = Object.create(http.IncomingMessage.prototype) var res = Object.create(http.ServerResponse.prototype) 下面是属性继承关系

  • Express框架中_router 对象数据结构使用详解

    目录 _router 对象介绍 使用调试直观的获取 _router 对象 一个简单的可以运行的 demo 使用 vscode 初始化一个调试文件 在合适的地点打一个断点 启动服务 观察全部属性并找到 _router 对象以及属性 找出 stack.layer 的排列顺序 分析 _router 的嵌套对象 _router 对象的相关源码 _router 的数据结构分析 小结 _router 对象介绍 _router 对象是一个私有的属性,但是它保存了重要的内容.其中就包括所有的合理的 Layer

  • Express框架Router Route Layer对象使用示例详解

    目录 引言 Layer Route Router 方法统计 两个 stack 取出 stack 中 layer 从 Router 到 layer 的路径 Router.route 方法中的 dispatch next 函数 小结 引言 这使用倒叙的方式: 将 Layer 放在最前面讲解,然后是 Route 路由项目,最后是 Router 路由器. Layer Layer 是什么? Express 中最小的存储单元,存储的重要内容包括 handle 也就是 fn.path 等路径.fn 就是中间件

  • Nginx 代理转发阿里云OSS上传的实现代码

    前言 因为小程序上传需要https,服务器https用的是letsencrypt生成的证书,但是阿里云oss没有做https(懒得上传证书),就想着用Nginx代理转发上传请求. Nginx配置 # HTTPS server # server { listen 443 ssl; server_name your.domain.name; ... location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $Host;

  • 详解Nginx 利用代理转发请求示例

    我们米扑科技的业务遍布全球,有时国外的客户无法访问我们搭建在国内的服务,这就要求我们在国外服务器上搭建一个代理转发服务,用户请求国外服务器的域名,然后代理转发到国内,处理请求后返回结果给国外的客户.Nginx 不仅可以实现负载均衡,还可以实现反向代理转发,非常适合我们的使用场景,因此我们米扑科技采用 Nginx 利用代理转发请求实例. Nginx 利用代理转发请求实例 nginx 作为目前最流行的web服务器之一,可以很方便地实现反向代理. nginx 反向代理官方文档: NGINX REVER

  • 如何利用Docker容器实现代理转发与数据备份详解

    前言 我们将应用以Docker容器的方式部署到服务器上的时候,通常需要考虑两个方面的的问题:网络和存储. 网络方面,有些应用需要占用端口,而其中一部分应用甚至需要对外提供访问. 出于安全方面考虑,代理转发方式相对于直接开放防火墙端口方式更为合适. 存储方面,由于容器内部并不适合做数据持久化,所以一般通过挂载卷的方式将数据保存在服务器磁盘上. 但是服务器也不能保证绝对安全,所以数据也需要备份到云上. 代理转发 默认情况下容器之间的网络是互相隔离的,但是对于一些有关联的应用而言(web前端容器和服务

  • 详解nginx安装过程并代理下载服务器文件

    主旨 nginx服务,现在是最好用的一种代理服务,日常我们代理的一般都是端口转发和流量控制,那么我们如何通过nginx来实现文件下载呢?就是通过nginx服务,通过url来下载文件. Nginx是一款轻量级的web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行.其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好. 环境 linux服务器nginx软件 软件下载 链接: https://pan.baidu.co

  • Vue-Cli配置代理转发解决跨域问题的方法

    目录 vue-cli中集成的跨域解决方案 vue-cli解决跨域配置说明 基地址 重启项目,验证结果 小结 vue-cli中集成的跨域解决方案 思路: 在前端服务和后端接口服务之间 架设一个中间代理服务,它的地址保持和前端服务一致,那么: 代理服务和前端服务之间由于协议域名端口三者统一不存在跨域问题,可以直接发送请求 代理服务和后端服务之间由于并不经过浏览器没有同源策略的限制,可以直接发送请求 这样,我们就可以通过中间这台服务器做接口转发,在开发环境下解决跨域问题,看起来好像挺复杂,其实vue-

  • vue 实现cli3.0中使用proxy进行代理转发

    解决方法: 在vue项目的根目录下添加 vue.config.js文件,文件中需要按照下面写法来写 module.exports = { lintOnSave: true, devServer: { proxy: { // proxy all requests starting with /api to jsonplaceholder '/api': { target: 'http://localhost:8080', //代理接口 changeOrigin: true, pathRewrite

  • ASP.NET Core 奇技淫巧之接口代理转发的实现

    前言 先讲讲本文的开发背景吧.. 在如今前后端分离的大背景下,咱的客户又有要求啦~ 要前后端分离~ 然因为种种原因..没办法用用纯前端的框架(其实是学习成本高,又没钱请前端开发人员)... 所以最终决定了一种方案.. 那就是采用MVC(只处理前端视图层,单纯是为了托管在.net core上)+Webapi的方式来实现前后端分离(讲真,很奇葩).. 那么问题就随之而来了. 现在主流的前端框架都是托管在nodejs上,是通过axios来访问后端API,可以通过配置axios的代理配置(proxyTa

  • Nginx反向代理转发tomcat的实现

    刚刚接触Nginx,记录下学习过程 先说正向代理,比如要访问youtube,但是不能直接访问,只能先找个翻墙软件,通过翻墙软件才能访问youtube. 翻墙软件就叫做正向代理. 所谓的反向代理,指的是用户要访问youtube,但是youtube悄悄地把这个请求交给bilibili来做,那么bilibili就是反向代理了. 在当前教程指的就是访问nginx,但是nginx把请求交给tomcat来做. 安装tomcat 参考文章:https://www.jb51.net/article/137839

  • NodeJs Express框架实现服务器接口详解

    目录 CORS 跨域资源共享 1. 接口的跨域问题 2. 使用 cors 中间件解决跨域问题 创建基本的服务器 创建 API 路由模块 编写 GET 接口 编写 POST 接口 注意:如果要获取 URL-encoded 格式的请求体数据,必须配置中间件 app.use(express.urlencoded({ extended: false })) CORS 跨域资源共享 1. 接口的跨域问题 <body> <button id="btnGET">GET<

  • 通过Nginx代理转发配置实现跨域的方法(API代理转发)

    前言 在WEB开发中,我们经常涉及到跨域的请求,解决跨域问题的方式有很多,比如有window.name.iframe.JSONP.CORS等等,就不详细展开了,涉及到 协议.端口 不一样的跨域请求方式是采用代理,这里我们重点聊聊Nginx代理的方式. 场景 本地启动了一个前后端分离的WEB应用,端口为:3000,可以通过http://127.0.0.1:3000访问前端页面,页面中有些Ajax请求的地址为http://127.0.0.1:3000/api/getList,一般情况下肯定是404或

随机推荐