pi

package module
v0.0.0-...-2fa1399 Latest Latest
Warning

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

Go to latest
Published: Aug 2, 2023 License: Apache-2.0 Imports: 15 Imported by: 0

README

Pi

build.yaml Go Reference

English

“Pi”是一个简洁轻量高性能的路由组件,通过使用泛型来减少后端接口开发中的模版代码。

代码示例

type UserData struct {
    Name string
    Password string
}

func h(ctx pi.Context) error {
    data := &UserData{}
    err := pi.Format(ctx, data)
    if err != nil {
        return pi.NewError(400, err.Error())
    }

    // do sth. actions...

    return ctx.Text("hello, world!")
}

sm := pi.NewServerMux(context.Background())
sm.Route("/api/v1/users").Post(h)

http.ListenAndServe("localhost:8080", sm)

安装

go get -u github.com/go-laeo/pi

特点

  • 基于前缀树的高性能路由功能,支持路由参数提取、通配路由等功能
  • 兼容 net/http (pi.HandlerFunc 实现了 http.Handler)
  • Auto使用泛型函数 pi.Format[T any]() 来主动解析请求体
  • 路由中间件由 pi.(ServerMux).Use()pi.(HandlerFunc).Connect() 进行注入
  • 内置针对 SPA 应用优化的 pi.FileServer
  • 无外部库依赖,无供应链攻击风险
  • 完备的单元测试与性能测试

更多示例

查看 _examples 目录。

开源协议

Apache 2.0 License

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrHandlerNotFound = errors.New("handler not found")
)
View Source
var (
	ErrInvalidP = errors.New("p must be *T")
)

Functions

func Bind

func Bind[T any](v url.Values, p *T) error

Bind populate values from v and fills to p.

type Paging struct{
	Index int `query:"i"`
	Size int `query:"s"`
}

p := Paging{}
err := pi.Bind(ctx.URL().Query(), &p)

The above code shows us how we can mapping queries to a struct by simply call `pi.Bind()`.

func Format

func Format[T any](ctx Context, p *T) error

Format decodes request body as JSON object to *T.

func FormatValidator

func FormatValidator[T any](ctx Context, p *T) error

FormatValidator runs Format() on *P, then tries call (Validator).Validate() on it.

func OverrideNotFound

func OverrideNotFound(root http.FileSystem, defaults string) http.FileSystem

OverrideNotFound open file from root, if the file does not exists, then try open defaults.

func Sub

func Sub(root http.FileSystem, dir string) http.FileSystem

Sub returns an new http.FileSystem that reads file from the sub directory of root.

Types

type Context

