jk

package module
v0.0.8 Latest Latest
Warning

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

Go to latest
Published: Aug 26, 2025 License: MIT Imports: 8 Imported by: 0

README

介绍

建议版本go版本 >= 1.23.0

安装教程

go get gitee.com/ruige_fun/jk

尽量只使用官方包

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

更多上下文方法

请访问 https://gitee.com/ruige_fun/rht

  • GetIP 获取相对真实客户端IP地址
  • ReadBody 读取请求体
  • ReadQuery 读取请求参数,并且绑定到结构体,并且进行表单校验
  • ReadForm、ReadPostForm、ReadJson、ReadXml 读取表单,并且绑定到结构体,并且进行表单校验
  • GetFormFile、GetFormFileSave、SaveFormFile 获取表单文件
  • WriteStdJSON、WriteStdXML、WriteString、WriteBytes 等等写入响应体方法

常用方法

基本使用

package main

import (
	"gitee.com/ruige_fun/jk"
	"net/http"
	"time"
)

func main() {
	mux := jk.NewServeMux()
	mux.HandleFunc("GET /ping", func(c jk.Context)jk.Error {
		_ = c.Response().WriteStdJSON(http.StatusOK, "", time.Now().String(), nil)
		return nil
	})
	_ = http.ListenAndServe(":8080", mux)
}

访问 http://127.0.0.1:8080/ping

{"code":200,"msg":"","data":{"data":"2025-06-14 18:35:17.4507441 +0800 CST m=+5.791581201","other":null}}

中间件和上下文传值

package main

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

func main() {
	mux := jk.NewServeMux()
	app := mux.Use(printLog0).Use(printLog1)
	app.HandleFunc("GET /ping", func(c jk.Context)jk.Error {
		_ = c.Response().WriteStdJSON(http.StatusOK, "", time.Now().String(), nil)
		return nil
	})
	_ = http.ListenAndServe(":8080", mux)
}

func printLog0(next jk.HandlerFunc) jk.HandlerFunc {
	return func(c jk.Context)jk.Error {
		now := time.Now()
		log.Println("printLog0开始")
		err := next(c)
		log.Println("printLog0结束", c.Request().GetIP(), c.Request().GetMethod(), c.Request().GetURI(), time.Since(now), "uid =", c.Store().GetInt("uid"))
	    return err
	}
}

func printLog1(next jk.HandlerFunc) jk.HandlerFunc {
	return func(c jk.Context)jk.Error {
		now := time.Now()
		log.Println("printLog1开始")
		c.Store().SetInt("uid", 123)
		err := next(c)
		log.Println("printLog1结束", c.Request().GetIP(), c.Request().GetMethod(), c.Request().GetURI(), time.Since(now), "uid =", c.Store().GetInt("uid"))
	    return err
	}
}

访问 http://127.0.0.1:8080/ping

{"code":200,"msg":"","data":{"data":"2025-06-14 18:42:54.045338 +0800 CST m=+13.220488901","other":null}}

控制台输出

2025/06/14 18:42:54 printLog0开始
2025/06/14 18:42:54 printLog1开始
2025/06/14 18:42:54 printLog1结束 127.0.0.1 GET /ping 0s uid = 123
2025/06/14 18:42:54 printLog0结束 127.0.0.1 GET /ping 0s uid = 123

表单绑定&校验

package main

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

func main() {
	mux := jk.NewServeMux()
	mux.HandleFunc("GET /ping", ping)
	_ = http.ListenAndServe(":8080", mux)
}

type pPing struct {
	ID   uint   `json:"id" form:"id" validate:"required,min=1"`
	Name string `json:"name" form:"name" validate:"required,min=1"`
}

func ping(c jk.Context)jk.Error {
	var p pPing
	if err := c.Request().ReadQuery(&p); err != nil {
		return jk.ErrParams
	}
	_ = c.Response().WriteStdJSON(http.StatusOK, "", p, nil)
	return nil
}

访问 http://127.0.0.1:8080/ping?id=1&name=瑞哥

{"code":200,"msg":"","data":{"data":{"id":1,"name":"瑞哥"},"other":null}}

sse事件流

package main

import (
	"gitee.com/ruige_fun/jk"
	"net/http"
	"time"
)

func main() {
	mux := jk.NewServeMux()
	mux.HandleFunc("POST /sse", sseHandler)
	_ = http.ListenAndServe(":8080", mux)
}

func sseHandler(c jk.Context)jk.Error {
	sse, err := jk.NewSSE(c)
	if err != nil {
		return jk.NewHttpError(http.StatusOK, http.StatusInternalServerError, "NewSSE error")
	}
	ticker := time.NewTicker(time.Second)
	for {
		select {
		case <-c.Done():
			return nil
		case <-ticker.C:
			_ = sse.SendData("Hello")
		}
	}
}

