jk

package module
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 13, 2024 License: MIT Imports: 18 Imported by: 0

README

介绍

建议版本go版本 >= 1.22.0

安装教程

go get gitee.com/ruige_fun/jk

尽量只使用官方包

  • 路由:net/http默认的。
  • 只是在官方基础上做一层封装,使其支持一些常用的方法。
  • 支持中间件。
  • 支持自定义Validator表单校验。
  • 支持各种读取请求信息方法。
  • 支持各种写入响应体方法。

常用方法

Context方法

  • 兼容:context.Context
  • 兼容:http.ResponseWriter

更多方法:

type Context interface {
    context.Context
    
    // Request 返回原生请求信息 *http.Request
    Request() *http.Request
    // ResponseWriter 返回原生的响应写入,http.ResponseWriter
    ResponseWriter() http.ResponseWriter
    // Logger 返回原生日志包 *slog.Logger
    Logger() *slog.Logger
    
    // Header 响应头
    Header() http.Header
    // Write 写入响应体
    Write(bytes []byte) (int, error)
    // WriteHeader 写入状态码
    WriteHeader(statusCode int)
    // WriteStatusCode 写入状态码
    WriteStatusCode(statusCode int)
    
    // GetIP 获取客户端IP地址
    GetIP() string
    // GetRemoteAddrIP 获取客户端/反向代理服务器IP,如果有反向代理,则获取的是服务器的IP。
    GetRemoteAddrIP() string
    // GetXRealIP 获取真实客户端IP,前提是反向代理里面设置了头 "X-Real-Ip"
    GetXRealIP() string
    // GetXForwardedForIP 获取相对真实的客户端IP,前提是反向代理里面设置了头 "X-Forwarded-For"
    GetXForwardedForIP() string
    
    // ReadBody 获取全部请求体,只能调用一次,第二次会读取不到内容。
    ReadBody() ([]byte, error)
    // ReadJson 读取请求体,并且JSON解码,只能调用一次,第二次会读取不到内容。
    ReadJson(obj any) error
    // ReadXml 读取请求体,并且XML解码,只能调用一次,第二次会读取不到内容。
    ReadXml(obj any) error
    // ReadJsonV 读取请求体,并且JSON解码和Validator校验,只能调用一次,第二次会读取不到内容。
    ReadJsonV(obj any) error
    // ReadXmlV 读取请求体,并且XML解码和Validator校验,只能调用一次,第二次会读取不到内容。
    ReadXmlV(obj any) error
    // Validator 执行一次Validator校验,需要提前调用 mux.SetValidator设置校验函数。
    Validator(obj any) error
    
    // WriteHTML 写入响应体
    WriteHTML(statusCode int, str string) error
    // WriteString 写入响应体。
    WriteString(statusCode int, str string) error
    // WriteBytes 写入响应体。
    WriteBytes(statusCode int, contentType string, body []byte) error
    // WriteStream 写入响应体
    WriteStream(statusCode int, contentType string, reader io.Reader) error
    // WriteFile 写入响应体
    WriteFile(filePath string) error
    // WriteDownload 写入响应体,让前端下载。
    WriteDownload(name string, filePath string) error
    
    // WriteStdJSON 写入响应体,以JSON编码的格式,按 StdResp 结构体来编码。
    WriteStdJSON(code int, msg string, data any, other any) error
    // WriteJSON 写入响应体,以JSON编码的格式。
    WriteJSON(v any) error
    // WriteJSONBytes 写入响应体,以JSON编码的格式。
    WriteJSONBytes(body []byte) error
    // WriteStdXML 写入响应体,以XML编码的格式,按 StdResp 结构体来编码。
    WriteStdXML(code int, msg string, data any, other any) error
    // WriteXML 写入响应体,以XML编码的格式。
    WriteXML(v any) error
    // WriteXMLBytes 写入响应体,以XML编码的格式。
    WriteXMLBytes(body []byte) error
    
    // GetFormFile 获取表单文件
    GetFormFile(name string) (multipart.File, *multipart.FileHeader, error)
    // GetFormFileSave 获取表单文件,并且保存到本地
    GetFormFileSave(name string, saveName string) (int64, error)
    // SaveFormFile 保存表单文件
    SaveFormFile(fh *multipart.FileHeader, dest string) (int64, error)
    // GetQuery 获取URL查询参数
    GetQuery(key string) string
    // GetFormValue 获取URL查询参数
    GetFormValue(key string) string
    // GetPostFormValue 获取请求体表单参数
    GetPostFormValue(key string) string
    // GetPathValue 获取URL路径参数
    GetPathValue(key string) string
    // GetBasicAuth 获取Basic认证信息
    GetBasicAuth() (username, password string, ok bool)
    // GetPath 获取请求路径
    GetPath() string
    // GetURI 获取请求路径和查询参数
    GetURI() string
    // GetHost 获取Host
    GetHost() string
    // GetMethod 获取请求方法
    GetMethod() string
    // GetProto 获取请求协议
    GetProto() string
    // GetHeader 获取请求头
    GetHeader() http.Header
    // GetUserAgent 获取UserAgent
    GetUserAgent() string
    // GetXRequestID 获取请求头 "X-Request-Id"
    GetXRequestID() string
    // GetAuthorization 获取请求头 "Authorization"
    GetAuthorization() string
    // GetXCSRFToken 获取请求头 "X-CSRF-Token"
    GetXCSRFToken() string
    
    // GetQueryString 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetQueryString(key string, def ...string) string
    // GetFormValueString 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetFormValueString(key string, def ...string) string
    // GetPostFormValueString 获取请求体表单参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetPostFormValueString(key string, def ...string) string
    // GetPathValueString 获取URL路径参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetPathValueString(key string, def ...string) string
    
    // GetQueryInt 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetQueryInt(key string, def ...int) int
    // GetFormValueInt 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetFormValueInt(key string, def ...int) int
    // GetPostFormValueInt 获取请求体表单参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetPostFormValueInt(key string, def ...int) int
    // GetPathValueInt 获取URL路径参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetPathValueInt(key string, def ...int) int
    
    // GetQueryUint 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetQueryUint(key string, def ...uint) uint
    // GetFormValueUint 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetFormValueUint(key string, def ...uint) uint
    // GetPostFormValueUint 获取请求体表单参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetPostFormValueUint(key string, def ...uint) uint
    // GetPathValueUint 获取URL路径参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetPathValueUint(key string, def ...uint) uint
    
    // GetQueryInt64 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetQueryInt64(key string, def ...int64) int64
    // GetFormValueInt64 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetFormValueInt64(key string, def ...int64) int64
    // GetPostFormValueInt64 获取请求体表单参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetPostFormValueInt64(key string, def ...int64) int64
    // GetPathValueInt64 获取URL路径参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetPathValueInt64(key string, def ...int64) int64
    
    // GetQueryUint64 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetQueryUint64(key string, def ...uint64) uint64
    // GetFormValueUint64 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetFormValueUint64(key string, def ...uint64) uint64
    // GetPostFormValueUint64 获取请求体表单参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetPostFormValueUint64(key string, def ...uint64) uint64
    // GetPathValueUint64 获取URL路径参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetPathValueUint64(key string, def ...uint64) uint64
    
    // GetQueryFloat64 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetQueryFloat64(key string, def ...float64) float64
    // GetFormValueFloat64 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetFormValueFloat64(key string, def ...float64) float64
    // GetPostFormValueFloat64 获取请求体表单参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetPostFormValueFloat64(key string, def ...float64) float64
    // GetPathValueFloat64 获取URL路径参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetPathValueFloat64(key string, def ...float64) float64
    
    // GetQueryBool 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetQueryBool(key string, def ...bool) bool
    // GetFormValueBool 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetFormValueBool(key string, def ...bool) bool
    // GetPostFormValueBool 获取请求体表单参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetPostFormValueBool(key string, def ...bool) bool
    // GetPathValueBool 获取URL路径参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
    GetPathValueBool(key string, def ...bool) bool
    
    // Store 上下文的数据的kv数据存储管理
    Store() Store
    // Rand 随机函数
    Rand() *rand.Rand
}

