Apply .gitignore rules

This commit is contained in:
皮蛋13361098506
2025-01-06 16:21:36 +08:00
parent 1b77f62820
commit ccd2c530cf
580 changed files with 69806 additions and 0 deletions

View File

@@ -0,0 +1,200 @@
package fileUtil
import (
"fmt"
"os"
"path/filepath"
"time"
"goutil/timeUtil"
)
// 大文件对象,可用于连续写入内容而不关闭文件,直到达到指定的大小
type BigFile struct {
// 文件夹名称
path string
// 当前文件名称
fileName string
// 文件名称前缀
fileNamePrefix string
// 当前文件大小单位Byte
fileSize int
// 最大的文件大小单位Byte
maxFileSize int
// 文件对象
file *os.File
// 获得新文件名称的方法
newFileNameFunc func(string, string) string
}
// 获取文件的完整路径
func (this *BigFile) getFullPath() string {
return filepath.Join(this.path, this.fileName)
}
// 初始化文件对象
func (this *BigFile) initFile() error {
// 初始化文件名称
this.fileName = this.newFileNameFunc(this.fileNamePrefix, this.fileName)
// 初始化文件大小
this.fileSize = 0
// 打开文件
file, err := os.OpenFile(this.getFullPath(), os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm|os.ModeTemporary)
if err != nil {
return fmt.Errorf("打开文件%s错误错误信息为%s", this.getFullPath(), err)
} else {
this.file = file
}
return nil
}
// 返回当前文件名称
// 返回值:
// 当前文件名称
func (this *BigFile) FileName() string {
return this.fileName
}
// 保存消息
// message消息内容
// 返回值:错误对象
func (this *BigFile) SaveMessage(message string) error {
if this.file == nil {
return fmt.Errorf("文件对象为空path:%s", this.getFullPath())
}
// 增加文件大小
this.fileSize += len([]byte(message))
// 写入消息(在结尾处增加一个换行符\n
message = fmt.Sprintf("%s\n", message)
if _, err := this.file.WriteString(message); err != nil {
return fmt.Errorf("向文件%s写入信息错误错误信息为%s", this.getFullPath(), err)
}
// 如果达到了文件的上限,则关闭文件并重新打开一个新文件
if this.fileSize >= this.maxFileSize {
this.Close()
this.initFile()
}
return nil
}
// 写入字节消息
// message消息内容
// 返回值:错误对象
func (this *BigFile) WriteMessage(message []byte) error {
if this.file == nil {
return fmt.Errorf("文件对象为空path:%s", this.getFullPath())
}
// 增加文件大小
this.fileSize += len(message)
// 写入消息
if _, err := this.file.Write(message); err != nil {
return fmt.Errorf("向文件%s写入信息错误错误信息为%s", this.getFullPath(), err)
}
// 如果达到了文件的上限,则关闭文件并重新打开一个新文件
if this.fileSize >= this.maxFileSize {
this.Close()
this.initFile()
}
return nil
}
// 关闭对象
// 返回值:无
func (this *BigFile) Close() {
if this.file != nil {
this.file.Close()
this.file = nil
}
}
// 创建新的大文件对象(obsolete)
// _path:文件夹路径
// _maxFileSize:单个文件大小的最大值单位Byte
// 返回值:
// 大文件对象
// 错误对象
func NewBigFile(_path string, _maxFileSize int) (*BigFile, error) {
return NewBigFileWithNewFileNameFunc(_path, "default", _maxFileSize, newFileName)
}
// 创建新的大文件对象
// _path:文件夹路径
// _fileNamePrefix:文件名称前缀
// _maxFileSize:单个文件大小的最大值单位Byte
// 返回值:
// 大文件对象
// 错误对象
func NewBigFile2(_path, _fileNamePrefix string, _maxFileSize int) (*BigFile, error) {
return NewBigFileWithNewFileNameFunc(_path, _fileNamePrefix, _maxFileSize, newFileName)
}
// 创建新的大文件对象
// _path:文件夹路径
// _fileNamePrefix:文件名称前缀
// _maxFileSize:单个文件大小的最大值单位Byte
// _newFileNameFunc:创建新文件名称的方法
// 返回值:
// 大文件对象
// 错误对象
func NewBigFileWithNewFileNameFunc(_path, _fileNamePrefix string, _maxFileSize int, _newFileNameFunc func(string, string) string) (*BigFile, error) {
return NewBigFileWithNewFileNameFunc2(_path, _fileNamePrefix, "default", _maxFileSize, _newFileNameFunc)
}
// 创建新的大文件对象
// _path:文件夹路径
// _fileNamePrefix:文件名称前缀
// _fileName:文件名称
// _maxFileSize:单个文件大小的最大值单位Byte
// _newFileNameFunc:创建新文件名称的方法
// 返回值:
// 大文件对象
// 错误对象
func NewBigFileWithNewFileNameFunc2(_path, _fileNamePrefix, _fileName string, _maxFileSize int, _newFileNameFunc func(string, string) string) (*BigFile, error) {
// 判断文件夹是否存在,如果不存在则创建
if !IsDirExists(_path) {
os.MkdirAll(_path, os.ModePerm|os.ModeTemporary)
}
// 初始化对象
obj := &BigFile{
path: _path,
fileNamePrefix: _fileNamePrefix,
fileName: _fileName,
maxFileSize: _maxFileSize,
newFileNameFunc: _newFileNameFunc,
}
// 初始化文件对象
if err := obj.initFile(); err != nil {
obj.Close()
return nil, err
}
return obj, nil
}
// 创建新的文件名称
// prefix:前缀
// currFileName:当前文件名称
// 返回值:
// 新的文件名称
func newFileName(prefix, currFileName string) string {
return fmt.Sprintf("%s_%s.data", prefix, timeUtil.Format(time.Now(), "yyyyMMddHHmmss"))
}

