15. 从零开始编写一个类nginx工具, 如果将nginx.conf转成yaml,toml,json会怎么样

wmproxy

wmproxy将用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,后续将实现websocket代理, 内外网穿透等, 会将实现过程分享出来, 感兴趣的可以一起造个轮子法

项目 ++wmproxy++

gite: https://gitee.com/tickbh/wmproxy

github: https://github.com/tickbh/wmproxy

了解三种格式

Json

  • JSON是一种轻量级的数据交换格式,被广泛使用在Web应用程序之间传输数据。
  • JSON使用大括号{}来表示数据结构,使用冒号:来连接键和值。
  • JSON支持字符串、数字、布尔值、null、数组和对象等多种数据类型。
  • JSON文件通常用于数据交换、存储等场景,也可以用作配置文件。 JSON简单易读存储通用,但JSON原生不支持注释用来做配置文件比较硬伤。

它流行度极高,基本上每个程序员都和他打过交道。 多层级时,对齐和缩进不好控制,容易出错

Yaml

  • YAML被设计为一种可读性极强的数据序列化标准,可以用来表达层次化数据。
  • YAML使用空格缩进来表示数据层次结构。
  • YAML支持浮点数、布尔值、字符串、数组、映射等多种数据类型。
  • YAML文件通常用于配置文件、数据交换等场景。

与JSON及TOML相比,结构比较紧凑 但相对用空格缩近,编写及拷贝时出错的机率比JSON及TOML高许多

Toml

TOML 旨在成为一个语义明显且易于阅读的最小化配置文件格式。 TOML 应该能很容易地被解析成各种语言中的数据结构。

  • TOML是一种简洁明了的键值对格式,被设计成可以很容易地映射为哈希表。
  • TOML使用等号(=)来连接键和值,使用缩进来表示数据层次结构。
  • TOML支持整数、浮点数、字符串、布尔值、数组、字典等多种数据类型。
  • TOML文件通常用于配置文件、数据交换等场景。

易于阅读和编写语法灵活 与JSON配置相比,TOML在简洁性方面远远胜出; 与YAML配置相比,TOML在简洁性以及语法灵活性方面远远胜出。

三种格式测试数据的对比

我们用Rust的项目配置文件来做对比,为了展示所有的类型,格式有所变更。它以Toml来做配置文件,我们首先先展示toml的格式

内容包含创建者,创建时间,项目名称,项目依赖等信息,如果我们将其转化成可配置的JSON格式时

toml

toml 复制代码
create="tickbh"
create_time=2023-09-08T10:30:00Z
[project]
# 项目名称
name="wmproxy"
version="1.1"
editor=2022
# 项目依赖
[project.dependencies]
wenmeng={version = "0.1.21", default-features = false, features = ["std", "tokio"]}
webparse={version = "0.1", default-features = false}

行数12行,注释两行,全部顶格开头,原生支持时间格式

json

json 复制代码
{
  "create": "tickbh",
  "create_time": "2023-09-08T10:30:00.000Z",
  "project": {
    "name": "wmproxy",
    "version": "1.1",
    "editor": 2022,
    "dependencies": {
      "wenmeng": {
        "version": "0.1.21",
        "default-features": false,
        "features": [
          "std",
          "tokio"
        ]
      },
      "webparse": {
        "version": "0.1",
        "default-features": false
      }
    }
  }
}

行数23行,层次的递进比较多,不容易对齐,无法注释,不支持时间格式

yaml

yaml 复制代码
create: tickbh
create_time: 2023-09-08T10:30:00.000Z
project:
  # 项目名称
  name: wmproxy
  version: "1.1"
  editor: 2022
  # 项目依赖
  dependencies:
    wenmeng:
      version: 0.1.21
      default-features: false
      features:
        - std
        - tokio
    webparse:
      version: "0.1"
      default-features: false

行数18行,注释两行,原生支持时间格式,到features这级行,深度相对较高,但是一眼看上去比json清晰

相对来说JSON比较不适合做比较复杂的配置文件,但VSCODE使用的拓展的JSON以支持注释功能。

接下来尝试将nginx.conf格式做转换

以下尝试的将

conf 复制代码
http {
    gzip on;
    server {
        listen 80;  #监听80的服务端口
        server_name wm-proxy.com;  #监听的域名
       
        location /products {
            proxy_pass http://127.0.0.1:8090/proxy;
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Allow-Origin' '*';
        }
        
        location / {
            root wmproxy;
            index index.html index.htm;
        }
    }
}