上下文kv数据管理

ctx.Store().xxxx

// Store 上下文存储信息,如果key不存在或错误,则随机返回def的任意一个,或者默认值。
type Store interface {
    Set(key string, val any)
    Get(key string, def ...any) (any, bool)
    
    GetString(key string, def ...string) (string, bool)
    
    GetInt(key string, def ...int) (int, bool)
    GetInt8(key string, def ...int8) (int8, bool)
    GetInt16(key string, def ...int16) (int16, bool)
    GetInt32(key string, def ...int32) (int32, bool)
    GetInt64(key string, def ...int64) (int64, bool)
    GetUint(key string, def ...uint) (uint, bool)
    GetUint8(key string, def ...uint8) (uint8, bool)
    GetUint16(key string, def ...uint16) (uint16, bool)
    GetUint32(key string, def ...uint32) (uint32, bool)
    GetUint64(key string, def ...uint64) (uint64, bool)
    
    GetFloat32(key string, def ...float32) (float32, bool)
    GetFloat64(key string, def ...float64) (float64, bool)
    
    GetBool(key string, def ...bool) (bool, bool)
    
    GetTime(key string, def ...time.Time) (time.Time, bool)
}

其它方法

jk.xxxx

  • Rand 随机函数
  • IgnoreOne 传入两个参数,忽略第一个参数,直接返回第二个参数。
  • IgnoreTwo 传入两个参数,忽略第二个参数,直接返回第一个参数。
