# Module Proxy **Repository Path**: ShangHaiHongLuXinXi/module-proxy ## Basic Information - **Project Name**: Module Proxy - **Description**: Module Proxy是一款HTTP反向代理中间件,突出的靓点是将HTTP协议代理为TCP Socket协议,特别适合Web前后台分离的编程架构项目。 - **Primary Language**: Rust - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 7 - **Created**: 2021-10-15 - **Last Updated**: 2021-10-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Mdoule Proxy Module Proxy是一款HTTP反向代理中间件,突出的靓点是将HTTP协议代理为TCP Socket协议,特别适合Web前后台分离的编程架构项目,使用Module Proxy可以让后端编程从HTTP技术体系中抽身出来,这将带来两个重要的改变: - 无Web编程经验的程序员,可以轻松进行B/S后端的编程工作。 - 几乎所有的现代编程语言,都可以被使用进行B/S后端的编程工作,使用中不需要这些编程语言有HTTP的实现。 Module Proxy中间件由Rust语言实现,使用了优秀的异步运行时Tokio和HTTP底层库hyper,具有高效、稳定、简单的特性。 ![输入图片说明](https://images.gitee.com/uploads/images/2021/1004/164117_80a11bdc_1896879.png "架构图.png") 从浏览器端看,Module Proxy是标准的http服务端,不仅能作为静态网站服务器,还能像Nginx一样出色地反向代理其他HTTP服务。从服务器内部看,Module Proxy能以模块代理的形式,支持静态、HTTP、Socket三种不同的服务,特别是Socket代理很可能改变Web项目的编程架构,降低Web后端编程的入门门槛,推动现代编程语言在B/S领域的普及和使用。 #### 源代码编译 编译前需要先安装Rust语言环境,编译时只需要下载仓库中的Cargo.toml文件和src目录及下面的所有.rs文件即可。 编译命令 **cargo build --release** 在Linux系统中编译后可得到二进制执行文件 modproxy , 在windows系统中编译后得到 modproxy.exe 。 Rust语言的环境安装和编译等相关信息,请参考Rust官方网站 [https://www.rust-lang.org](http://) #### 发行版程序包 已提供编译好的发行版程序包,可直接下载使用: - mod_proxy_x.x_example_linux_amd64.tar.gz 适合Linux的发行版程序包,已在CentOS7 AMD 64环境测试过。 - mod_proxy_x.x_example_win64.zip 适合Windows的发行版程序包,已在Windows10 AMD 64环境测试过。 如果以上程序包不符合您的计算机系统版本或CPU架构,可进行源代码编译,替换程序包中的二进制可执行文件即可。 #### 程序结构 ![输入图片说明](https://images.gitee.com/uploads/images/2021/1004/224702_352ab0c4_1896879.png "程序结构.png") 基本的程序结构非常简单,第一次使用请下载example发行版,包含示例程序,容易上手。 #### 使用说明 使用Module Proxy主要就是配置代理,下面是配置示例: ``` # default.toml name = "module proxy" version = "0.1" [server] port = 80 # http侦听端口 root_path = "/opt/mod_proxy/example/root/" # 网站根路径 chunked_size = 10240000 # chunked方式最小字节 [log] level = "info" # 日志级别,分为 error warn info debug 四种 [module] module_html = [ # 本地html模块 {module = "vue", path = "/opt/mod_proxy/example/vue_html"}, ] module_http = [ # http反向代理模块 {module = "servlet", proxy_pass = "http://127.0.0.1:8080" }, {module = "examples", proxy_pass = "http://127.0.0.1:8080" }, ] module_socket = [ # socket反向代理模块 {module = "socket", ip = "127.0.0.1", port = 21230 }, {module = "socket1", ip = "127.0.0.1", port = 21231 }, ] ``` 配置文件最重要的是理解[module]中的三种代理配置: - module_html 静态网站代理,可以理解为其他http服务器的虚拟网站。 - module_http HTTP反向代理,和Nginx的反向代理是差不多的。 - module_socket socket反向代理,将HTTP协议代理为Socket协议。 module(模块)是Module Proxy的重要概念: ![输入图片说明](https://images.gitee.com/uploads/images/2021/1005/112729_3a2756b6_1896879.png "模块.png") URL中第一段路径被定义为模块。Module Proxy收到的每一个HTTP请求,都会分析出模块名称,并根据配置文件的配置来进行后续的代理,下面例举一些URL(这里假定Module Proxy服务的地址是 http://192.168.0.234:80): - http://192.168.0.234:80/socket/ 模块名称socket,代理转发到Socket 127.0.0.1:21230 - http://192.168.0.234:80/socket1/aaa/index.html 模块名称socket1,代理转发到Socket 127.0.0.1:21231, URL中的/aaa/index.html无意义。 - http://192.168.0.234:80/servlet/aaa/index.html 模块名称servlet,代理转发到http://127.0.0.1:8080/servlet/aaa/index.html - http://192.168.0.234:80/vue/aaa/logo.png 模块名称vue,访问静态文件/opt/mod_proxy/example/vue_html/aaa/logo.png - http://192.168.0.234:80/logo.png 无模块,访问静态文件/opt/mod_proxy/example/root/logo.png - http://192.168.0.234 无模块,客户端会自动补充URL为 http://192.168.0.234:80/ 因找不到对应文件,返回404 #### demo程序示例 Ajax客户端: ```
``` Go语言实现的Socket端: ``` package main import ( "encoding/json" "fmt" "net" "strconv" "strings" "time" ) func main() { listener, err := net.Listen("tcp", "0.0.0.0:21231") //侦听端口21231 if err != nil { fmt.Println("listen error:", err) return } fmt.Println("server start...") for { conn, err := listener.Accept() if err != nil { fmt.Println("accept error:", err) break } go process(conn) //协程 } } func process(conn net.Conn) { defer conn.Close() //读取req json长度,长度行是Module Proxy转发时在Json数据前补充的 buf := make([]byte, 12) //长度行总是12字节 n, _ := conn.Read(buf) lenStr := string(buf[:n]) lenStr = strings.Trim(lenStr, "\r\n") //去除行尾的回车换行 lenStr = strings.Trim(lenStr, " ") //去除行左的空格 len, _ := strconv.Atoi(lenStr) //string转int //读取req json jsonBuf := make([]byte, len) n, _ = conn.Read(jsonBuf) //解析req json m := make(map[string]interface{}) //map json.Unmarshal(jsonBuf, &m) //json转map method := m["head"].(map[string]interface{})["method"] data := m["data"] fmt.Println("method: ", method) fmt.Println("data: ", data) //调用业务函数 var rspJson []byte var rsplen int switch method { case "hello": rspJson, rsplen = hello(data.(map[string]interface{})) //只传入Json中的data数据部分 default: rspJson, rsplen = foo() } //返回 rsp json lenRsp := fmt.Sprintf("%10d\r\n", rsplen) //构建12字节长度行(左补空格,右补\r\n) conn.Write([]byte(lenRsp)) //socket返回 长度行 conn.Write(rspJson) //socket返回 rsp json } func hello(m map[string]interface{}) ([]byte, int) { m["time"] = time.Now().Format("2006-01-02 15:04:05") m["module"] = "golang" b, _ := json.Marshal(m) //map转json return b, len(b) } func foo() ([]byte, int) { b := []byte("{}") return b, len(b) } ``` 说明:因篇幅原因,以上代码省略了必要的错误和异常处理,只起到示范说明作用。 #### 版权及作者 Module Proxy是开源软件,遵循GPL3. 作者:关中麦客 1036038462@qq.com 关中麦客是一名有20年编程工作的普通程序员,业余时间开发了Module Proxy中间件,也是对近期自学Rust语言的总结。他热情欢迎您使用Module Proxy并提出积极的建议,有关Module Proxy的问题请提交到Issue,或直接邮件到 1036038462@qq.com 。