whttp

package module
v0.0.0-...-dbf4827 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2025 License: MIT Imports: 18 Imported by: 0

README

WHTTP

WHTTP 是一个用Go 开发的 web 脚手架,基于标准库简单封装。

特性:

  • 中间件支持

开始

必要条件

需要 Go 版本 1.22 以上

获取

下载

go get github.com/duomi520/whttp

将 WHTTP 引入到代码中

import "github.com/duomi520/whttp"
运行

简单例子:

package main

import (
  "github.com/duomi520/whttp"
  "log/slog"
  "net/http"
)

func main() {
  route := whttp.NewRoute(nil)
  // 配置服务
  srv := &http.Server{
    Handler:        route.Mux,
    MaxHeaderBytes: 1 << 20,
  }
  route.GET("/", func(c *whttp.HTTPContext) {
    c.String(http.StatusOK, "Hi")
  })
  // 监听并在 0.0.0.0 上启动服务 (windows "localhost")
  if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
    slog.Error(err.Error())
  }
}

使用go run 命令运行:

go run main.go

在您的浏览器查看结果 0.0.0.0 !

api 的用法

路由定义
  • GET 查询数据,对应 get 请求
  • POST 创建数据,对应 post 请求
  • PUT 更新数据,对应 put 请求
  • DELETE 删除数据,对应 delete 请求
控制器函数

控制器函数只接受一个 whttp.HTTPContext 上下文参数

func HandlerFunc(c *whttp.HTTPContext)

(whttp.HTTPContext).Writer 为原始的 http.ResponseWriter

(whttp.HTTPContext).Request 为原始的 *http.Request

路由参数
//匹配 /user/linda/mobile/xxxxxxxx
route.GET("/user/{name}/mobile/{mobile}", func(c *HTTPContext) {
  user := c.Request.PathValue("name")
  mobile := c.Request.PathValue("mobile")
  c.String(http.StatusOK, user+mobile)
})
查询字符串参数
//示例 URL: /name=linda&mobile=xxxxxxxx
route.POST("/", func(c *HTTPContext) {
  user := c.Request.FormValue("name")
  mobile := c.Request.FormValue("mobile")
  c.String(http.StatusOK, user+mobile)
})
操作 解析 读取 URL 读取 Body(表单) 支持文本 支持二进制
Form ParseForm
PostForm ParseForm
FormValue 自动调用 ParseForm
PostFormValue 自动调用 ParseForm
MultipartForm ParseMultipartForm
FormFile 自动调用 ParseMultipartForm
响应方式

status 为 http 状态码,响应方式会在中间件执行完毕后执行

  • 返回字符串 func (c *HTTPContext) String(status int, msg string)
  • 返回 JSON func (c *HTTPContext) JSON(status int, v any)
  • 返回二进制 func (c *HTTPContext) Blob(status int, contentType string, data []byte)
  • 返回文件 func (c *HTTPContext) File(filepath string)

自定义

c.Flush = func() (int, error) {
  return c.Writer.Write(d)
}
模板

模版文件 file.tmpl 内容

{{.}}

渲染模版文件

//解析模板文件
tl, err := template.ParseFiles("file.tmpl")
if err != nil {
  c.String(http.StatusInternalServerError, err.Error())
}
//注册模板
route.SetRenderer(tl)
route.GET("/", func(c *HTTPContext) {
  //渲染模板
  c.Render(http.StatusOK, "file.tmpl", "6月7日")
})

渲染结果为:6 月 7 日

静态文件服务

group 为中间件函数,Static 单个文件服务,StaticFS 目录服务

func (r *WRoute) Static(relativePath, root string, group ...func(*HTTPContext))

route.Static("/", "welcome.txt")

func (r *WRoute) StaticFS(dir string, group ...func(*HTTPContext))

route.StaticFS("txt")
中间件

中间件指的是可以拦截 http 请求-响应生命周期的特殊函数,在请求-响应生命周期中可以注册多个中间件,每个中间件执行不同的功能,一个中间执行完再轮到下一个中间件执行