返回对应类型副本的指针的方法
  • PointerInt(i int) *int
  • PointerUint(i uint) *uint
  • PointerInt32(i int32) *int32
  • PointerInt64(i int64) *int64
  • PointerFloat32(i float32) *float32
  • PointerFloat64(i float64) *float64
  • PointerString(str string) *string
  • PointerFalse() *bool
  • PointerTrue() *bool
字符串转换成其它类型
  • StrToInt(str string) int
  • StrToInt32(str string) int32
  • StrToInt64(str string) int64
  • StrToUint(str string) uint
  • StrToUint32(str string) uint32
  • StrToUint64(str string) uint64
  • StrToFloat32(str string) float32
  • StrToFloat64(str string) float64
  • StrToBool(str string) bool

用法

简单用法

package main

import (
	"fmt"
	"gitee.com/ruige_fun/jk"
	"log"
	"log/slog"
	"net/http"
)

func main() {
	slog.SetLogLoggerLevel(slog.LevelDebug)
	mux := jk.NewServeMux(slog.Default())
	mux.HandleFunc("GET /ping/{id}", ping)
	mux.HandleFunc("POST /ping/{id}", ping)
	_ = http.ListenAndServe(":8080", mux)
}

func ping(ctx jk.Context) {
	log.Println(ctx.GetMethod(), fmt.Sprintf("http://127.0.0.1:8080%v", ctx.GetURI()), ":", ctx.GetPathValueInt("id"), ctx.GetFormValue("name"))
	_, _ = ctx.Write([]byte("ok"))
}

运行结果

2024/08/09 11:50:54 GET http://127.0.0.1:8080/ping/1?name=abc123 : 1 abc123
2024/08/09 11:51:08 POST http://127.0.0.1:8080/ping/1?name=abc123 : 1 abc123

表单验证

使用github.com/go-playground/validator/v10来表单验证。

package main

import (
	"fmt"
	"gitee.com/ruige_fun/jk"
	"github.com/go-playground/validator/v10"
	"log"
	"log/slog"
	"net/http"
)

func main() {
	slog.SetLogLoggerLevel(slog.LevelDebug)
	mux := jk.NewServeMux(slog.Default())
	mux.SetValidator(validator.New()) //添加表单验证
	mux.HandleFunc("GET /ping/{id}", ping)
	mux.HandleFunc("POST /ping/{id}", ping)
	_ = http.ListenAndServe(":8080", mux)
}

type Query struct {
	ID   uint64 `json:"id" validate:"required,min=100"`
	Name string `json:"name" validate:"required,min=1"`
}

func ping(ctx jk.Context) {
	log.Println(ctx.GetMethod(), fmt.Sprintf("http://127.0.0.1:8080%v", ctx.GetURI()), ":", ctx.GetPathValueInt("id"), ctx.GetFormValue("name"))
	var q = Query{
		ID:   ctx.GetPathValueUint64("id"),
		Name: ctx.GetFormValueString("name"),
	}
	err := ctx.Validator(&q)
	log.Println("表单验证结果:", err)
	_, _ = ctx.Write([]byte("ok"))

}

运行结果

2024/08/09 12:03:00 GET http://127.0.0.1:8080/ping/1?name=abc123 : 1 abc123
2024/08/09 12:03:00 表单验证结果: Key: 'Query.ID' Error:Field validation for 'ID' failed on the 'min' tag
2024/08/09 12:03:15 GET http://127.0.0.1:8080/ping/99?name=abc123 : 99 abc123
2024/08/09 12:03:15 表单验证结果: Key: 'Query.ID' Error:Field validation for 'ID' failed on the 'min' tag
2024/08/09 12:03:24 GET http://127.0.0.1:8080/ping/100?name=abc123 : 100 abc123
2024/08/09 12:03:24 表单验证结果: <nil>
2024/08/09 12:03:31 GET http://127.0.0.1:8080/ping/101?name=abc123 : 101 abc123
2024/08/09 12:03:31 表单验证结果: <nil>

websocket服务

package main

import (
	"github.com/gorilla/websocket"
	"gitee.com/ruige_fun/jk"
	"log"
	"log/slog"
	"net/http"
)

func main() {
	slog.SetLogLoggerLevel(slog.LevelDebug)
	mux := jk.NewServeMux(slog.Default())
	mux.HandleFunc("/ws", ws)
	_ = http.ListenAndServe(":8080", mux)
}

var upgrader = websocket.Upgrader{CheckOrigin: func(r *http.Request) bool {
	return true
}}

