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
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,将会同时兼容toml及yaml格式的配置文件。
15. 从零开始编写一个类nginx工具, 如果将nginx.conf转成yaml,toml,json会怎么样的更多相关文章
- 从零开始编写一个BitTorrent下载器
从零开始编写一个BitTorrent下载器 BT协议 简介 BT协议Bit Torrent(BT)是一种通信协议,又是一种应用程序,广泛用于对等网络通信(P2P).曾经风靡一时,由于它引起了巨大的流量 ...
- 22.编写一个类A,该类创建的对象可以调用方法showA输出小写的英文字母表。然后再编写一个A类的子类B,子类B创建的对象不仅可以调用方法showA输出小写的英文字母表,而且可以调用子类新增的方法showB输出大写的英文字母表。最后编写主类C,在主类的main方法 中测试类A与类B。
22.编写一个类A,该类创建的对象可以调用方法showA输出小写的英文字母表.然后再编写一个A类的子类B,子类B创建的对象不仅可以调用方法showA输出小写的英文字母表,而且可以调用子类新增的方法sh ...
- 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 ...
- 编写一个类,其中包含一个排序的方法Sort(),当传入的是一串整数,就按照从小到大的顺序输出,如果传入的是一个字符串,就将字符串反序输出。
namespace test2 { class Program { /// <summary> /// 编写一个类,其中包含一个排序的方法Sort(),当传入的是一串整数,就按照从小到大的 ...
- 二、 编写一个类,用两个栈实现队列,支持队列的基本操作(add,poll,peek)
请指教交流! package com.it.hxs.c01; import java.util.Stack; /* 编写一个类,用两个栈实现队列,支持队列的基本操作(add,poll,peek) */ ...
- 如何编写一个SQL注入工具
0x01 前言 一直在思考如何编写一个自动化注入工具,这款工具不用太复杂,但是可以用最简单.最直接的方式来获取数据库信息,根据自定义构造的payload来绕过防护,这样子就可以. 0x02 SQL注 ...
- 从零开始编写一个vue插件
title: 从零开始编写一个vue插件 toc: true date: 2018-12-17 10:54:29 categories: Web tags: vue mathjax 写毕设的时候需要一 ...
- 题目一:编写一个类Computer,类中含有一个求n的阶乘的方法
作业:编写一个类Computer,类中含有一个求n的阶乘的方法.将该类打包,并在另一包中的Java文件App.java中引入包,在主类中定义Computer类的对象,调用求n的阶乘的方法(n值由参数决 ...
- 多任务-python实现-继承Thread类,单独编写一个类(2.1.2)
@ 目录 1.thread类 1.thread类 threding代码实现 import threading import time class MyThread(threading.Thread): ...
- 按要求编写一个Java应用程序: (1)定义一个类,描述一个矩形,包含有长、宽两种属性,和计算面积方法。 (2)编写一个类,继承自矩形类,同时该类描述长方体,具有长、宽、高属性, 和计算体积的方法。 (3)编写一个测试类,对以上两个类进行测试,创建一个长方体,定义其长、 宽、高,输出其底面积和体积。
package jvxing; public class Jvxing { //成员变量 private double width; private double chang; public doub ...
随机推荐
- 添加.gitignore不生效问题
1. 解决.gitignore不生效问题 把某些目录或文件加入忽略规则,按照上述方法定义后发现并未生效,原因是.gitignore只能忽略那些原来没有被追踪的文件,如果某些文件已经被纳入了版本管理中, ...
- 【技术积累】JavaScript中的基础语法【二】
JavaScript编写方式 JavaScript是一种脚本语言,用于为网页添加交互性和动态功能.它可以直接嵌入到HTML中,并通过浏览器解释执行.下面是一些常见的JavaScript编写方式和相应的 ...
- MIT 6.5840 Raft Implementation(2B, Log Replication)
Raft实现思路+细节(2B) 任务分解 2B中最主要的任务就是进行日志的复制.Raft是一个强领导人的系统,这意味着所有的日志添加都是由领导人发起的,与之相类似的,还有很多其他的结论(它们都是比较显 ...
- zabbix 概念 - 主机、主机配置模板
zabbix 是以"主机"为单位来组织监控项的. 主机(Host)是一个你想要监控的网络实体(物理的,或者虚拟的).它可以是一台物理服务器,一个网络交换机,一个虚拟机或者一些应用. ...
- docker下nginx配置
一步一坑安装docker nginx 首先选择适当版本镜像下载 我选的: nginx:1.16.0 docker pull nginx:1.16.0 安装完毕之后创建挂载文件夹 : mkdir /u ...
- 合并两个不同远程仓库的Git命令
一.需求场景描述 远程仓库A:http://XXXA.git 远程gitlab,团队协作开发主仓库,新仓库 远程仓库B:http://XXXB.git 旧仓库 从A仓库和B仓库,都对同一个项目进行过开 ...
- Java程序员的MacBookPro(14寸M1)配置备忘录
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 欣宸的月俸虽然很低,但还是咬着牙攒够银子,入 ...
- Lithosphere是什么,它解决什么问题?
这问题很好,一针见血,它解决什么问题? 那这得说说,在IoT应用中,我们会碰到什么问题? 和纯软件项目,互联网项目比,IoT应用项目一个比较大不同的地方,应该是它既要做软件,又要做硬件. 我并不是硬件 ...
- CSS实现文字描边效果
一.介绍最近在一个项目的宣传页中,设计师使用了文字描边效果,之前我确实没有实现过文字的描边效果,然后我在查阅资料后,知道了实现方法.文字描边分为两种:内外双描边和单外描边,也就是指在给文字加上描边效果 ...
- [ABC151E] Max-Min Sums
2023-03-11 题目 题目传送门 翻译 翻译 难度&重要性(1~10):5 题目来源 AtCoder 题目算法 数学 解题思路 对于一个正数 \(x,x\in A\) 一定会有 \(C_ ...