xhttp

package
v0.0.0-...-b147793 Latest Latest
Warning

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

Go to latest
Published: Jan 7, 2025 License: BSD-3-Clause Imports: 31 Imported by: 1

Documentation

Overview

Package xhttp HTTP 协议

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Bind

func Bind(r *http.Request, obj any) error

func ClientIP

func ClientIP(r *http.Request) string

func Error

func Error(w http.ResponseWriter, r *http.Request, code int, title string, error string)

func HeaderDiffMore

func HeaderDiffMore(old, new http.Header) http.Header

HeaderDiffMore 查找到 new 相比 old 增量的部分,总是返回一个全新的 Header

func IsAjax

func IsAjax(r *http.Request) bool

func NotFound

func NotFound(w http.ResponseWriter, r *http.Request)

func NotFoundHandler

func NotFoundHandler() http.Handler

func PathJoin

func PathJoin(arr ...string) string

func RegisterGroup

func RegisterGroup(r *Router, prefix string, h GroupHandler, mds ...MiddlewareFunc)

RegisterGroup 注册一组业务,安装规则将 GroupHandler 中的所有的 http.HandlerFunc 注册到路由中去。

注册规则如下:

 1. {HTTPMethod} 指的是 Get、Post、Delete 等 ,不区分大小写,所以 GET、POST、DELETE 也一样。
 2. 所有和 {HTTPMethod} 或者 {HTTPMethod}{Xyz} 或者 {HTTPMethod}{Xyz}{Abc} 等驼峰命名的,
 注册的路由只支持此种 HTTP 请求,如 Delete 方法只支持 HTTP DELETE 请求。
 3. 方法名中包含 Save 的,注册为 POST 请求。

假设 RegisterGroup(r,"/user/",&userHandler{}),userHandler{} 中所有实现了 func(http.ResponseWriter, *http.Request) 这个函数签名的注册结果如下:

user.Index        --> GET      /user/ 和 /user/Index
user.Delete       --> DELETE   /user/
user.Post         --> POST     /user/
user.GetByID      --> GET      /user/GetByID
user.DeleteByID   --> DELETE   /user/DeleteByID
user.UpdateStatus --> PUT      /user/UpdateStatus
user.Search       --> GET      /user/Search
user.Add          --> GET      /user/Add
user.Edit         --> GET      /user/Edit
user.Save         --> POST     /user/Save

func RegisterRegexpAlias

func RegisterRegexpAlias(name string, reg string)

RegisterRegexpAlias 注册路由正则别买 默认已集成 UUID、UINT

func SetNotFoundHandler

func SetNotFoundHandler(h http.Handler)

func WriteHTML

func WriteHTML(w http.ResponseWriter, html []byte)

WriteHTML 输出 HTML 格式的数据,状态码为 200

func WriteHTMLStatus

func WriteHTMLStatus(w http.ResponseWriter, status int, html []byte)

WriteHTMLStatus 输出 HTML 格式的数据,需要指定状态码

func WriteHeader

func WriteHeader(w http.ResponseWriter, header http.Header)

func WriteJSON

func WriteJSON(w http.ResponseWriter, data any)

WriteJSON 输出 JSON 格式的数据,状态码为 200

func WriteJSONP

func WriteJSONP(w http.ResponseWriter, cb string, data any)

func WriteJSONPStatus

func WriteJSONPStatus(w http.ResponseWriter, status int, cb string, data any)

func WriteJSONStatus

func WriteJSONStatus(w http.ResponseWriter, status int, data any)

WriteJSONStatus 输出 JSON 格式的数据,需要指定状态码

func WriteText

func WriteText(w http.ResponseWriter, text []byte)

WriteText 输出 TEXT 格式的数据,状态码为 200

func WriteTextStatus

func WriteTextStatus(w http.ResponseWriter, status int, text []byte)

WriteTextStatus 输出 TEXT 格式的数据,需要指定状态码

Types

type FS

type FS struct {
	// FS 必填,可以是 embed.FS
	FS fs.FS

	// RootDir 可选,FS 里此目录作为基准目录
	RootDir string

	// NotFound 可选,当文件不存在时的回调
	NotFount http.Handler
	// contains filtered or unexported fields
}

FS 将 fs.FS 文件封装为 http.Handler,以使其内部文件可被访问到 相比 http.FS 而言,可指定 fs 内部的基准目录,并添加了 etag 支持

func (*FS) Exists

func (e *FS) Exists(fp string) bool

Exists 判断文件是否存在,fp 应该时经过了 path.Clean 的,并且不以 / 开头

func (*FS) Open

func (e *FS) Open(name string) (fs.File, error)

func (*FS) ServeHTTP