websocket

package main

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

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

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

func ws(c jk.Context)jk.Error {
	conn, err := upgrader.Upgrade(c.Response().ResponseWriter(), c.Request().Request(), nil)
	if err != nil {
		log.Println("Upgrade err :", err)
		return jk.ErrUpgradeRequired
	}
	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
		}
	}
	return nil
}

访问 ws://127.0.0.1:8080/ws

静态文件服务

使用官方包文件服务
package main

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

func main() {
	mux := jk.NewServeMux()
	mux.HandleFunc("/static/", fileServer())
	_ = http.ListenAndServe(":8080", mux)
}

func fileServer() func(c jk.Context)jk.Error {
	prefix := http.StripPrefix("/static", http.FileServer(http.Dir("./")))
	return func(c jk.Context)jk.Error {
		prefix.ServeHTTP(c.Response().ResponseWriter(), c.Request().Request())
		return nil
	}
}

访问 http://127.0.0.1:8080/static/

自定义文件下载服务
package main

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

func main() {
	mux := jk.NewServeMux()
	mux.HandleFunc("/static/", fileServer)
	_ = http.ListenAndServe(":8080", mux)
}

func fileServer(c jk.Context)jk.Error {
	filePath := strings.TrimPrefix(c.Request().GetPath(), "/static")
	file, err := os.Open(filepath.Join("./", filePath))
	if err != nil {
		return jk.Err404
	}
	defer file.Close()
	stat, err := file.Stat()
	if err != nil {
		return jk.Err404
	}
	c.Response().HeaderSet(http.CanonicalHeaderKey("Content-Disposition"), "attachment; filename=\""+stat.Name()+"\"")
	http.ServeContent(c.Response().ResponseWriter(), c.Request().Request(), stat.Name(), stat.ModTime(), file)
    return nil
}

自定义文件下载限速
package main

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

func main() {
	mux := jk.NewServeMux()
	mux.HandleFunc("/static/", fileServer)
	_ = http.ListenAndServe(":8080", mux)
}

func fileServer(c jk.Context)jk.Error {
	filePath := strings.TrimPrefix(c.Request().GetPath(), "/static")
	file, err := os.Open(filepath.Join("./", filePath))
	if err != nil {
		return jk.Err404
	}
	defer file.Close()
	stat, err := file.Stat()
	if err != nil {
		return jk.Err404
	}
	c.Response().HeaderSet(http.CanonicalHeaderKey("Content-Disposition"), "attachment; filename=\""+stat.Name()+"\"")

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

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)
}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Err401 = NewHttpError(http.StatusUnauthorized, http.StatusUnauthorized, "身份验证失败!")
View Source
var Err403 = NewHttpError(http.StatusForbidden, http.StatusForbidden, "无权限执行该请求!")
View Source
var Err404 = NewHttpError(http.StatusNotFound, http.StatusNotFound, "请求的资源不存在!")
View Source
var ErrBodyTooLarge = NewHttpError(http.StatusOK, http.StatusRequestEntityTooLarge, "请求体过大!")
View Source
var ErrBusy = NewHttpError(http.StatusOK, http.StatusServiceUnavailable, "系统忙,请稍后再试!")
View Source
var ErrForbidden = NewHttpError(http.StatusOK, http.StatusForbidden, "无权限执行该请求!")
View Source
var ErrGoneDelete = NewHttpError(http.StatusOK, http.StatusGone, "相关记录已不存在!")
View Source
var ErrParams = NewHttpError(http.StatusOK, http.StatusBadRequest, "缺少参数或参数错误!")
View Source
var ErrRecordNotFound = NewHttpError(http.StatusOK, http.StatusNotFound, "相关记录不存在,或请稍后再试!")
View Source
var ErrServerError = NewHttpError(http.StatusOK, http.StatusInternalServerError, "系统忙,请稍后再试!")
View Source
var ErrTimeout = NewHttpError(http.StatusOK, http.StatusRequestTimeout, "请求超时,请稍后再试!")
View Source
var ErrTooManyRequests = NewHttpError(http.StatusOK, http.StatusTooManyRequests, "请求次数过多!")
View Source
var ErrUnauthorized = NewHttpError(http.StatusOK, http.StatusUnauthorized, "身份验证失败,请重新登录!")
View Source
var ErrUnavailableForLegalReasons = NewHttpError(http.StatusOK, http.StatusUnavailableForLegalReasons, "禁止访问!")
View Source
var ErrUpgradeRequired = NewHttpError(http.StatusOK, http.StatusUpgradeRequired, "请升级客户端!")