type Context interface {
	Context() context.Context
	SetContext(ctx context.Context)

	Raw() (w http.ResponseWriter, r *http.Request)
	Query(field string, defaults ...string) string
	Form(field string, defaults ...string) string

	// File returns first uploaded file by field.
	File(field string) (multipart.File, *multipart.FileHeader, error)

	// FileSet gets all uploaded files by field from underlying request,
	FileSet(field string) []*multipart.FileHeader

	// Cookie returns the named cookie provided in the request or
	// ErrNoCookie if not found.
	// If multiple cookies match the given name, only one cookie will
	// be returned.
	Cookie(name string) (*http.Cookie, error)

	// Get gets the first value associated with the given key from request header. If
	// there are no values associated with the key, Get returns "".
	// It is case insensitive; textproto.CanonicalMIMEHeaderKey is
	// used to canonicalize the provided key. Get assumes that all
	// keys are stored in canonical form. To use non-canonical keys,
	// access the map directly.
	Get(name string) string

	// Domain gets domain name of from request's Host field, eg. www.google.com.
	Domain() string

	URL() *url.URL

	// Param gets named route param by name, returns empty string if it does not exists.
	Param(name string) string

	// ParamValues returns all path params.
	ParamValues() url.Values

	// IP gets first client IP.
	IP() string

	// IPSet gets all client IPs if available.
	IPSet() []string

	Method() string
	Is(method string) bool

	// Header returns the header map that will be sent by
	// WriteHeader. The Header map also is the mechanism with which
	// Handlers can set HTTP trailers.
	//
	// Changing the header map after a call to WriteHeader (or
	// Write) has no effect unless the HTTP status code was of the
	// 1xx class or the modified headers are trailers.
	//
	// There are two ways to set Trailers. The preferred way is to
	// predeclare in the headers which trailers you will later
	// send by setting the "Trailer" header to the names of the
	// trailer keys which will come later. In this case, those
	// keys of the Header map are treated as if they were
	// trailers. See the example. The second way, for trailer
	// keys not known to the Handler until after the first Write,
	// is to prefix the Header map keys with the TrailerPrefix
	// constant value. See TrailerPrefix.
	//
	// To suppress automatic response headers (such as "Date"), set
	// their value to nil.
	Header() http.Header

	// Write writes the data to the connection as part of an HTTP reply.
	//
	// If WriteHeader has not yet been called, Write calls
	// WriteHeader(http.StatusOK) before writing the data. If the Header
	// does not contain a Content-Type line, Write adds a Content-Type set
	// to the result of passing the initial 512 bytes of written data to
	// DetectContentType. Additionally, if the total size of all written
	// data is under a few KB and there are no Flush calls, the
	// Content-Length header is added automatically.
	//
	// Depending on the HTTP protocol version and the client, calling
	// Write or WriteHeader may prevent future reads on the
	// Request.Body. For HTTP/1.x requests, handlers should read any
	// needed request body data before writing the response. Once the
	// headers have been flushed (due to either an explicit Flusher.Flush
	// call or writing enough data to trigger a flush), the request body
	// may be unavailable. For HTTP/2 requests, the Go HTTP server permits
	// handlers to continue to read the request body while concurrently
	// writing the response. However, such behavior may not be supported
	// by all HTTP/2 clients. Handlers should read before writing if
	// possible to maximize compatibility.
	Write([]byte) (int, error)

	// Code only responds to client with HTTP status code.
	Code(code int) error

	// Json encode v into JSON string then writes to client.
	Json(v any) error

	// Text writes v to client as plain text.
	Text(v string) error
	Redirect(to string, code ...int) error
	SetCookie(c *http.Cookie)

	Error(status int, result *ErrorResult) error
}

type ErrorResult

type ErrorResult struct {
	Error        string `json:"error"`
	ErrorMessage string `json:"error_message"`
}

type HandlerFunc

type HandlerFunc func(ctx Context) error

func FileServer

func FileServer(root http.FileSystem, defaultsFile string) HandlerFunc

FileServer returns a HTTP handler for serving files from within root. If the requested files are not exist, then send defaultsFile to client.

func (HandlerFunc) Connect

func (h HandlerFunc) Connect(cc ...func(next HandlerFunc) HandlerFunc) HandlerFunc

type LengthResult

type LengthResult[T any] struct {
	Data     []T `json:"data"`
	Page     int `json:"page"`
	PageSize int `json:"page_size"`
	Total    int `json:"total"`
}

type Result

type Result[T any] struct {
	Data T `json:"data"`
}

type Route

type Route interface {
	Search(route string, captured url.Values) Route
	Invoke(ctx Context) error

	Get(h HandlerFunc) Route
	Post(h HandlerFunc) Route
	Put(h HandlerFunc) Route
	Delete(h HandlerFunc) Route
	Patch(h HandlerFunc) Route
	Options(h HandlerFunc) Route
	Head(h HandlerFunc) Route
	Any(h HandlerFunc) Route
}

type ServerMux

type ServerMux interface {
	http.Handler

	Route(path string) Route
	Group(prefix string, fn func(sm ServerMux))
	SetNotFoundHandler(h HandlerFunc)
	SetErrorFormatter(fn func(ctx Context, err error))
	Use(c func(next HandlerFunc) HandlerFunc)
}

func NewServerMux

func NewServerMux() ServerMux

type Validator

type Validator interface {
	Validate(ctx context.Context) error
}

Directories

Path Synopsis
_examples

Jump to

Keyboard shortcuts

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