Moduel ProxyHTTP 反向代理中间件

联合创作 · 2023-10-01 10:49

Module Proxy是一款HTTP反向代理中间件,突出的靓点是将HTTP协议代理为TCP Socket协议,特别适合Web前后台分离的编程架构项目,使用Module Proxy可以让后端编程从HTTP技术体系中抽身出来,这将带来两个重要的改变:

  • 无Web编程经验的程序员,可以轻松进行B/S后端的编程工作 。
  • 几乎所有的现代编程语言,都可以被使用进行B/S后端的编程工作,使用中不需要这些编程语言有HTTP的实现。

Module Proxy中间件由Rust语言实现,使用了优秀的异步运行时Tokio和HTTP底层库hyper,具有高效、稳定、简单的特性。

Demo 程序示例

Ajax客户端:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script>
<script type="text/javascript">
$(function(){
	// method是和后端服务的约定,这里表示调用后端的hello方法,data是前后端约定的业务数据
	var req_json =  {
                       "head":{"method":"hello"},
                       "data":{"hello":"world!!!", "list":[1,2,3,4]}
                    };
	$("#btn").click(function(){
		$.ajax({
			type: "POST",       //传输方式POST
			url: "/socket1/",   //提交URL, socket1是模块名
			contentType : "application/json; charset=utf-8",  //Socket转发的固定格式
			data: JSON.stringify(req_json),
			success: function(rsp_json){
				$("#myDiv").html('<h3>'+JSON.stringify(rsp_json)+'</h3>');
			}
		});		
	 });
});
</script>    
</head>
    <body>
        <button id="btn" type="button">submit</button>
        <div id="myDiv"></div>
    </body>
</html>

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)
}

说明:因篇幅原因,以上代码省略了必要的错误和异常处理,只起到示范说明作用。

浏览 2
点赞
评论
收藏
分享

手机扫一扫分享

编辑
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

编辑
举报