func (e *FS) ServeHTTP(w http.ResponseWriter, r *http.Request)

type FSHandler

type FSHandler interface {
	http.Handler
	Exists(fp string) bool
	Open(name string) (fs.File, error)
}

func ToFSHandler

func ToFSHandler(h http.Handler) FSHandler

type FSHandlers

type FSHandlers []FSHandler

func (FSHandlers) Exists

func (fs FSHandlers) Exists(fp string) bool

func (FSHandlers) Open

func (fs FSHandlers) Open(name string) (fs.File, error)

func (FSHandlers) ServeHTTP

func (fs FSHandlers) ServeHTTP(w http.ResponseWriter, r *http.Request)

type FSMerge

type FSMerge struct {
	Minify map[string]func(b []byte) ([]byte, error)
	FS     FSHandler
	// contains filtered or unexported fields
}

FSMerge 合并多个 js 文件到一个

func (*FSMerge) MergeJS

func (fm *FSMerge) MergeJS(names ...string) (string, error)

MergeJS 合并多个 js 文件,并返回新的合并后的文件名。

func (*FSMerge) ServeHTTP

func (fm *FSMerge) ServeHTTP(w http.ResponseWriter, req *http.Request)

type GroupHandler

type GroupHandler interface {
	GroupHandler() map[string]PatternHandler
}

type MiddlewareFunc

type MiddlewareFunc func(http.Handler) http.Handler

MiddlewareFunc HTTP Router(路由) 的 中间件函数类型定义,可用于给 Router 增加切面。 如添加额外的日志、可用性统计等独立的功能

type PatternHandler

type PatternHandler struct {
	Pattern    string
	Func       http.HandlerFunc
	Middleware []MiddlewareFunc
}

type RouteInfo

type RouteInfo struct {
	Method string // 注册的请求方法,如 GET、ANY

	// Pattern 注册的路由地址,如 /user, /user/{id}, /user/*, /user/{category}/{id:[0-9]+}
	Pattern string

	// Path 归一化后的 pattern 地址,,去掉变量的正则只保留变量名,
	// 如 /user, /user/{id}, /user/*, /user/{category}/{id}
	Path string

	// MetaID 注册在 路由 pattern 中的 meta 的 id 值
	MetaID string

	// MetaOther
	MetaOther map[string]string
}

func ReadRouteInfo

func ReadRouteInfo(ctx context.Context) RouteInfo

ReadRouteInfo 从 http.Request.Context() 信息里读取路由信息

func (*RouteInfo) String

func (i *RouteInfo) String() string

type Router

type Router struct {
	xlog.WithLogger
	// contains filtered or unexported fields
}
Router 支持静态地址和通配符、支持中间件的 HTTP Router

Pattern 格式:

在使用 Handle、HandleFunc 注册路由时,路由的 Pattern 支持格式 :(Method\s+)?(Path)(\s+meta|Meta)? 。
在使用 Get、GetFUnc 等方法中带有 Method 的时候,Pattern 支持格式: (Path)(\s+meta|Meta)? 。

Method, Handler 支持的请求方法:

Pattern 中的 Method 可以配置 [0-N] 个,当 Method 为空时,此 handler 可以处理所有的请求类型(路由信息会读取到 Method = "ANY" )。 当为多个时,使用英文逗号连接。注册时的填写的 Method 不区分大小写,传入后会统一转换为大写(如 get -> GET)。 如 Handle("/index"),Handle("get /index"),Handle("get,post /index") 。

Path, 路由地址,支持静态地址和通配符