View File

@@ -0,0 +1,4 @@
/*
zlib压缩、解压缩相关的助手包
*/
package zlibUtil

View File

@@ -0,0 +1,374 @@
package webServer
import (
"bytes"
"compress/zlib"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"time"
"goutil/logUtil"
"goutil/netUtil"
"goutil/typeUtil"
"goutil/zlibUtil"
)
const (
defaultMaxMemory = 32 << 20 // 32 MB
)
// 请求上下文对象
type Context struct {
// 用户自定义数据(注册回调时设置通过Context传到用户回调) Add:raojianhua Time:2022-02-16 17:00
userData interface{}
// 请求对象
request *http.Request
// 响应对象
responseWriter http.ResponseWriter
// 数据是否已经解析数据
ifBodyParsed bool
// 请求数据
bodyContent []byte
// Form的数据是否已经解析
ifFormParsed bool
// MultipleForm的数据是否已经解析
ifMultipartFormParsed bool
// 是否经过了负载均衡的中转如果是则需要通过header获取客户端实际的请求地址
ifDelegate bool
// 请求的开始时间
StartTime time.Time
// 请求的结束时间
EndTime time.Time
// 处理请求数据的处理器(例如压缩、解密等)
requestDataHandler func(*Context, []byte) ([]byte, error)
// 处理响应数据的处理器(例如压缩、加密等)
responseDataHandler func(*Context, []byte) ([]byte, error)
}
// 获取用户自定义数据(注册回调时设置通过Context传到用户回调) Add:raojianhua Time:2022-02-16 17:00
func (this *Context) GetUserData() interface{} {
return this.userData
}
// 获取请求对象
func (this *Context) GetRequest() *http.Request {
return this.request
}
// 获取响应对象
func (this *Context) GetResponseWriter() http.ResponseWriter {
return this.responseWriter
}
// 获取请求路径(不带参数)
func (this *Context) GetRequestPath() string {
return this.request.URL.Path
}
// 获取请求的客户端的IP地址
func (this *Context) GetRequestIP() string {
if this.ifDelegate {
return netUtil.GetHttpAddr2(this.request).Host
}
return netUtil.GetHttpAddr(this.request).Host
}
// 获取请求执行的秒数
func (this *Context) GetExecuteSeconds() int64 {
return this.EndTime.Unix() - this.StartTime.Unix()
}
// 格式化context对象
func (this *Context) String() string {
var bodyContent string
if bytes, exist, err := this.GetRequestBytes(); err == nil && exist {
bodyContent = string(bytes)
}
return fmt.Sprintf("IP:%s, URL:%s, FormValue:%#v, BodyContent:%s",
this.GetRequestIP(), this.GetRequestPath(), this.GetFormValueData(), bodyContent)
}
func (this *Context) parseForm() {
if !this.ifFormParsed {
// 先保存一份body
this.parseBodyContent()
this.request.ParseMultipartForm(32 << 20)
this.ifFormParsed = true
}
}
// 获取请求的参数值包括GET/POST/PUT/DELETE等所有参数
func (this *Context) FormValue(key string) (value string) {
this.parseForm()
return this.request.FormValue(key)
}
// 获取POST的参数值
func (this *Context) PostFormValue(key string) (value string) {
this.parseForm()
return this.request.PostFormValue(key)
}
// 获取所有参数的MapData类型包括GET/POST/PUT/DELETE等所有参数
func (this *Context) GetFormValueData() typeUtil.MapData {
this.parseForm()
valueMap := make(map[string]interface{})
for k, v := range this.request.Form {
valueMap[k] = v[0]
}
return typeUtil.MapData(valueMap)
}
// 获取POST参数的MapData类型
func (this *Context) GetPostFormValueData() typeUtil.MapData {
this.parseForm()
valueMap := make(map[string]interface{})
for k, v := range this.request.PostForm {
valueMap[k] = v[0]
}
return typeUtil.MapData(valueMap)
}
func (this *Context) parseMultipartForm() {
if !this.ifMultipartFormParsed {
this.request.ParseMultipartForm(defaultMaxMemory)
this.ifMultipartFormParsed = true
}
}
// 获取MultipartForm的MapData类型
func (this *Context) GetMultipartFormValueData() typeUtil.MapData {
this.parseMultipartForm()
valueMap := make(map[string]interface{})
if this.request.MultipartForm != nil {
for k, v := range this.request.MultipartForm.Value {
valueMap[k] = v[0]
}
}
return typeUtil.MapData(valueMap)
}
func (this *Context) parseBodyContent() (err error) {
if this.ifBodyParsed {
return
}
defer func() {
this.request.Body.Close()
this.ifBodyParsed = true
if len(this.bodyContent) > 0 {
this.request.Body = ioutil.NopCloser(bytes.NewBuffer(this.bodyContent))
}
}()
this.bodyContent, err = ioutil.ReadAll(this.request.Body)
if err != nil {
logUtil.ErrorLog(fmt.Sprintf("url:%s,read body failed. Err%s", this.GetRequestPath(), err))
return
}
return
}
// 获取请求字节数据
// 返回值:
// []byte:请求字节数组
// exist:是否存在数据
// error:错误信息
func (this *Context) GetRequestBytes() (result []byte, exist bool, err error) {
if err = this.parseBodyContent(); err != nil {
return
}
result = this.bodyContent
if result == nil || len(result) == 0 {
return
}
// handle request data
if this.requestDataHandler != nil {
if result, err = this.requestDataHandler(this, result); err != nil {
return
}
}
exist = true
return
}
// 获取请求字符串数据
// 返回值:
// result:请求字符串数据
// exist:是否存在数据
// error:错误信息
func (this *Context) GetRequestString() (result string, exist bool, err error) {
var data []byte
if data, exist, err = this.GetRequestBytes(); err != nil || !exist {
return
}
result = string(data)
exist = true
return
}
// 反序列化为对象JSON
// obj:反序列化结果数据
// isCompressed:数据是否已经被压缩
// 返回值:
// 错误对象
func (this *Context) Unmarshal(obj interface{}) (exist bool, err error) {
var data []byte
if data, exist, err = this.GetRequestBytes(); err != nil || !exist {
return
}
// Unmarshal
if err = json.Unmarshal(data, &obj); err != nil {
logUtil.ErrorLog(fmt.Sprintf("Unmarshal %s failed. Err:%s", string(data), err))
return
}
exist = true
return
}
// 反序列化为对象zlib+JSON
// obj:反序列化结果数据
// isCompressed:数据是否已经被压缩
// 返回值:
// 错误对象
func (this *Context) UnmarshalZlib(obj interface{}) (exist bool, err error) {
var data []byte
if data, exist, err = this.GetRequestBytes(); err != nil || !exist {
return
}
zlibBytes, err := zlibUtil.Decompress(data)
if err != nil {
logUtil.ErrorLog(fmt.Sprintf("Decompress %v failed. Err:%s", string(data), err))
return
}
// Unmarshal
if err = json.Unmarshal(zlibBytes, &obj); err != nil {
logUtil.ErrorLog(fmt.Sprintf("Unmarshal %s failed. Err:%s", string(data), err))
return
}
exist = true
return
}
func (this *Context) writeBytes(data []byte) error {
var err error
if this.responseDataHandler != nil {
if data, err = this.responseDataHandler(this, data); err != nil {
return err
}
}
_, err = this.responseWriter.Write(data)
return err
}
// 输出字符串给客户端
func (this *Context) WriteString(result string) error {
return this.writeBytes([]byte(result))
}
// 输出json数据给客户端
func (this *Context) WriteJson(result interface{}) error {
data, err := json.Marshal(result)
if err != nil {
logUtil.ErrorLog(fmt.Sprintf("Marshal %v failed. Err:%s", result, err))
return err
}
return this.writeBytes(data)
}
// 输出zlib+json数据给客户端
func (this *Context) WriteZlibJson(result interface{}) error {
data, err := json.Marshal(result)
if err != nil {
logUtil.ErrorLog(fmt.Sprintf("Marshal %v failed. Err:%s", result, err))
return err
}
zlibBytes, err := zlibUtil.Compress(data, zlib.DefaultCompression)
if err != nil {
logUtil.ErrorLog(fmt.Sprintf("Compress %v failed. Err:%s", string(data), err))
return err
}
return this.writeBytes(zlibBytes)
}
/*
Http状态码301和302概念简单区别
302重定向表示临时性转移(Temporarily Moved )当一个网页URL需要短期变化时使用。 301重定向是永久的重定向搜索引擎在抓取新内容的同时也将旧的网址替换为重定向之后的网址。 302重定向是临时的重定向搜索引擎会抓取新的内容而保留旧的网址。
如果是短链需要每次都访问原来的短链地址以便于进行统计则使用302重定向
*/
// 重定向到其它页面(301)
func (this *Context) RedirectTo(url string) {
this.responseWriter.Header().Set("Location", url)
this.responseWriter.WriteHeader(301)
}
// 重定向到其它页面(302)
func (this *Context) RedirectTo302(url string) {
this.responseWriter.Header().Set("Location", url)
this.responseWriter.WriteHeader(302)
}
// 新建API上下文对象
// request:请求对象
// responseWriter:应答写对象
// _ifDelegate:是否经过负载均衡
// 返回值:
// *Context:上下文
func newContext(request *http.Request, responseWriter http.ResponseWriter,
requestDataHandler func(*Context, []byte) ([]byte, error),
responseDataHandler func(*Context, []byte) ([]byte, error),
_ifDelegate bool) *Context {
return &Context{
request: request,
responseWriter: responseWriter,
StartTime: time.Now(),
EndTime: time.Now(),
requestDataHandler: requestDataHandler,
responseDataHandler: responseDataHandler,
ifDelegate: _ifDelegate,
}
}