Middleware := func() func(*HTTPContext) {
return func(c *HTTPContext) {
  //处理拦截请求的逻辑
  fmt.Println("前处理")
  //执行下一个中间件或者执行控制器函数
  c.Next()
  //后处理
  fmt.Println("后处理")
}
}

为每个路由添加任意数量的中间件

route.GET("/some", MiddlewareA(),MiddlewareB(), Endpoint)

为中间件建一切片,简化重复输入

g := []func(*HTTPContext){MiddlewareA(), MiddlewareB(), MiddlewareC()}
route.GET("/some", append(g, Endpoint)...)

全局中间件,需在初始化后立即加载。

route.Use(LoggerMiddleware())
自定义日志

日志使用 "log/slog" ,NewRoute()初始化路由时加载自定义日志

func(c *HTTPContext) {
  c.Debug("This is Debug Level")
  c.Info("This is Info Level")
  c.Warn("This is Warn Level")
  c.Error("This is Error Level")
}

进阶的用法

examples 样例库

与众不同的模块

待续...

Documentation

Index

Constants

View Source
const (
	// MIME text
	MIMETextPlain             = "text/plain"
	MIMETextPlainUTF8         = "text/plain; charset=utf-8"
	MIMETextPlainISO88591     = "text/plain; charset=iso-8859-1"
	MIMETextPlainFormatFlowed = "text/plain; format=flowed"
	MIMETextPlainDelSpaceYes  = "text/plain; delsp=yes"
	MIMETextPlainDelSpaceNo   = "text/plain; delsp=no"
	MIMETextHtml              = "text/html"
	MIMETextCss               = "text/css"
	MIMETextJavascript        = "text/javascript"
	MIMETextCSV               = "text/csv"
	// MIME application
	MIMEApplicationOctetStream  = "application/octet-stream"
	MIMEApplicationFlash        = "application/x-shockwave-flash"
	MIMEApplicationHTMLForm     = "application/x-www-form-urlencoded"
	MIMEApplicationHTMLFormUTF8 = "application/x-www-form-urlencoded; charset=UTF-8"
	MIMEApplicationTar          = "application/x-tar"
	MIMEApplicationGZip         = "application/gzip"
	MIMEApplicationXGZip        = "application/x-gzip"
	MIMEApplicationBZip2        = "application/bzip2"
	MIMEApplicationXBZip2       = "application/x-bzip2"
	MIMEApplicationShell        = "application/x-sh"
	MIMEApplicationDownload     = "application/x-msdownload"
	MIMEApplicationJSON         = "application/json"
	MIMEApplicationJSONUTF8     = "application/json; charset=utf-8"
	MIMEApplicationXML          = "application/xml"
	MIMEApplicationXMLUTF8      = "application/xml; charset=utf-8"
	MIMEApplicationZip          = "application/zip"
	MIMEApplicationPdf          = "application/pdf"
	MIMEApplicationWord         = "application/msword"
	MIMEApplicationExcel        = "application/vnd.ms-excel"
	MIMEApplicationPPT          = "application/vnd.ms-powerpoint"
	MIMEApplicationOpenXMLWord  = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
	MIMEApplicationOpenXMLExcel = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
	MIMEApplicationOpenXMLPPT   = "application/vnd.openxmlformats-officedocument.presentationml.presentation"
	MIMEApplicationWASM         = "application/wasm"
	// MIME image
	MIMEImageJPEG         = "image/jpeg"
	MIMEImagePNG          = "image/png"
	MIMEImageGIF          = "image/gif"
	MIMEImageBitmap       = "image/bmp"
	MIMEImageWebP         = "image/webp"
	MIMEImageIco          = "image/x-icon"
	MIMEImageMicrosoftICO = "image/vnd.microsoft.icon"
	MIMEImageTIFF         = "image/tiff"
	MIMEImageSVG          = "image/svg+xml"
	MIMEImagePhotoshop    = "image/vnd.adobe.photoshop"
	MIMEImageAPNG         = "image/apng"
	// MIME audio
	MIMEAudioBasic     = "audio/basic"
	MIMEAudioL24       = "audio/L24"
	MIMEAudioMP3       = "audio/mpeg"
	MIMEAudioMP4       = "audio/mp4"
	MIMEAudioMPEG      = "audio/mpeg"
	MIMEAudioOggVorbis = "audio/ogg"
	MIMEAudioWAVE      = "audio/wav"
	MIMEAudioWebM      = "audio/webm"
	MIMEAudioAAC       = "audio/aac"
	MIMEAudioAIFF      = "audio/aiff"
	MIMEAudioMIDI      = "audio/midi"
	MIMEAudioM3U       = "application/x-mpegurl"
	MIMEAudioRealAudio = "audio/x-pn-realaudio"
	// MIME video
	MIMEVideoMPEG          = "video/mpeg"
	MIMEVideoOgg           = "video/ogg"
	MIMEVideoMP4           = "video/mp4"
	MIMEVideoQuickTime     = "video/quicktime"
	MIMEVideoWinMediaVideo = "video/x-ms-wmv"
	MIMEVideoWebM          = "video/webm"
	MIMEVideoFLV           = "video/x-flv"
	MIMEVideo3GPP          = "video/3gpp"
	MIMEVideoAVI           = "video/x-msvideo"
	MIMEVideoMatroska      = "video/x-matroska"
	MIMEVideoHLS           = "application/vnd.apple.mpegurl"
)