下文中 Router 的 Handle、Get 等 API 文档中所述的 Path就是此。

  1. 静态路由地址: /user

  2. 单词通配:一个变量匹配一个目录,可以有前缀和后缀

    /user/{name}/{age}, /user/{id}/detail, /user/{id}.html, /user/hello-{id}.html

  3. 正则表达式:

    /user/{category}/{id:[0-9]+}, /user/{id:[0-9]+}.html, /user/hello-{id:[0-9]+}-{age:[0-9]+}.html

    正则表达式别名: /{id:UUID} 、/{id:UINT} UUID 可匹配 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 这个格式的 UUID UINT 可匹配正整数 Base62 匹配 [0-9a-zA-Z]+ Base36 匹配 [0-9a-z]+ Base64URL 匹配 [0-9a-zA-Z\-_]+ 除此之外,还可以使用 RegisterRegexpAlias 注册自定义的别名

  4. *通配符(简化正则)(* 可以匹配包含 / 的所有字符) /user/*, /user/*/detail, /user/*/detail/*, /user/*/detail/*.html /user/{s1:*}, /user/{s1:*}/detail, /user/{s1:*}/detail/{s2:*}

路由变量读取:

在路由地址中的 {name},* 和 {id:[0-9]+} 均为路由变量,是可以使用 http.Request.PathValue("name") 读取对应的值的。
对于 {name} 、 {id:[0-9]+}、{age:*} 这种,分别使用 PathValue("name") 和 PathValue("id")、PathValue("age") 就能读取到。
对于使用了 /user/*/detail/* 这种方式,分别使用 PathValue("p0")、PathValue("p1"),即变量名 = p + 变量序号( 从 0 开始 )

Meta 路由元信息:

在 Handler 中或者中间件中使用 ReadRouteInfo(http.Request.Context()) 可以读取此 Handler 注册的路由信息。
如用于监控、鉴权等场景时,可以读取 RouteInfo 信息。
在 Pattern 中,除了 Path 等其他元信息可以通过在 Pattern 中添加 (\s+meta|Meta) 段落内容添加。
如 Handle("get /index meta|id=1,type=user")。id 字段时固定的字段,还可以添加其他任意 key 。

func NewRouter

func NewRouter() *Router

func (*Router) Delete

func (r *Router) Delete(pattern string, handler http.Handler, mds ...MiddlewareFunc) RouteInfo

Delete 注册 DELETE 请求路由,pattern 应是一个 (Path)(\s+meta|Meta) 格式的字符串

func (*Router) DeleteFunc

func (r *Router) DeleteFunc(pattern string, handler http.HandlerFunc, mds ...MiddlewareFunc) RouteInfo

DeleteFunc 注册 DELETE 请求路由,pattern 应是一个 (Path)(\s+meta|Meta) 格式的字符串

func (*Router) Get

func (r *Router) Get(pattern string, handler http.Handler, mds ...MiddlewareFunc) RouteInfo

Get 注册 GET 请求路由,pattern 应是一个 (Path)(\s+meta|Meta) 格式的字符串

func (*Router) GetFunc

func (r *Router) GetFunc(pattern string, handler http.HandlerFunc, mds ...MiddlewareFunc) RouteInfo

GetFunc 注册 GET 请求路由,pattern 应是一个 (Path)(\s+meta|Meta) 格式的字符串

func (*Router) Handle

func (r *Router) Handle(pattern string, handler http.Handler, mds ...MiddlewareFunc)

Handle 注册路由

pattern: 支持格式 (Method\s+)?(Path)(\s+meta|Meta)

Method: 请求方法,可选,支持一个活多个,如 “GET”,“GET,POST”
若 Method 为空则不限定请求方法

Path: 请求地址,支持静态地址和通配符

Meta:路由的其他元信息
如 meta|id=123 或者 meta|id=123,type=user

func (*Router) HandleFunc

func (r *Router) HandleFunc(pattern string, handler http.HandlerFunc, mds ...MiddlewareFunc)

HandleFunc 注册路由, pattern 支持格式 (Method\s+)?(Path)(\s+meta|Meta)

func (*Router) Head

func (r *Router) Head(pattern string, handler http.Handler, mds ...MiddlewareFunc) RouteInfo

Head 注册 HEAD 请求路由,pattern 支持格式 (Method\s+)?(Path)(\s+meta|Meta)

func (*Router) HeadFunc

func (r *Router) HeadFunc(pattern string, handler http.HandlerFunc, mds ...MiddlewareFunc) RouteInfo

HeadFunc 注册 HEAD 请求路由,pattern 支持格式 (Method\s+)?(Path)(\s+meta|Meta)

func (*Router) NotFound

func (r *Router) NotFound(handler http.Handler)

func (*Router) NotFoundFunc

func (r *Router) NotFoundFunc(handler http.HandlerFunc)

func (*Router) Options

func (r *Router) Options(pattern string, handler http.Handler, mds ...MiddlewareFunc) RouteInfo

Options 注册 OPTIONS 请求路由,pattern 应是一个 (Path)(\s+meta|Meta) 格式的字符串

func (*Router) OptionsFunc

func (r *Router) OptionsFunc(pattern string, handler http.HandlerFunc, mds ...MiddlewareFunc) RouteInfo

OptionsFunc 注册 OPTIONS 请求路由,pattern 应是一个 (Path)(\s+meta|Meta) 格式的字符串

func (*Router) Post

func (r *Router) Post(pattern string, handler http.Handler, mds ...MiddlewareFunc) RouteInfo

Post 注册 POST 请求路由,pattern 应是一个 (Path)(\s+meta|Meta) 格式的字符串

func (*Router) PostFunc

func (r *Router) PostFunc(pattern string, handler http.HandlerFunc, mds ...MiddlewareFunc) RouteInfo

PostFunc 注册 POST 请求路由,pattern 应是一个 (Path)(\s+meta|Meta) 格式的字符串

func (*Router) Prefix

func (r *Router) Prefix(prefix string, mds ...MiddlewareFunc) *Router

Prefix 给地址前缀 prefix 生成一个独立的分组, prefix 只能是静态地址,不能包含变量参数,如 /user/

Example
package main

import (
	"net/http"

	"github.com/xanygo/anygo/xhttp"
)

func main() {
	r := xhttp.NewRouter()
	r.GetFunc("/", func(w http.ResponseWriter, r *http.Request) {
		_, _ = w.Write([]byte("index"))
	})

	g1 := r.Prefix("/user/")

	// 完整地址: /user/{id}/detail,  可接收如 GET /user/123/detail
	g1.GetFunc("/{id}/detail", func(w http.ResponseWriter, r *http.Request) {
		_, _ = w.Write([]byte("user detail"))
	})

	// 完整地址:/user/{id}, 可接收如 DELETE /user/123
	g1.DeleteFunc("/{id}", func(w http.ResponseWriter, r *http.Request) {
		_, _ = w.Write([]byte("delete user"))
	})
}
Output:

func (*Router) Put

func (r *Router) Put(pattern string, handler http.Handler, mds ...MiddlewareFunc) RouteInfo

Put 注册 PUT 请求路由,pattern 应是一个 (Path)(\s+meta|Meta) 格式的字符串

func (*Router) PutFunc

func (r *Router) PutFunc(pattern string, handler http.HandlerFunc, mds ...MiddlewareFunc) RouteInfo

PutFunc 注册 PUT 请求路由,pattern 应是一个 (Path)(\s+meta|Meta) 格式的字符串

func (*Router) ServeHTTP

func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)

func (*Router) Trace

func (r *Router) Trace(pattern string, handler http.Handler, mds ...MiddlewareFunc) RouteInfo

Trace 注册 TRACE 请求路由,pattern 应是一个 (Path)(\s+meta|Meta) 格式的字符串

func (*Router) TraceFunc

func (r *Router) TraceFunc(pattern string, handler http.HandlerFunc, mds ...MiddlewareFunc) RouteInfo

TraceFunc 注册 TRACE 请求路由,pattern 应是一个 (Path)(\s+meta|Meta) 格式的字符串

func (*Router) Use

func (r *Router) Use(mds ...MiddlewareFunc)

Use 给路由注册新的中间件, 在使用 Handle、HandleFunc、Get、GetFunc 等注册 Handler 时,会读取已注册到 Router 的中间件列表,用于对 Handler 添加切面。 在完成注册 Handler 之后,使用 Use 方法注册的中间件不会影响 已注册的 Handler。

Example
package main

import (
	"fmt"
	"net/http"

	"github.com/xanygo/anygo/xhttp"
)

func main() {
	r := xhttp.NewRouter()
	r.Use(func(handler http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			fmt.Println("call before")

			handler.ServeHTTP(w, r)

			fmt.Println("call after")
		})
	})
}
Output:

type StatusWriter

type StatusWriter struct {
	W http.ResponseWriter
	// contains filtered or unexported fields
}

func (*StatusWriter) Header

func (w *StatusWriter) Header() http.Header

func (*StatusWriter) StatusCode

func (w *StatusWriter) StatusCode() int

func (*StatusWriter) Unwrap

func (w *StatusWriter) Unwrap() http.ResponseWriter

func (*StatusWriter) Write

func (w *StatusWriter) Write(bytes []byte) (int, error)

func (*StatusWriter) WriteHeader

func (w *StatusWriter) WriteHeader(statusCode int)

func (*StatusWriter) Wrote

func (w *StatusWriter) Wrote() int

type ZipFile

type ZipFile struct {
	// Reader 压缩文件的 reader, Reader 和 Content 二者至少有一个,并优先使用 Reader
	Reader *zip.Reader

	// Content zip 压缩的内容,可选
	Content []byte

	// RootDir 可选,FS 里此目录作为基准目录
	RootDir string

	// NotFound 可选,当文件不存在时的回调
	NotFound http.Handler
	// contains filtered or unexported fields
}

ZipFile 将 zip 文件封装为 http.Handler,以使其内部文件可被访问到,并添加了 etag 支持

func (*ZipFile) Exists

func (z *ZipFile) Exists(fp string) bool

Exists 判断文件是否存在,fp 应该时经过了 path.Clean 的,并且不以 / 开头

func (*ZipFile) Init

func (z *ZipFile) Init() error

func (*ZipFile) Open

func (z *ZipFile) Open(name string) (fs.File, error)

func (*ZipFile) ServeHTTP

func (z *ZipFile) ServeHTTP(w http.ResponseWriter, req *http.Request)

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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