View File

@@ -0,0 +1,100 @@
package websocketServer
import (
"fmt"
"github.com/gorilla/websocket"
"net/http"
webServer "Framework/webServer"
"strconv"
"sync"
"testing"
"time"
)
// 处理HTTP请求
func httpHandler(cxt *webServer.Context) {
msg := "test msg"
cxt.GetResponseWriter().Write([]byte(msg))
}
// websocket连接事件
func onConnFunc(ctx *Context) {
fmt.Printf("new conn, ip: %s %p\n", ctx.GetWebServerContext().GetRequestIP(), ctx)
ctx.SendMessage(websocket.TextMessage, []byte("Hello")) // 返回数据
}
// websocket关闭事件
func onCloseFunc(ctx *Context) {
fmt.Printf("close conn, ip: %s %p\n", ctx.GetWebServerContext().GetRequestIP(), ctx)
}
// websocket接收事件
func onMsgFunc(ctx *Context, msgType int, msgData []byte) {
fmt.Printf("%p ", ctx)
fmt.Println("msg ip:", ctx.GetWebServerContext().GetRequestIP(), "msg type:", msgType, "msg:", string(msgData))
ctx.SendMessage(msgType, []byte("SVR: "+string(msgData))) // 返回数据
// 主动关闭连接测试
if string(msgData) == "close" {
ctx.SendMessage(msgType, []byte("close")) // 返回数据
//time.Sleep(time.Microsecond * 100)
ctx.Close()
}
}
func TestWsServer(t *testing.T) {
var ssl bool = false
var server IServer
if ssl {
server = NewWssServer(":22222", "cert.pem", "key.pem", false)
} else {
server = NewWsServer(":22222", false)
}
server.SetIfDelegate(false)
// 注册HTTP处理函数
server.RegisterHandler("/http", httpHandler, &webServer.HandlerConfig{})
// 设置websocket允许跨域访问
server.GetUpgrader().CheckOrigin = func(r *http.Request) bool {
return true
}
//upgrader := &websocket.Upgrader{
// // 允许跨域
// CheckOrigin: func(r *http.Request) bool {
// return true
// },
//}
//server.SetUpgrader(upgrader)
// 注册websocket处理事件
server.RegisterWebsocketHandler("/websocket", &EventCallbackFuncs{
OnConnFunc: onConnFunc,
OnCloseFunc: onCloseFunc,
OnMsgFunc: onMsgFunc,
}, &webServer.HandlerConfig{})
// 设置广播并发数
server.SetBroadcastConcurrent(2)
// 设置接收到Ping消息时自动回复Pong信息
server.SetAutoPong(true)
// 设置心跳检测信息心跳检测周期10秒缺少2个心跳周期断开连接
server.SetHeartbeatDetectInfo(2, time.Second*10)
// 广播测试
go func() {
var i = 0
for {
time.Sleep(time.Second * 10)
// 广播测试
server.BroadcastMessage(websocket.TextMessage, []byte(strconv.Itoa(i)))
i++
}
}()
wg := sync.WaitGroup{}
server.Start(&wg)
}