go开源webssh终端源码main.go分析

1.地址:  

https://github.com/Jrohy/webssh.git

2.添加中文注释地址:

https://github.com/tonyimax/webssh_cn.git

main.go分析

主包名:main

package main //主包名

依赖包加载

//导入依赖包
import ("embed"                       //可执行文件资源嵌入"flag"                        //标志变量"fmt"                         //格式化"github.com/gin-contrib/gzip" //压缩库"github.com/gin-gonic/gin"    //网页框架"io/fs"                       //文件系统"net/http"                    //http通信"os"                          //系统信息"strconv"                     //字符串转换"strings"                     //字符串"time"                        //时间"webssh/controller"           //websocket通信
)
在可执行文件中嵌入文件夹dist
//go:embed web/dist/*

访问集成文件夹文件系统

var f embed.FS //集成文件集合,取go:embed中文件夹中文件与文件夹列表
变量声明
var (//整形标志声明,用于储存整形指针port = flag.Int("p", //标志名5032,     //标志值"服务运行端口") //标志描述v        = flag.Bool("v", false, "显示版本号")authInfo = flag.String("a", "", "开启账号密码登录验证, '-a user:pass'的格式传参")//普通变量声明timeout    int    //连接超时savePass   bool   //保存密码version    string //版本号buildDate  string //编译时间goVersion  string //go版本号gitVersion string //git版本号username   string //用户名password   string //密码
)

初始化函数分析

func init() {}

初始化变量为标志

//初始化timeout变量为标志flag.IntVar(&timeout, //标志指针"t",              //标志名120,              //标志值"ssh连接超时时间(min)") //标志描述//初始化savePass变量为标志flag.BoolVar(&savePass, //标志指针"s",       //标志名true,      //标志值"保存ssh密码") //标志描述flag.StringVar(&version,"ver","v1.0.0","程序版本号")flag.StringVar(&goVersion,"gover","v1.22","go版本号")flag.StringVar(&gitVersion,"gitver","2.45.2","git版本号")flag.StringVar(&buildDate,"d",time.Now().String(),"编译日期")

操作环境变量

//查找环境变量savePassif envVal, ok := os.LookupEnv("savePass"); ok {//转换环境变量值为Bool值if b, err := strconv.ParseBool(envVal); err == nil {savePass = b //如果环境变量有值保存到savePass}}//读取环境变量用户验证信息if envVal, ok := os.LookupEnv("authInfo"); ok {*authInfo = envVal}//读取环境变量通信端口信息if envVal, ok := os.LookupEnv("port"); ok {//转换为整数if b, err := strconv.Atoi(envVal); err == nil {*port = b}}//必须在标志定义之后及程序访问之前调用flag.Parse()

参数检测

//如果有-v参数,显示版本号信息if *v {fmt.Printf("Version: %s\n\n", version)fmt.Printf("BuildDate: %s\n\n", buildDate)fmt.Printf("GoVersion: %s\n\n", goVersion)fmt.Printf("GitVersion: %s\n\n", gitVersion)os.Exit(0)}