我们也模仿类似的结构,但是对于toml,yaml,json来说,都没有一个key两个值的,要么我们只能用对应的数组,此时我来先来初步重构类似的结构。以下我们以toml结构为例,我们分析table的级数有三级,最外层为http,中间层为server为数组,最内层为location也为数组,headers我们用之前提到过的mappings,用proxy开头来表示重写Reqeust,其它的来表示重写Response,文件系统我们用上节提到的file_server。 我们先定义http的table,他只有一个属性gzip为on

toml 复制代码
[http]
gzip="on"

其次server为一个数组,那么我们可以如下定义,有绑定地址和server_name

toml 复制代码
[[http.server]]
bind_addr="127.0.0.1:80"
server_name="wm-proxy.com"

再然后location也为一个数组,定义如下

toml 复制代码
[[http.server.location]]
rule = "/products"
reverse_proxy = "http://127.0.0.1:8090/proxy"
headers = [
  ["+", "Access-Control-Allow-Credentials", "true"],
  ["+", "Access-Control-Allow-Origin", "*"]
]
[[http.server.location]]
rule = "/"
file_server = { root="wmproxy", browse = true, index=["index.html", "index.htm"] }

那么,最终的结构为如下:

toml 复制代码
[http]
gzip="on"
[[http.server]]
bind_addr="127.0.0.1:80"
server_name="wm-proxy.com"
[[http.server.location]]
rule = "/products"
reverse_proxy = "http://127.0.0.1:8090/proxy"
headers = [
  ["+", "Access-Control-Allow-Credentials", "true"],
  ["+", "Access-Control-Allow-Origin", "*"]
]
[[http.server.location]]
rule = "/"
file_server = { root="wmproxy", browse = true, index=["index.html", "index.htm"] }

而yaml的格式结构如下:

yaml 复制代码
http:
  gzip: on
  server:
    - bind_addr: 127.0.0.1:80
      server_name: wm-proxy.com
      location:
        - rule: /products
          reverse_proxy: http://127.0.0.1:8090/proxy
          headers:
            - - +
              - Access-Control-Allow-Credentials
              - "true"
            - - +
              - Access-Control-Allow-Origin
              - "*"
        - rule: /
          file_server:
            root: wmproxy
            browse: true
            index:
              - index.html
              - index.htm

而json的格式结构如下:

json 复制代码
{
  "http": {
    "gzip": "on",
    "server": [
      {
        "bind_addr": "127.0.0.1:80",
        "server_name": "wm-proxy.com",
        "location": [
          {
            "rule": "/products",
            "reverse_proxy": "http://127.0.0.1:8090/proxy",
            "headers": [
              [
                "+",
                "Access-Control-Allow-Credentials",
                "true"
              ],
              [
                "+",
                "Access-Control-Allow-Origin",
                "*"
              ]
            ]
          },
          {
            "rule": "/",
            "file_server": {
              "root": "wmproxy",
              "browse": true,
              "index": [
                "index.html",
                "index.htm"
              ]
            }
          }
        ]
      }
    ]
  }
}
  • 自建的好处是比较清晰,可以自定义自己合适的结构,但是编写者需要重新开始学习,而用能用的配置文件需要遵循它的格式定义
  • 像toml文件,如果层级很深,他的key值配置会很长,因为他一旦定义一个table,就是从最顶级来解析,但是编写者只要熟悉过这配置文件很快就能写出满意的配置文件
  • 而yaml的层级结构相对会需要去看对齐与否,编写的时候需要额外注意,因为弄错了缩进,层级就会发生错误
  • 而json最后结尾的会有相当多的花括号,相对比较容易弄错。JSON总体来说不太适合做比较复杂的配置文件

结语

在不考虑自建格式的情况下,如nginx的nginx.conf,如caddy的Caddyfile,将会同时兼容tomlyaml格式的配置文件。

相关推荐
跟着珅聪学java32 分钟前
spring boot +Elment UI 上传文件教程
java·spring boot·后端·ui·elementui·vue
徐小黑ACG2 小时前
GO语言 使用protobuf
开发语言·后端·golang·protobuf
叠叠乐4 小时前
rust Send Sync 以及对象安全和对象不安全
开发语言·安全·rust
战族狼魂4 小时前
CSGO 皮肤交易平台后端 (Spring Boot) 代码结构与示例
java·spring boot·后端
niandb5 小时前
The Rust Programming Language 学习 (九)
windows·rust
杉之6 小时前
常见前端GET请求以及对应的Spring后端接收接口写法
java·前端·后端·spring·vue
hycccccch6 小时前
Canal+RabbitMQ实现MySQL数据增量同步
java·数据库·后端·rabbitmq
bobz9657 小时前
k8s 怎么提供虚拟机更好
后端
沫夕残雪7 小时前
HTTP,请求响应报头,以及抓包工具的讨论
网络·vscode·网络协议·http
bobz9657 小时前
nova compute 如何创建 ovs 端口
后端