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

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

{
"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

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格式做转换

以下尝试的将

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

[http]
gzip="on"

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

[[http.server]]
bind_addr="127.0.0.1:80"
server_name="wm-proxy.com"

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

[[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"] }

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

[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的格式结构如下:

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的格式结构如下:

{
"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格式的配置文件。

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

  1. 从零开始编写一个BitTorrent下载器

    从零开始编写一个BitTorrent下载器 BT协议 简介 BT协议Bit Torrent(BT)是一种通信协议,又是一种应用程序,广泛用于对等网络通信(P2P).曾经风靡一时,由于它引起了巨大的流量 ...

  2. 22.编写一个类A,该类创建的对象可以调用方法showA输出小写的英文字母表。然后再编写一个A类的子类B,子类B创建的对象不仅可以调用方法showA输出小写的英文字母表,而且可以调用子类新增的方法showB输出大写的英文字母表。最后编写主类C,在主类的main方法 中测试类A与类B。

    22.编写一个类A,该类创建的对象可以调用方法showA输出小写的英文字母表.然后再编写一个A类的子类B,子类B创建的对象不仅可以调用方法showA输出小写的英文字母表,而且可以调用子类新增的方法sh ...

  3. 35.按要求编写Java程序: (1)编写一个接口:InterfaceA,只含有一个方法int method(int n); (2)编写一个类:ClassA来实现接口InterfaceA,实现int method(int n)接口方 法时,要求计算1到n的和; (3)编写另一个类:ClassB来实现接口InterfaceA,实现int method(int n)接口 方法时,要求计算n的阶乘(n

      35.按要求编写Java程序: (1)编写一个接口:InterfaceA,只含有一个方法int method(int n): (2)编写一个类:ClassA来实现接口InterfaceA,实现in ...

  4. 编写一个类,其中包含一个排序的方法Sort(),当传入的是一串整数,就按照从小到大的顺序输出,如果传入的是一个字符串,就将字符串反序输出。

    namespace test2 { class Program { /// <summary> /// 编写一个类,其中包含一个排序的方法Sort(),当传入的是一串整数,就按照从小到大的 ...

  5. 二、 编写一个类,用两个栈实现队列,支持队列的基本操作(add,poll,peek)

    请指教交流! package com.it.hxs.c01; import java.util.Stack; /* 编写一个类,用两个栈实现队列,支持队列的基本操作(add,poll,peek) */ ...

  6. 如何编写一个SQL注入工具

    0x01  前言 一直在思考如何编写一个自动化注入工具,这款工具不用太复杂,但是可以用最简单.最直接的方式来获取数据库信息,根据自定义构造的payload来绕过防护,这样子就可以. 0x02 SQL注 ...

  7. 从零开始编写一个vue插件

    title: 从零开始编写一个vue插件 toc: true date: 2018-12-17 10:54:29 categories: Web tags: vue mathjax 写毕设的时候需要一 ...

  8. 题目一:编写一个类Computer,类中含有一个求n的阶乘的方法

    作业:编写一个类Computer,类中含有一个求n的阶乘的方法.将该类打包,并在另一包中的Java文件App.java中引入包,在主类中定义Computer类的对象,调用求n的阶乘的方法(n值由参数决 ...

  9. 多任务-python实现-继承Thread类,单独编写一个类(2.1.2)

    @ 目录 1.thread类 1.thread类 threding代码实现 import threading import time class MyThread(threading.Thread): ...

  10. 按要求编写一个Java应用程序: (1)定义一个类,描述一个矩形,包含有长、宽两种属性,和计算面积方法。 (2)编写一个类,继承自矩形类,同时该类描述长方体,具有长、宽、高属性, 和计算体积的方法。 (3)编写一个测试类,对以上两个类进行测试,创建一个长方体,定义其长、 宽、高,输出其底面积和体积。

    package jvxing; public class Jvxing { //成员变量 private double width; private double chang; public doub ...

随机推荐

  1. 添加.gitignore不生效问题

    1. 解决.gitignore不生效问题 把某些目录或文件加入忽略规则,按照上述方法定义后发现并未生效,原因是.gitignore只能忽略那些原来没有被追踪的文件,如果某些文件已经被纳入了版本管理中, ...

  2. 【技术积累】JavaScript中的基础语法【二】

    JavaScript编写方式 JavaScript是一种脚本语言,用于为网页添加交互性和动态功能.它可以直接嵌入到HTML中,并通过浏览器解释执行.下面是一些常见的JavaScript编写方式和相应的 ...

  3. MIT 6.5840 Raft Implementation(2B, Log Replication)

    Raft实现思路+细节(2B) 任务分解 2B中最主要的任务就是进行日志的复制.Raft是一个强领导人的系统,这意味着所有的日志添加都是由领导人发起的,与之相类似的,还有很多其他的结论(它们都是比较显 ...

  4. zabbix 概念 - 主机、主机配置模板

    zabbix 是以"主机"为单位来组织监控项的. 主机(Host)是一个你想要监控的网络实体(物理的,或者虚拟的).它可以是一台物理服务器,一个网络交换机,一个虚拟机或者一些应用. ...

  5. docker下nginx配置

    一步一坑安装docker  nginx 首先选择适当版本镜像下载 我选的: nginx:1.16.0 docker pull nginx:1.16.0 安装完毕之后创建挂载文件夹 : mkdir /u ...

  6. 合并两个不同远程仓库的Git命令

    一.需求场景描述 远程仓库A:http://XXXA.git 远程gitlab,团队协作开发主仓库,新仓库 远程仓库B:http://XXXB.git 旧仓库 从A仓库和B仓库,都对同一个项目进行过开 ...

  7. Java程序员的MacBookPro(14寸M1)配置备忘录

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 欣宸的月俸虽然很低,但还是咬着牙攒够银子,入 ...

  8. Lithosphere是什么,它解决什么问题?

    这问题很好,一针见血,它解决什么问题? 那这得说说,在IoT应用中,我们会碰到什么问题? 和纯软件项目,互联网项目比,IoT应用项目一个比较大不同的地方,应该是它既要做软件,又要做硬件. 我并不是硬件 ...

  9. CSS实现文字描边效果

    一.介绍最近在一个项目的宣传页中,设计师使用了文字描边效果,之前我确实没有实现过文字的描边效果,然后我在查阅资料后,知道了实现方法.文字描边分为两种:内外双描边和单外描边,也就是指在给文字加上描边效果 ...

  10. [ABC151E] Max-Min Sums

    2023-03-11 题目 题目传送门 翻译 翻译 难度&重要性(1~10):5 题目来源 AtCoder 题目算法 数学 解题思路 对于一个正数 \(x,x\in A\) 一定会有 \(C_ ...