HTTP 常用 MIME 类型

View Source
const (
	// 通用头
	HeaderCacheControl     = "Cache-Control"
	HeaderConnection       = "Connection"
	HeaderDate             = "Date"
	HeaderPragma           = "Pragma"
	HeaderTrailer          = "Trailer"
	HeaderTransferEncoding = "Transfer-Encoding"
	HeaderUpgrade          = "Upgrade"
	HeaderVia              = "Via"
	HeaderTE               = "TE"
	// 请求头
	HeaderAccept             = "Accept"
	HeaderAcceptCharset      = "Accept-Charset"
	HeaderAcceptEncoding     = "Accept-Encoding"
	HeaderAcceptLanguage     = "Accept-Language"
	HeaderAuthorization      = "Authorization"
	HeaderCookie             = "Cookie"
	HeaderExpect             = "Expect"
	HeaderFrom               = "From"
	HeaderHost               = "Host"
	HeaderIfMatch            = "If-Match"
	HeaderIfModifiedSince    = "If-Modified-Since"
	HeaderIfNoneMatch        = "If-None-Match"
	HeaderIfRange            = "If-Range"
	HeaderIfUnmodifiedSince  = "If-Unmodified-Since"
	HeaderMaxForwards        = "Max-Forwards"
	HeaderProxyAuthorization = "Proxy-Authorization"
	HeaderRange              = "Range"
	HeaderReferer            = "Referer"
	HeaderReferrerPolicy     = "Referrer-Policy"
	HeaderUserAgent          = "User-Agent"
	// 响应头
	HeaderAcceptRanges      = "Accept-Ranges"
	HeaderAge               = "Age"
	HeaderAllow             = "Allow"
	HeaderContentEncoding   = "Content-Encoding"
	HeaderContentLanguage   = "Content-Language"
	HeaderContentLength     = "Content-Length"
	HeaderContentLocation   = "Content-Location"
	HeaderContentRange      = "Content-Range"
	HeaderContentType       = "Content-Type"
	HeaderETag              = "ETag"
	HeaderExpires           = "Expires"
	HeaderLastModified      = "Last-Modified"
	HeaderLocation          = "Location"
	HeaderProxyAuthenticate = "Proxy-Authenticate"
	HeaderRetryAfter        = "Retry-After"
	HeaderServer            = "Server"
	HeaderSetCookie         = "Set-Cookie"
	HeaderWWWAuthenticate   = "WWW-Authenticate"
	HeaderVary              = "Vary"
	// 安全头 (新增现代Web安全头)
	HeaderContentSecurityPolicy   = "Content-Security-Policy"
	HeaderXFrameOptions           = "X-Frame-Options"
	HeaderXXSSProtection          = "X-XSS-Protection"
	HeaderXContentTypeOptions     = "X-Content-Type-Options"
	HeaderStrictTransportSecurity = "Strict-Transport-Security"
)