Functions

This section is empty.

Types

type Context

type Context interface {
	rht.HttpServerContextFunc
}

type Error added in v0.0.5

type Error interface {
	// GetStatusCode 获取http状态码
	GetStatusCode() int
	// GetCode 获取错误码
	GetCode() int
	// GetMsg 获取错误消息内容
	GetMsg() string
	// String 错误信息
	String() string
	// IsEQ 判断错误信息是否相等
	IsEQ(Error) bool
}

func NewHttpError added in v0.0.5

func NewHttpError(statusCode int, code int, msg string) Error

type HandlerFunc added in v0.0.3

type HandlerFunc func(Context) Error

func AnyCORS added in v0.0.8

func AnyCORS(next HandlerFunc) HandlerFunc

type HandlerFuncNotErr added in v0.0.5

type HandlerFuncNotErr func(Context)

type MiddlewareFunc

type MiddlewareFunc func(HandlerFunc) HandlerFunc

func (MiddlewareFunc) Append added in v0.0.3

type SSE added in v0.0.6

type SSE struct {
	// contains filtered or unexported fields
}

func NewSSE added in v0.0.6

func NewSSE(c Context) (*SSE, error)

func (*SSE) Send added in v0.0.6

func (s *SSE) Send(data string, event string, id int64, retry uint) error

func (*SSE) SendBytes added in v0.0.6

func (s *SSE) SendBytes(data []byte, event string, id int64, retry uint) error

func (*SSE) SendData added in v0.0.6

func (s *SSE) SendData(data string) error

func (*SSE) SendDataBytes added in v0.0.6

func (s *SSE) SendDataBytes(data []byte) error

func (*SSE) SendDataJson added in v0.0.6

func (s *SSE) SendDataJson(data any) error

type Serve

type Serve interface {
	// Use 中间件
	Use(fx MiddlewareFunc) Serve
	// Group 分组,自动往请求路径前面增加prevPath
	Group(prevPath string) Serve
	// Handler 响应处理
	Handler(pattern string, handler http.Handler, description ...string)
	// HandleFunc 处理函数
	HandleFunc(pattern string, handler HandlerFunc, description ...string)
	// HandleFuncN 处理函数
	HandleFuncN(pattern string, handler HandlerFuncNotErr, description ...string)

	// Get 常用路由注册方法
	Get(pattern string, handler HandlerFunc, description ...string)
	// Post 常用路由注册方法
	Post(pattern string, handler HandlerFunc, description ...string)
	// Put 常用路由注册方法
	Put(pattern string, handler HandlerFunc, description ...string)
	// Delete 常用路由注册方法
	Delete(pattern string, handler HandlerFunc, description ...string)
	// Patch 常用路由注册方法
	Patch(pattern string, handler HandlerFunc, description ...string)
	// Options 常用路由注册方法
	Options(pattern string, handler HandlerFunc, description ...string)
	// Head 常用路由注册方法
	Head(pattern string, handler HandlerFunc, description ...string)
	// Connect 常用路由注册方法
	Connect(pattern string, handler HandlerFunc, description ...string)
	// Trace 常用路由注册方法
	Trace(pattern string, handler HandlerFunc, description ...string)
	// GetN 常用路由注册方法
	GetN(pattern string, handler HandlerFuncNotErr, description ...string)
	// PostN 常用路由注册方法
	PostN(pattern string, handler HandlerFuncNotErr, description ...string)
	// PutN 常用路由注册方法
	PutN(pattern string, handler HandlerFuncNotErr, description ...string)
	// DeleteN 常用路由注册方法
	DeleteN(pattern string, handler HandlerFuncNotErr, description ...string)
	// PatchN 常用路由注册方法
	PatchN(pattern string, handler HandlerFuncNotErr, description ...string)
	// OptionsN 常用路由注册方法
	OptionsN(pattern string, handler HandlerFuncNotErr, description ...string)
	// HeadN 常用路由注册方法
	HeadN(pattern string, handler HandlerFuncNotErr, description ...string)
	// ConnectN 常用路由注册方法
	ConnectN(pattern string, handler HandlerFuncNotErr, description ...string)
	// TraceN 常用路由注册方法
	TraceN(pattern string, handler HandlerFuncNotErr, description ...string)

	// ServeHTTP http服务
	ServeHTTP(w http.ResponseWriter, r *http.Request)
	// AllRouters 返回所有已注册的路由地址
	AllRouters() []routeStrItem
}

func NewServeMux

func NewServeMux() Serve

Jump to

Keyboard shortcuts

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