func ws(ctx jk.Context) {
	conn, err := upgrader.Upgrade(ctx.ResponseWriter(), ctx.Request(), nil)
	if err != nil {
		log.Println("Upgrade err :", err)
		_ = ctx.WriteString(http.StatusMethodNotAllowed, "不支持websocket")
		return
	}
	defer conn.Close()
	for {
		mt, msg, err := conn.ReadMessage()
		if err != nil {
			log.Println("ReadMessage err :", err)
			break
		}
		log.Println("recv :", string(msg))
		err = conn.WriteMessage(mt, msg)
		if err != nil {
			log.Println("WriteMessage err :", err)
			break
		}
	}
}

静态文件服务

使用官方包的http.FileServer
package main

import (
	"fmt"
	"gitee.com/ruige_fun/jk"
	"log/slog"
	"net/http"
)

func main() {
	slog.SetLogLoggerLevel(slog.LevelDebug)
	mux := jk.NewServeMux(slog.Default())
	mux.HandleFunc("/static/", func() func(context jk.Context) {
		//使用闭包的方式,是为了让下面这行创建静态服务的时候,只创建一次。而不是每次请求都创建一次。
		prefix := http.StripPrefix("/static", http.FileServer(http.Dir("./")))
		return func(ctx jk.Context) {
			fmt.Println(&prefix, ctx.GetURI())
			prefix.ServeHTTP(ctx.ResponseWriter(), ctx.Request())
		}
	}())
	_ = http.ListenAndServe(":8080", mux)
}

访问:http://127.0.0.1:8080/static/ 返回结果:

<pre>
<a href=".idea/">.idea/</a>
<a href="1.txt">1.txt</a>
<a href="go.mod">go.mod</a>
<a href="go.sum">go.sum</a>
<a href="jk/">jk/</a>
<a href="main.go">main.go</a>
<a href="readme.md">readme.md</a>
<a href="%E7%BC%96%E8%AF%91%E6%88%90Linux.cmd">编译成Linux.cmd</a>
<a href="%E7%BC%96%E8%AF%91%E6%88%90Windows.cmd">编译成Windows.cmd</a>
</pre>
自己写一个文件服务
package main