用户名与密码参数分割 (-a user:pass'的格式传参)

if *authInfo != "" {//分割用户名与密码accountInfo := strings.Split(*authInfo, ":")//非空判断if len(accountInfo) != 2 ||accountInfo[0] == "" ||accountInfo[1] == "" {fmt.Println("请按'user:pass'的格式来传参或设置环境变量, 且账号密码都不能为空!")os.Exit(0)}//保存用户名与密码username, password = accountInfo[0], accountInfo[1]}

静态路由函数分析

func staticRouter(router *gin.Engine) {}

创建用户键值对

//创建账户mapaccountList := map[string]string{username: password,}

授权并写页面

//授权路由//传入用户列表{用户:密码}authorized := router.Group("/", gin.BasicAuth(accountList))authorized.GET("", func(c *gin.Context) {//读取主页面indexHTML, _ := f.ReadFile("web/dist/" + "index.html")//向上下文写入主页面c.Writer.Write(indexHTML)})

http操作静态资源

staticFs, _ := fs.Sub(f, "web/dist/static")
router.StaticFS("/static", http.FS(staticFs))

main主函数分析

func main() {}

设置http服务参数并启用路由

//取web引擎实例server := gin.Default()//设置可信代理server.SetTrustedProxies(nil)//使用压缩中间件,支持资源压缩功能server.Use(gzip.Gzip(gzip.DefaultCompression))//启动路由staticRouter(server)

HTTP服务操作:

//HTTP服务操作//GET操作,连接终端websocketserver.GET("/term", func(c *gin.Context) {//调用终端websocketcontroller.TermWs(c, time.Duration(timeout)*time.Minute)})//GET操作,SSH服务检测server.GET("/check", func(c *gin.Context) {//检测SSH服务responseBody := controller.CheckSSH(c)//保存连接密码responseBody.Data = map[string]interface{}{"savePass": savePass,}//渲染JSON数据及HTTP状态码给客户端c.JSON(200, responseBody)})

文件资源操作:

//文件资源操作file := server.Group("/file"){//请求文件列表file.GET("/list", func(c *gin.Context) {c.JSON(200, controller.FileList(c))})//下载文件file.GET("/download", func(c *gin.Context) {controller.DownloadFile(c)})//上传文件file.POST("/upload", func(c *gin.Context) {c.JSON(200, controller.UploadFile(c))})//上传/下载进度处理file.GET("/progress", func(c *gin.Context) {controller.UploadProgressWs(c)})}

启动HTTP服务

//启动HTTP服务server.Run(fmt.Sprintf(":%d", *port))

启动成功输出 如下日志:

[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.- using env:	export GIN_MODE=release- using code:	gin.SetMode(gin.ReleaseMode)[GIN-debug] GET    /                         --> main.staticRouter.func2 (4 handlers)
[GIN-debug] GET    /static/*filepath         --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (4 handlers)
[GIN-debug] HEAD   /static/*filepath         --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (4 handlers)
[GIN-debug] GET    /term                     --> main.main.func1 (4 handlers)
[GIN-debug] GET    /check                    --> main.main.func2 (4 handlers)
[GIN-debug] GET    /file/list                --> main.main.func3 (4 handlers)
[GIN-debug] GET    /file/download            --> main.main.func4 (4 handlers)
[GIN-debug] POST   /file/upload              --> main.main.func5 (4 handlers)
[GIN-debug] GET    /file/progress            --> main.main.func6 (4 handlers)
[GIN-debug] Listening and serving HTTP on :5032

main.go

package main //主包名
//导入依赖包
import ("embed"                       //可执行文件资源嵌入"flag"                        //标志变量"fmt"                         //格式化"github.com/gin-contrib/gzip" //压缩库"github.com/gin-gonic/gin"    //网页框架"io/fs"                       //文件系统"net/http"                    //http通信"os"                          //系统信息"strconv"                     //字符串转换"strings"                     //字符串"time"                        //时间"webssh/controller"           //websocket通信
)// 在可执行文件中嵌入文件夹dist
//
//go:embed web/dist/*
var f embed.FS //集成文件集合,取go:embed中文件夹中文件与文件夹列表
// 变量声明
var (//整形标志声明,用于储存整形指针port = flag.Int("p", //标志名5032,     //标志值"服务运行端口") //标志描述v        = flag.Bool("v", false, "显示版本号")authInfo = flag.String("a", "", "开启账号密码登录验证, '-a user:pass'的格式传参")//普通变量声明timeout    int    //连接超时savePass   bool   //保存密码version    string //版本号buildDate  string //编译时间goVersion  string //go版本号gitVersion string //git版本号username   string //用户名password   string //密码
)// 初始化
func init() {//初始化timeout变量为标志flag.IntVar(&timeout, //标志指针"t",              //标志名120,              //标志值"ssh连接超时时间(min)") //标志描述//初始化savePass变量为标志flag.BoolVar(&savePass, //标志指针"s",       //标志名true,      //标志值"保存ssh密码") //标志描述flag.StringVar(&version,"ver","v1.0.0","程序版本号")flag.StringVar(&goVersion,"gover","v1.22","go版本号")flag.StringVar(&gitVersion,"gitver","2.45.2","git版本号")flag.StringVar(&buildDate,"d",time.Now().String(),"编译日期")//查找环境变量savePassif envVal, ok := os.LookupEnv("savePass"); ok {//转换环境变量值为Bool值if b, err := strconv.ParseBool(envVal); err == nil {savePass = b //如果环境变量有值保存到savePass}}//读取环境变量用户验证信息if envVal, ok := os.LookupEnv("authInfo"); ok {*authInfo = envVal}//读取环境变量通信端口信息if envVal, ok := os.LookupEnv("port"); ok {//转换为整数if b, err := strconv.Atoi(envVal); err == nil {*port = b}}//必须在标志定义之后及程序访问之前调用flag.Parse()//如果有-v参数,显示版本号信息if *v {fmt.Printf("Version: %s\n\n", version)fmt.Printf("BuildDate: %s\n\n", buildDate)fmt.Printf("GoVersion: %s\n\n", goVersion)fmt.Printf("GitVersion: %s\n\n", gitVersion)os.Exit(0)}if *authInfo != "" {//分割用户名与密码accountInfo := strings.Split(*authInfo, ":")//非空判断if len(accountInfo) != 2 ||accountInfo[0] == "" ||accountInfo[1] == "" {fmt.Println("请按'user:pass'的格式来传参或设置环境变量, 且账号密码都不能为空!")os.Exit(0)}//保存用户名与密码username, password = accountInfo[0], accountInfo[1]}
}// 启动静态路由
func staticRouter(router *gin.Engine) {//如果密码不为空if password != "" {//创建账户mapaccountList := map[string]string{username: password,}//授权路由//传入用户列表{用户:密码}authorized := router.Group("/", gin.BasicAuth(accountList))authorized.GET("", func(c *gin.Context) {//读取主页面indexHTML, _ := f.ReadFile("web/dist/" + "index.html")//向上下文写入主页面c.Writer.Write(indexHTML)})} else {router.GET("/", func(c *gin.Context) {indexHTML, _ := f.ReadFile("web/dist/" + "index.html")c.Writer.Write(indexHTML)})}//http操作静态资源staticFs, _ := fs.Sub(f, "web/dist/static")router.StaticFS("/static", http.FS(staticFs))
}func main() {//取web引擎实例server := gin.Default()//设置可信代理server.SetTrustedProxies(nil)//使用压缩中间件,支持资源压缩功能server.Use(gzip.Gzip(gzip.DefaultCompression))//启动路由staticRouter(server)//HTTP服务操作//GET操作,连接终端websocketserver.GET("/term", func(c *gin.Context) {//调用终端websocketcontroller.TermWs(c, time.Duration(timeout)*time.Minute)})//GET操作,SSH服务检测server.GET("/check", func(c *gin.Context) {//检测SSH服务responseBody := controller.CheckSSH(c)//保存连接密码responseBody.Data = map[string]interface{}{"savePass": savePass,}//渲染JSON数据及HTTP状态码给客户端c.JSON(200, responseBody)})//文件资源操作file := server.Group("/file"){//请求文件列表file.GET("/list", func(c *gin.Context) {c.JSON(200, controller.FileList(c))})//下载文件file.GET("/download", func(c *gin.Context) {controller.DownloadFile(c)})//上传文件file.POST("/upload", func(c *gin.Context) {c.JSON(200, controller.UploadFile(c))})//上传/下载进度处理file.GET("/progress", func(c *gin.Context) {controller.UploadProgressWs(c)})}//启动HTTP服务server.Run(fmt.Sprintf(":%d", *port))
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/865833.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决js对象解构赋值多行格式被prettier格式化为一行的问题

目前没有特别好的解决方法,但是有一个hack方法,就是在第一个解构参数后面加个空注释,骗过prettier。 代码示例如下: const {prop1, //prop2,prop3, } props 欢迎关注公众号:清晰编程,获取更多精彩内容

方向导数和梯度

方向导数和梯度 1 导数的回忆2 偏导数及其向量形式偏导数的几何意义偏导数的向量形式 3 方向导数向量形式几何意义方向导数和偏导的关系 4 梯度5 梯度下降算法 1 导数的回忆 导数的几何意义如图所示: 当 P 0 P_{0} P0​点不断接近 P P P时,导数如下定义…

springboot私人诊所管理系统-计算机毕业设计源码93887

摘要 随着科技的不断发展和医疗服务的日益普及,私人诊所管理系统成为现代医疗管理的重要组成部分。该系统通过引入计算机技术和互联网平台,为患者提供方便快捷的就诊方式,同时也为诊所、医院提供高效的资源管理和服务优化的途径。本文将介绍私…

RocketMQ 顺序消息

顺序消息 顺序消息为云消息队列 RocketMQ 版中的高级特性消息,本文为您介绍顺序消息的应用场景、功能原理、使用限制、使用方法和使用建议。 应用场景 在有序事件处理、撮合交易、数据实时增量同步等场景下,异构系统间需要维持强一致的状态同步&#…

万字详解AI开发中的数据预处理(清洗)

数据清洗(Data Cleaning)是通过修改、添加或删除数据的方式为数据分析做准备的过程,这个过程通常也被称为数据预处理(Data Preprocessing)。对于数据科学家和机器学习工程师来说,熟练掌握数据清洗全流程至关…

21_硬件电路基础

目录 组合逻辑电路 组合逻辑电路原理 真值表 布尔代数 门电路 译码器 发光二极管LED 液晶字符显示器LCD 数据选择器 数据分配器 多路开关 时序逻辑电路 时序逻辑电路原理 时钟信号 触发器 电位触发方式触发器 边沿触发方式触发器 寄存器 移位器 计数器 总线…

经营人心:Mrs. B的百年传奇

这个故事的主角是Rose Blumkin,也被称为Mrs. B,她是Nebraska Furniture Mart的创始人。 她的故事确实是一个关于用户思维、客户关系和创业精神的经典案例。 Rose Blumkin于1893年出生在俄罗斯的一个小村庄,她在1921年移民到美国。 1937年&…

ImportError cannot import name ‘uic‘ from ‘PyQt5‘

ImportError cannot import name ‘uic’ from ‘PyQt5’ 1、描述 使用nuitka把PyQt5打包exe文件时报错: ImportError cannot import name ‘uic’ from ‘PyQt5’ 2、原因 这个是由于无法找到uic的目录导致的,在PyQt5的目录下是有uic文件的。 3、解决方案 找到导入uic…

SQL Server 2022的组成

《SQL Server 2022从入门到精通(视频教学超值版)》图书介绍-CSDN博客 SQL Server 2022主要由4部分组成,分别是数据库引擎、分析服务、集成服务和报表服务。本节将详细介绍这些内容。 1.2.1 SQL Server 2022的数据库引擎 SQL Server 2022的…

NGINX+KEEPALIVED | 一文搞懂NG+KL负载均衡高可用架构的实操教程(详细)

文章目录 NGINXKEEPALIVED负载均衡高可用架构为什么需要多节点应用为什么需要Nginx服务为什么需要Keepalived服务NGKL简述前期准备Linux服务器公共环境配置Server1 NGKL服务器配置Server2 NGKL服务器配置Server3 HTTP服务器配置Server4 HTTP服务器配置运行测试用例 NGINXKEEPAL…

使用Keil将STM32部分程序放在RAM中运行

手动分配RAM区域,新建.sct文件,定义RAM_CODE区域,并指定其正确的起始地址和大小。 ; ************************************************************* ; *** Scatter-Loading Description File generated by uVision *** ; ************************************************…

C语言 -- 函数

C语言 -- 函数 1. 函数的概念2. 库函数2.1 标准库和头文件2.2 库函数的使用方法2.2.1 功能2.2.2 头文件包含2.2.3 实践2.2.4 库函数文档的一般格式 3. 自定义函数3.1 函数的语法形式3.2 函数的举例 4. 形参和实参4.1 实参4.2 形参4.3 实参和形参的关系 5. return 语句6. 数组做…

Element中的消息提示组件Message和弹框组件MessageBox

简述:在 Element UI 中,Message和MessageBox都是比较常用的组件,Message用来提示消息,而MessageBox是一个用于创建模态对话框的组件。它可以用于在页面上快速展示信息、警告或错误提示,而不会阻止用户的其他操作。简单…

116-基于5VLX110T FPGA FMC接口功能验证6U CPCI平台

一、板卡概述 本板卡是Xilinx公司芯片V5系列芯片设计信号处理板卡。由一片Xilinx公司的XC5VLX110T-1FF1136 / XC5VSX95T-1FF1136 / XC5VFX70T-1FF1136芯片组成。FPGA接1片DDR2内存条 2GB,32MB Nor flash存储器,用于存储程序。外扩 SATA、PCI、PCI expres…

【期末复习】数据库系统概论(附带考点汇总)

第1章.绪论 目录 第1章.绪论1.1. 数据库系统概述1.1.1.基本概念1.1.2.产生和发展 1.2.概念模型1.2.1.三种模型1.2.2.概念模型1.2.3.关系模型 1.3.数据库系统结构1.3.1三级模式结构1.3.2.两级映像与数据独立性 第2章.关系型数据库2.1.关系2.2.关系操作2.2.1.基本关系操作2.2.2.关…

SALOME源码分析:View Model

作为一款开源的CAx(CAD/CAE/CAM)软件集成平台,为了实现各个Module支持不同的数据显示与交互方案,出于扩展性的考虑,SALOME引入了View Model,用以支持OpenGL、OCC、VTK、ParaView、Qwt等数据显示与交互实现。 本文将以OCCViewer、…

昇思25天学习打卡营第16天|Diffusion扩散模型

导入必要的库函数 import math from functools import partial %matplotlib inline import matplotlib.pyplot as plt from tqdm.auto import tqdm import numpy as np from multiprocessing import cpu_count from download import downloadimport mindspore as ms import mi…

Python基于卷积神经网络分类模型(CNN分类算法)实现时装类别识别项目实战

说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 在深度学习领域,卷积神经网络(Convolutional Neural Networks, CNNs&#xff0…

【架构-20】死锁

什么是死锁? 死锁(Deadlock)是指两个或多个线程/进程在执行过程中,由于资源的互相占用和等待,而陷入一种互相等待的僵局,无法继续往下执行的情况。 产生死锁的四个必要条件: (1)互斥条件(Mutual Exclusion):至少有一个资源是非共享…

Elasticsearch:结合稀疏、密集和地理字段

作者:来自 Elastic Madhusudhan Konda 如何以自定义方式组合多个稀疏、密集和地理字段 Elasticsearch 是一款强大的工具,可用于近乎实时地搜索和分析数据。作为开发人员,我们经常会遇到包含各种不同字段的数据集。有些字段是必填字段&#x…