HTTP 头信息

View Source
const (
	// Protocol
	HTTP11 = "HTTP/1.1"
	HTTP10 = "HTTP/1.0"
	HTTP20 = "HTTP/2.0"
)

HTTP 协议版本

Variables

View Source
var DefaultMarshal func(any) ([]byte, error) = json.Marshal

DefaultMarshal 缺省JSON编码器

View Source
var DefaultUnmarshal func([]byte, any) error = json.Unmarshal

DefaultUnmarshal 缺省JSON解码器

View Source
var HTTPContextPool = sync.Pool{
	New: func() any {
		return &HTTPContext{}
	},
}
View Source
var IPAdmissioneEmpty struct{}

Functions

func BasicAuthMiddleware

func BasicAuthMiddleware(valid func(c *HTTPContext, username, password string) bool) func(*HTTPContext)

func ClientIP

func ClientIP(r *http.Request) string

ClientIP 尽最大努力实现获取客户端 IP 的算法。 解析 X-Real-IP 和 X-Forwarded-For 以便于反向代理(nginx 或 haproxy)可以正常工作。

func ClientPublicIP

func ClientPublicIP(r *http.Request) string

ClientPublicIP 尽最大努力实现获取客户端公网 IP 的算法。 解析 X-Real-IP 和 X-Forwarded-For 以便于反向代理(nginx 或 haproxy)可以正常工作。

func HasLocalIPAddr

func HasLocalIPAddr(ip net.IP) bool

HasLocalIPAddr 检测 IP 地址是否是内网地址 通过直接对比ip段范围效率更高,详见:https://github.com/thinkeridea/go-extend/issues/2

func HeaderMiddleware

func HeaderMiddleware(h map[string]string) func(*HTTPContext)

func LoggerMiddleware

func LoggerMiddleware() func(*HTTPContext)

LoggerMiddleware 日志

func RemoteIP

func RemoteIP(r *http.Request) string

RemoteIP 通过 RemoteAddr 获取 IP 地址。

Types

type H

type H map[string]any

H map[string]any 缩写

type HTTPContext

type HTTPContext struct {
	Writer  http.ResponseWriter
	Request *http.Request
	Flush   func() (int, error)
	// contains filtered or unexported fields
}

HTTPContext 上下文

func (*HTTPContext) BindJSON

func (c *HTTPContext) BindJSON(v any) error

BindJSON 绑定JSON数据

func (*HTTPContext) Blob

func (c *HTTPContext) Blob(status int, contentType string, data []byte)

Blob

func (*HTTPContext) Debug

func (c *HTTPContext) Debug(msg string, args ...any)

func (*HTTPContext) Del

func (c *HTTPContext) Del(k string)

Del 上下文key-value值

func (*HTTPContext) Error

func (c *HTTPContext) Error(msg string, args ...any)

func (*HTTPContext) File

func (c *HTTPContext) File(filepath string)

File 将静态文件返回给客户端

func (*HTTPContext) Get

func (c *HTTPContext) Get(k string) (v any, b bool)

Get 上下文key-value值

func (*HTTPContext) Info

func (c *HTTPContext) Info(msg string, args ...any)

func (*HTTPContext) JSON

func (c *HTTPContext) JSON(status int, v any)

JSON 带有状态码的JSON 数据

func (*HTTPContext) Next

func (c *HTTPContext) Next()

Next 下一个

func (*HTTPContext) Render

func (c *HTTPContext) Render(status int, name string, v any)

Render 渲染模板

func (*HTTPContext) Set

func (c *HTTPContext) Set(k string, v any)

Set 上下文key-value值

func (*HTTPContext) String

func (c *HTTPContext) String(status int, msg string)

String 带有状态码的纯文本响应

func (*HTTPContext) Warn

func (c *HTTPContext) Warn(msg string, args ...any)

type IPAdmission

type IPAdmission struct {
	sync.Map
}

IPAdmission IP准入

func NewIPAdmission

func NewIPAdmission() *IPAdmission

func (*IPAdmission) BlacklistMiddleware

func (f *IPAdmission) BlacklistMiddleware() func(*HTTPContext)

BlacklistMiddleware 黑名单。

func (*IPAdmission) Check

func (f *IPAdmission) Check(line string) bool

Check 检查某个ip在不在设置的规则里

func (*IPAdmission) ParseNode

func (f *IPAdmission) ParseNode(line string) error

ParseNode 添加规则

func (*IPAdmission) RemoveNode

func (f *IPAdmission) RemoveNode(line string) error

RemoveNode 移除规则

func (*IPAdmission) WhitelistMiddleware

func (f *IPAdmission) WhitelistMiddleware() func(*HTTPContext)

WhitelistMiddleware 白名单。

type JWT

type JWT struct {
	TokenSigningKey []byte
	TokenExpires    time.Duration
}

JWT

func (JWT) CreateToken

func (j JWT) CreateToken(claims map[string]any) (string, error)

CreateToken 生成

func (JWT) JWTMiddleware

func (j JWT) JWTMiddleware(requiredClaims ...string) func(*HTTPContext)

func (JWT) RefreshToken

func (j JWT) RefreshToken(c *HTTPContext) error

RefreshToken 刷新令牌

func (JWT) TokenParse

func (j JWT) TokenParse(tokenString string) (jwt.MapClaims, error)

TokenParse 令牌解析

type Renderer

type Renderer interface {
	ExecuteTemplate(io.Writer, string, any) error
}

Renderer 模板渲染接口

type WRoute

type WRoute struct {
	Mux *http.ServeMux

	//HTTPContext String、JSON、Render IO Write时错误的处理函数
	HookIOWriteError func(*HTTPContext, int, error)
	// contains filtered or unexported fields
}

WRoute 路由

func NewRoute

func NewRoute(l *slog.Logger) *WRoute

NewRoute 新建

func (*WRoute) DELETE

func (r *WRoute) DELETE(pattern string, fn ...func(*HTTPContext))

DELETE 注册DELETE方法

func (*WRoute) GET

func (r *WRoute) GET(pattern string, fn ...func(*HTTPContext))

GET 注册GET方法

func (*WRoute) HEAD

func (r *WRoute) HEAD(pattern string, fn ...func(*HTTPContext))

HEAD 注册HEAD方法

func (*WRoute) POST

func (r *WRoute) POST(pattern string, fn ...func(*HTTPContext))

POST 注册POST方法

func (*WRoute) PUT

func (r *WRoute) PUT(pattern string, fn ...func(*HTTPContext))

PUT 注册PUT方法

func (*WRoute) SetDebugMode

func (r *WRoute) SetDebugMode(b bool)

func (*WRoute) SetRenderer

func (r *WRoute) SetRenderer(s Renderer)

func (*WRoute) Static

func (r *WRoute) Static(relativePath, file string, group ...func(*HTTPContext))

Static 将指定目录下的静态文件映射到URL路径中

func (*WRoute) StaticFS

func (r *WRoute) StaticFS(dir string, group ...func(*HTTPContext))

StaticFS 静态文件目录服务

func (*WRoute) Use

func (r *WRoute) Use(g ...func(*HTTPContext))

Use 全局中间件 需放在最前面

Jump to

Keyboard shortcuts

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