import (
	"gitee.com/ruige_fun/jk"
	"log/slog"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

func main() {
	slog.SetLogLoggerLevel(slog.LevelDebug)
	mux := jk.NewServeMux(slog.Default())
	mux.HandleFunc("/static/", FileServer)
	_ = http.ListenAndServe(":8080", mux)
}

func FileServer(ctx jk.Context) {
	filePath := strings.TrimPrefix(ctx.GetPath(), "/static")
	file, err := os.Open(filepath.Join("./", filePath))
	if err != nil {
		ctx.WriteHeader(http.StatusNotFound)
		return
	}
	defer file.Close()
	fi, err := file.Stat()
	if err != nil {
		ctx.WriteHeader(http.StatusNotFound)
		return
	}
	http.ServeContent(ctx.ResponseWriter(), ctx.Request(), fi.Name(), fi.ModTime(), file)
}

限制每个请求的下载速度
package main

import (
	"fmt"
	"gitee.com/ruige_fun/jk"
	"io"
	"log/slog"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"
)

func main() {
	slog.SetLogLoggerLevel(slog.LevelDebug)
	mux := jk.NewServeMux(slog.Default())
	mux.HandleFunc("/static/", FileServer)
	_ = http.ListenAndServe(":8080", mux)
}

func FileServer(ctx jk.Context) {
	filePath := strings.TrimPrefix(ctx.GetPath(), "/static")
	fmt.Println(ctx.GetURI())
	file, err := os.Open(filepath.Join("./", filePath))
	if err != nil {
		ctx.WriteHeader(http.StatusNotFound)
		return
	}
	defer file.Close()
	fi, err := file.Stat()
	if err != nil {
		ctx.WriteHeader(http.StatusNotFound)
		return
	}
	ctx.Header().Set(jk.HeaderContentDisposition, "attachment; filename=\""+fi.Name()+"\"")

	ticker := time.NewTicker(time.Second) //设置每个刻度多长时间。
	defer ticker.Stop()
	http.ServeContent(ctx.ResponseWriter(), ctx.Request(), fi.Name(), fi.ModTime(), NewReadSeeker(file, ticker, 100*1024))
}

func NewReadSeeker(file *os.File, ticker *time.Ticker, rateSize int64) io.ReadSeeker {
	return &_File{file: file, rateSize: rateSize, ticker: ticker}
}

var _ io.ReadSeeker = new(_File)

type _File struct {
	file     *os.File
	tempSize int64
	rateSize int64 //大概值,这种方式无法做到准确值。
	ticker   *time.Ticker
}

func (f *_File) Read(p []byte) (n int, err error) {
	if f.tempSize >= f.rateSize {
		<-f.ticker.C
		f.tempSize = 0
	}
	n, err = f.file.Read(p)
	if n > 0 {
		f.tempSize += int64(n)
	}
	return n, err
}

func (f *_File) Seek(offset int64, whence int) (int64, error) {
	return f.file.Seek(offset, whence)
}

中间件

简单案例

type MiddlewareFunc func(Context) bool

中间件返回true,则继续往后执行代码。

中间件返回false则停止后续的代码。

package main

import (
	"fmt"
	"gitee.com/ruige_fun/jk"
	"log"
	"log/slog"
	"net/http"
)

func main() {
	slog.SetLogLoggerLevel(slog.LevelDebug)
	mux := jk.NewServeMux(slog.Default())
	mux.Use(func(ctx jk.Context) bool {
		log.Println("中间件:", ctx.GetMethod(), ctx.GetURI())
		return true
	})
	mux.HandleFunc("GET /ping/{id}", ping)
	_ = http.ListenAndServe(":8080", mux)
}

func ping(ctx jk.Context) {
	log.Println(ctx.GetMethod(), fmt.Sprintf("http://127.0.0.1:8080%v", ctx.GetURI()), ":", ctx.GetPathValueInt("id"), ctx.GetFormValue("name"))
	_, _ = ctx.Write([]byte("ok"))
}

运行结果

2024/08/09 11:52:11 中间件: GET /ping/1?name=abc123
2024/08/09 11:52:11 GET http://127.0.0.1:8080/ping/1?name=abc123 : 1 abc123

跨域
package main

import (
	"fmt"
	"gitee.com/ruige_fun/jk"
	"log"
	"log/slog"
	"net/http"
)

func main() {
	slog.SetLogLoggerLevel(slog.LevelDebug)
	mux := jk.NewServeMux(slog.Default())
	mux.Use(jk.CORS)
	mux.HandleFunc("GET /ping/{id}", ping)
	mux.HandleFunc("POST /ping/{id}", ping)
	_ = http.ListenAndServe(":8080", mux)
}

func ping(ctx jk.Context) {
	log.Println(ctx.GetMethod(), fmt.Sprintf("http://127.0.0.1:8080%v", ctx.GetURI()), ":", ctx.GetPathValueInt("id"), ctx.GetFormValue("name"))
	_, _ = ctx.Write([]byte("ok"))
}

复杂案例
package main

import (
	"encoding/json"
	"gitee.com/ruige_fun/jk"
	"log"
	"log/slog"
	"net/http"
)

func main() {
	slog.SetLogLoggerLevel(slog.LevelDebug)
	mux := jk.NewServeMux(slog.Default())
	group := mux.Group("/haha")
	use := group.Use(MdGet)
	group.HandleFunc("GET /ping/{id}", ping)
	mux.Use(MdPost)
	mux.HandleFunc("POST /ping/{id}", ping)
	use.Use(MdPut)
	use.HandleFunc("PUT /ping/{id}", ping)
	_ = http.ListenAndServe(":8080", mux)
}

func ping(ctx jk.Context) {
	log.Println(ctx.GetMethod(), ctx.GetURI())
	_, _ = ctx.Write([]byte("ok"))
}

func MdGet(ctx jk.Context) bool {
	ctx.WriteHeader(404)
	marshal, _ := json.Marshal(ctx.Request().Header)
	log.Println("中间件GET:", string(marshal))
	return true
}

func MdPost(ctx jk.Context) bool {
	marshal, _ := json.Marshal(ctx.Request().Header)
	log.Println("中间件POST:", string(marshal))
	return true
}

func MdPut(ctx jk.Context) bool {
	marshal, _ := json.Marshal(ctx.Request().Header)
	log.Println("中间件PUT:", string(marshal))
	return true
}

运行结果:

2024/08/09 11:53:53 中间件GET: {"Accept":["*/*"],"Accept-Encoding":["gzip, deflate, br"],"Cache-Control":["no-cache"],"Connection":["keep-alive"],"User-Agent":["PostmanRuntime-ApipostRuntime/1.1.0"]}
2024/08/09 11:53:53 GET /haha/ping/1?name=abc123
2024/08/09 11:54:08 中间件POST: {"Accept":["*/*"],"Accept-Encoding":["gzip, deflate, br"],"Cache-Control":["no-cache"],"Connection":["keep-alive"],"Content-Length":["0"],"User-Agent":["PostmanRuntime-ApipostRuntime/1.1.0"]}
2024/08/09 11:54:08 POST /ping/1?name=abc123
2024/08/09 11:54:17 中间件GET: {"Accept":["*/*"],"Accept-Encoding":["gzip, deflate, br"],"Cache-Control":["no-cache"],"Connection":["keep-alive"],"Content-Length":["0"],"User-Agent":["PostmanRuntime-ApipostRuntime/1.1.0"]}
2024/08/09 11:54:17 中间件PUT: {"Accept":["*/*"],"Accept-Encoding":["gzip, deflate, br"],"Cache-Control":["no-cache"],"Connection":["keep-alive"],"Content-Length":["0"],"User-Agent":["PostmanRuntime-ApipostRuntime/1.1.0"]}
2024/08/09 11:54:17 PUT /haha/ping/1?name=abc123

Documentation

Index

Constants

View Source
const (
	CorsAccessControlAllowHeaders = "Content-Type,Authorization,X-Request-Id,X-CSRF-Token,Sign"
	CorsAccessControlAllowMethods = "GET,HEAD,POST,PUT,PATCH,DELETE,CONNECT,OPTIONS,TRACE"
)
View Source
const (
	ContentTypeJSON      = "application/json; charset=utf-8"
	ContentTypeXML       = "application/xml; charset=utf-8"
	ContentTypeStream    = "application/octet-stream"
	ContentTypeDownload  = `application/force-download`             //文件下载
	ContentTypeTextPlain = `text/plain; charset=utf-8`              //文本
	ContentTypeHTML      = `text/html; charset=utf-8`               //HTML
	ContentTypeXJS       = `application/x-javascript;charset=utf-8` //JavaScript
	ContentTypeJS        = `text/javascript; charset=utf-8`         //JavaScript
	ContentTypeCSS       = `text/css; charset=utf-8`                //CSS

	ContentTypeImageJPEG = `image/jpeg`   //jpeg图片
	ContentTypeImageJPG  = `image/jpeg`   //jpg图片
	ContentTypeImagePNG  = `image/png`    //png图片
	ContentTypeImageWEBP = `image/webp`   //webp图片
	ContentTypeImageGIF  = `image/gif`    //gif图片
	ContentTypeImageICON = `image/x-icon` //icon图标

	HeaderXRequestID         = "X-Request-Id"
	HeaderAuthorization      = "Authorization"
	HeaderContentType        = "Content-Type"
	HeaderContentDisposition = "Content-Disposition"
	HeaderCookie             = "Cookie"
	HeaderSetCookie          = "Set-Cookie"
	HeaderXCSRFToken         = "X-CSRF-Token"
	HeaderUpgrade            = "Upgrade"
	HeaderSign               = "Sign"

	HeaderXRealIP       = "X-Real-Ip"
	HeaderXForwardedFor = "X-Forwarded-For"
)

Variables

View Source
var Rand = rand.New(rand.NewPCG(uint64(time.Now().UnixNano()+rand.Int64N(1024)), rand.Uint64()))

Functions

func CORS

func CORS(c Context) bool

func IgnoreOne

func IgnoreOne[T1 any, T2 any](_t1 T1, _t2 T2) T2

IgnoreOne 忽略第一个参数,直接返回第二个参数。

func IgnoreTwo

func IgnoreTwo[T1 any, T2 any](_t1 T1, _t2 T2) T1

IgnoreTwo 忽略第二个参数,直接返回第一个参数。

func PointerFalse

func PointerFalse() *bool

func PointerFloat32

func PointerFloat32(i float32) *float32

func PointerFloat64

func PointerFloat64(i float64) *float64

func PointerInt

func PointerInt(i int) *int

func PointerInt32

func PointerInt32(i int32) *int32

func PointerInt64

func PointerInt64(i int64) *int64

func PointerString

func PointerString(str string) *string

func PointerTrue

func PointerTrue() *bool

func PointerUint

func PointerUint(i uint) *uint

func StrToBool

func StrToBool(str string) bool

func StrToFloat32

func StrToFloat32(str string) float32

func StrToFloat64

func StrToFloat64(str string) float64

func StrToInt

func StrToInt(str string) int

func StrToInt32

func StrToInt32(str string) int32

func StrToInt64

func StrToInt64(str string) int64

func StrToUint

func StrToUint(str string) uint

func StrToUint32

func StrToUint32(str string) uint32

func StrToUint64

func StrToUint64(str string) uint64

Types

type Context

type Context interface {
	context.Context

	// Request 返回原生请求信息 *http.Request
	Request() *http.Request
	// ResponseWriter 返回原生的响应写入,http.ResponseWriter
	ResponseWriter() http.ResponseWriter
	// Logger 返回原生日志包 *slog.Logger
	Logger() *slog.Logger

	// Header 响应头
	Header() http.Header
	// Write 写入响应体
	Write(bytes []byte) (int, error)
	// WriteHeader 写入状态码
	WriteHeader(statusCode int)
	// WriteStatusCode 写入状态码
	WriteStatusCode(statusCode int)

	// GetIP 获取客户端IP地址
	GetIP() string
	// GetRemoteAddrIP 获取客户端/反向代理服务器IP,如果有反向代理,则获取的是服务器的IP。
	GetRemoteAddrIP() string
	// GetXRealIP 获取真实客户端IP,前提是反向代理里面设置了头 "X-Real-Ip"
	GetXRealIP() string
	// GetXForwardedForIP 获取相对真实的客户端IP,前提是反向代理里面设置了头 "X-Forwarded-For"
	GetXForwardedForIP() string

	// ReadBody 获取全部请求体,只能调用一次,第二次会读取不到内容。
	ReadBody() ([]byte, error)
	// ReadJson 读取请求体,并且JSON解码,只能调用一次,第二次会读取不到内容。
	ReadJson(obj any) error
	// ReadXml 读取请求体,并且XML解码,只能调用一次,第二次会读取不到内容。
	ReadXml(obj any) error
	// ReadJsonV 读取请求体,并且JSON解码和Validator校验,只能调用一次,第二次会读取不到内容。
	ReadJsonV(obj any) error
	// ReadXmlV 读取请求体,并且XML解码和Validator校验,只能调用一次,第二次会读取不到内容。
	ReadXmlV(obj any) error
	// Validator 执行一次Validator校验,需要提前调用 mux.SetValidator设置校验函数。
	Validator(obj any) error

	// WriteHTML 写入响应体
	WriteHTML(statusCode int, str string) error
	// WriteString 写入响应体。
	WriteString(statusCode int, str string) error
	// WriteBytes 写入响应体。
	WriteBytes(statusCode int, contentType string, body []byte) error
	// WriteStream 写入响应体
	WriteStream(statusCode int, contentType string, reader io.Reader) error
	// WriteFile 写入响应体
	WriteFile(filePath string) error
	// WriteDownload 写入响应体,让前端下载。
	WriteDownload(name string, filePath string) error

	// WriteStdJSON 写入响应体,以JSON编码的格式,按 StdResp 结构体来编码。
	WriteStdJSON(code int, msg string, data any, other any) error
	// WriteJSON 写入响应体,以JSON编码的格式。
	WriteJSON(v any) error
	// WriteJSONBytes 写入响应体,以JSON编码的格式。
	WriteJSONBytes(body []byte) error
	// WriteStdXML 写入响应体,以XML编码的格式,按 StdResp 结构体来编码。
	WriteStdXML(code int, msg string, data any, other any) error
	// WriteXML 写入响应体,以XML编码的格式。
	WriteXML(v any) error
	// WriteXMLBytes 写入响应体,以XML编码的格式。
	WriteXMLBytes(body []byte) error

	// GetFormFile 获取表单文件
	GetFormFile(name string) (multipart.File, *multipart.FileHeader, error)
	// GetFormFileSave 获取表单文件,并且保存到本地
	GetFormFileSave(name string, saveName string) (int64, error)
	// SaveFormFile 保存表单文件
	SaveFormFile(fh *multipart.FileHeader, dest string) (int64, error)
	// GetQuery 获取URL查询参数
	GetQuery(key string) string
	// GetFormValue 获取URL查询参数
	GetFormValue(key string) string
	// GetPostFormValue 获取请求体表单参数
	GetPostFormValue(key string) string
	// GetPathValue 获取URL路径参数
	GetPathValue(key string) string
	// GetBasicAuth 获取Basic认证信息
	GetBasicAuth() (username, password string, ok bool)
	// GetPath 获取请求路径
	GetPath() string
	// GetURI 获取请求路径和查询参数
	GetURI() string
	// GetHost 获取Host
	GetHost() string
	// GetMethod 获取请求方法
	GetMethod() string
	// GetProto 获取请求协议
	GetProto() string
	// GetHeader 获取请求头
	GetHeader() http.Header
	// GetUserAgent 获取UserAgent
	GetUserAgent() string
	// GetXRequestID 获取请求头 "X-Request-Id"
	GetXRequestID() string
	// GetAuthorization 获取请求头 "Authorization"
	GetAuthorization() string
	// GetXCSRFToken 获取请求头 "X-CSRF-Token"
	GetXCSRFToken() string

	// GetQueryString 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetQueryString(key string, def ...string) string
	// GetFormValueString 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetFormValueString(key string, def ...string) string
	// GetPostFormValueString 获取请求体表单参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetPostFormValueString(key string, def ...string) string
	// GetPathValueString 获取URL路径参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetPathValueString(key string, def ...string) string

	// GetQueryInt 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetQueryInt(key string, def ...int) int
	// GetFormValueInt 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetFormValueInt(key string, def ...int) int
	// GetPostFormValueInt 获取请求体表单参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetPostFormValueInt(key string, def ...int) int
	// GetPathValueInt 获取URL路径参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetPathValueInt(key string, def ...int) int

	// GetQueryUint 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetQueryUint(key string, def ...uint) uint
	// GetFormValueUint 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetFormValueUint(key string, def ...uint) uint
	// GetPostFormValueUint 获取请求体表单参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetPostFormValueUint(key string, def ...uint) uint
	// GetPathValueUint 获取URL路径参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetPathValueUint(key string, def ...uint) uint

	// GetQueryInt64 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetQueryInt64(key string, def ...int64) int64
	// GetFormValueInt64 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetFormValueInt64(key string, def ...int64) int64
	// GetPostFormValueInt64 获取请求体表单参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetPostFormValueInt64(key string, def ...int64) int64
	// GetPathValueInt64 获取URL路径参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetPathValueInt64(key string, def ...int64) int64

	// GetQueryUint64 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetQueryUint64(key string, def ...uint64) uint64
	// GetFormValueUint64 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetFormValueUint64(key string, def ...uint64) uint64
	// GetPostFormValueUint64 获取请求体表单参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetPostFormValueUint64(key string, def ...uint64) uint64
	// GetPathValueUint64 获取URL路径参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetPathValueUint64(key string, def ...uint64) uint64

	// GetQueryFloat64 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetQueryFloat64(key string, def ...float64) float64
	// GetFormValueFloat64 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetFormValueFloat64(key string, def ...float64) float64
	// GetPostFormValueFloat64 获取请求体表单参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetPostFormValueFloat64(key string, def ...float64) float64
	// GetPathValueFloat64 获取URL路径参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetPathValueFloat64(key string, def ...float64) float64

	// GetQueryBool 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetQueryBool(key string, def ...bool) bool
	// GetFormValueBool 获取URL查询参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetFormValueBool(key string, def ...bool) bool
	// GetPostFormValueBool 获取请求体表单参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetPostFormValueBool(key string, def ...bool) bool
	// GetPathValueBool 获取URL路径参数,如果不存在或错误,则随机返回def的任意一个,或者默认值。
	GetPathValueBool(key string, def ...bool) bool

	// Store 上下文的数据的kv数据存储管理
	Store() Store
	// Rand 随机函数
	Rand() *rand.Rand
}

type MiddlewareFunc

type MiddlewareFunc func(Context) bool

type Serve

type Serve interface {
	// Use 中间件
	Use(fx MiddlewareFunc) Serve
	// Group 分组,自动往请求路径前面增加prevPath
	Group(prevPath string) Serve
	// HandleFunc 处理函数
	HandleFunc(pattern string, handler func(Context))
	// ServeHTTP http服务
	ServeHTTP(w http.ResponseWriter, r *http.Request)
	// AllRouters 返回所有已注册的路由地址
	AllRouters() []string
	// SetValidator 设置表单校验的函数
	SetValidator(v Validator)
}

func NewServeMux

func NewServeMux(logger *slog.Logger) Serve

type StdResp

type StdResp struct {
	Code int         `json:"code" xml:"code"`
	Msg  string      `json:"msg" xml:"msg"`
	Data StdRespData `json:"data" xml:"data"`
}

type StdRespData

type StdRespData struct {
	Data  any `json:"data" xml:"data"`
	Other any `json:"other" xml:"other"`
}

type Store

type Store interface {
	Set(key string, val any)
	Get(key string, def ...any) (any, bool)

	GetString(key string, def ...string) (string, bool)

	GetInt(key string, def ...int) (int, bool)
	GetInt8(key string, def ...int8) (int8, bool)
	GetInt16(key string, def ...int16) (int16, bool)
	GetInt32(key string, def ...int32) (int32, bool)
	GetInt64(key string, def ...int64) (int64, bool)
	GetUint(key string, def ...uint) (uint, bool)
	GetUint8(key string, def ...uint8) (uint8, bool)
	GetUint16(key string, def ...uint16) (uint16, bool)
	GetUint32(key string, def ...uint32) (uint32, bool)
	GetUint64(key string, def ...uint64) (uint64, bool)

	GetFloat32(key string, def ...float32) (float32, bool)
	GetFloat64(key string, def ...float64) (float64, bool)

	GetBool(key string, def ...bool) (bool, bool)

	GetTime(key string, def ...time.Time) (time.Time, bool)
}

Store 上下文存储信息,如果key不存在或错误,则随机返回def的任意一个,或者默认值。

type Validator

type Validator interface {
	Struct(interface{}) error
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL