webapi

package module
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Aug 6, 2022 License: MIT Imports: 14 Imported by: 1

README

webapi

GoDoc Go codecov License

这是SlimWebApi的 Go 版。 SlimAPI 通信协议详见godoc-SlimAPI通信协议

快速使用

安装:

go get -u github.com/cmstar/go-webapi@latest

上代码:

package main

import (
	"fmt"
	"net/http"
	"time"

	"github.com/cmstar/go-errx"
	"github.com/cmstar/go-logx"
	"github.com/cmstar/go-webapi"
	"github.com/cmstar/go-webapi/slimapi"
)

func main() {
	// 初始化 API 容器。
	slim := slimapi.NewSlimApiHandler("demo")

	// 注册 WebAPI 方法。
	slim.RegisterMethods(Methods{})

	// 初始化日志。 https://github.com/cmstar/go-logx
	logger := logx.NewStdLogger(nil)
	logFinder := logx.NewSingleLoggerLogFinder(logger)

	// 初始化引擎。
	e := webapi.NewEngine()

	// 注册路由,使用 chi 库的语法。 https://github.com/go-chi/chi
	e.Handle("/api/{~method}", slim, logFinder)

	// 启动。
	err := http.ListenAndServe(":15001", e)
	if err != nil {
		logger.Log(logx.LevelFatal, err.Error())
	}
}

// 用于承载 WebAPI 方法。
type Methods struct{}

// 方法必须是 exported ,即大写字母开头的。
func (Methods) Plus(req struct {
	A int // 参数首字母也必须是大写的。
	B int
}) int {
	return req.A + req.B
}

func (Methods) Time() string {
	return time.Now().Format("2006-01-02 15:04")
}

// 参数也可以是 *webapi.ApiState ,可通过其访问到当前请求的上下文。
// 也可以同时搭配 struct 型的参数。
func (Methods) Headers(state *webapi.ApiState, req struct{ NoMeaning bool }) map[string][]string {
	// RawRequest 是标准库中,当前请求的 *http.Request 。
	return state.RawRequest.Header
}

// 支持至多两个返回值,第一个返回值对应输出的 Data 字段;第二个返回值必须是 error 。详见《错误处理》节。
func (Methods) Err(req struct {
	BizErr bool
	Value  string
}) (string, error) {
	if req.BizErr {
		return req.Value, errx.NewBizError(12345, "your message", nil)
	}
	return "", fmt.Errorf("not a biz-error: %v", req.Value)
}

跑起来,现在可以调用 Methods 上的方法了。方法名称和参数都是大小写不敏感的。

GET http://localhost:15001/api/plus?a=11&b=22

=> {
    "Code": 0,
    "Message": "",
    "Data": 33
}

---
# 以 JSON 格式请求。
POST http://localhost:15001/api/plus
Content-Type: application/json

{"a":11, "b":22}

=> {
    "Code": 0,
    "Message": "",
    "Data": 33
}

---
GET http://localhost:15001/api/time

=> {
    "Code": 0,
    "Message": "",
    "Data": "2022-03-06 23:16"
}

---
GET http://localhost:15001/api/headers

=> {
    "Code": 0,
    "Message": "",
    "Data": {
        "Accept": ["text/html,application/xhtml+xml"],
        "Accept-Encoding": ["gzip, deflate, br"],
        "Connection": ["keep-alive"],
        "User-Agent": ["Mozilla/5.0 ..."],
        ...
    }
}

---
# BizError 会以 Code + Message 的方式体现在输出上。
GET http://localhost:15001/api/err?bizErr=1&value=my-value

=> {
    "Code": 12345,
    "Message": "your message",
    "Data": "my-value"
}

---
# 非 BizError 均表现为 internal error 。
GET http://localhost:15001/api/err?bizErr=false&value=my-value

=> {
    "Code": 500,
    "Message": "internal error",
    "Data": ""
}

错误处理

表示 WebAPI 的方法支持0-2个返回值(详见GoDoc)。

当方法返回:

  • 没有 error 返回值或返回的 errornil:表示调用成功,输出的 Code=0
  • 返回 errx.BizError:输出 Code=BizError.Code(), Message=BizError.Message()
  • 返回不是 errx.BizErrorerror:统一输出 Code=500, Message=internal error
  • 方法 panic:统一输出 Code=500, Message=internal error

BizError 的详细说明,参考go-errx库

Documentation

Overview

webapi 包定义一组抽象过程与辅助类型,用于开发特定协议的 WebAPI 框架,如 SlimAPI 。

Index

Constants

View Source
const (
	// ContentTypeNone 未指定类型。
	ContentTypeNone = ""

	// ContentTypeJson 对应 Content-Type: application/json 的值。
	ContentTypeJson = "application/json"

	// ContentTypeBinary 对应 Content-Type: application/octet-stream 的值。
	ContentTypeBinary = "application/octet-stream"

	// ContentTypeJavascript 对应 Content-Type: text/javascript 的值。
	ContentTypeJavascript = "text/javascript"

	// ContentTypePlainText 对应 Content-Type: text/javascript 的值。
	ContentTypePlainText = "text/plain"

	// ContentTypeForm 对应 Content-Type: application/x-www-form-urlencoded 的值。
	ContentTypeForm = "application/x-www-form-urlencoded"

	// ContentTypeMultipartForm 对应 Content-Type: multipart/form-data 的值。
	ContentTypeMultipartForm = "multipart/form-data"
)
View Source
const (
	// 错误码。表示不合规的请求数据。
	ErrorCodeBadRequest = 400

	// 错误码。表示发生内部错误。
	ErrorCodeInternalError = 500
)

用于 WebAPI 预定义的状态码。1000以下基本抄 HTTP 状态码。

View Source
const (
	// HttpHeaderContentType 对应 HTTP 头中的 Content-Type 字段。
	HttpHeaderContentType = "Content-Type"
)

Variables

This section is empty.

Functions

func ApiStateDecodeFunc added in v0.4.0

func ApiStateDecodeFunc(state *ApiState, index int, argType reflect.Type) (ok bool, v interface{}, err error)

ApiStateDecodeFunc 是一个 DecodeFunc ,它用于解析并赋值 *ApiState

func CreateHandlerFunc

func CreateHandlerFunc(handler ApiHandler, logFinder logx.LogFinder) http.HandlerFunc

CreateHandlerFunc 返回一个封装了给定的 ApiHandler 的 http.HandlerFunc 。

logFinder 用于获取 Logger ,该 Logger 会赋值给 ApiState.Logger 。可为 nil 表示不记录日志。 对于每个请求,其日志名称基于响应该请求的方法,由两部分构成,格式为“{ApiHandler.Name()}.{ApiMethod.Provider}.{ApiMethod.Name}”。 如果未能检索到对应的方法,则日志名称为 ApiHandler.Name() 。

func DescribeError

func DescribeError(err error) (logLevel logx.Level, errTypeName, errDescription string)

DescribeError 根据给定的错误,返回错误的日志级别、名称和错误描述。 如果 err 为 nil ,返回 logx.LevelInfo 和空字符串。 此方法可用于搭配 ApiLogger.Log() 输出带有错误描述的日志。

描述信息使用 common.Errors.Describe() 获取。

func GetRouteParam

func GetRouteParam(r *http.Request, name string) string

GetRouteParam 从给定的请求中获取指定名称的路由参数。参数不存在时,返回空字符串。

func PanicApiError

func PanicApiError(state *ApiState, cause error, message string, args ...interface{})

PanicApiError 使用 CreateApiError 创建 ApiError ,并直接直接 panic 。 当 ApiHandler 遇见不应该发生(如编码 bug)的异常情况时,可使用此方法中断处理过程。

func SetRouteParams

func SetRouteParams(r *http.Request, params map[string]string) *http.Request

SetRouteParams 向当前请求中添加一组路由参数,返回追加参数后的请求。 若给定参数表为 nil 或不包含元素,则返回原始请求。

Types

type ApiDecoder

type ApiDecoder interface {
	// Decode 从 HTTP 请求中,构建用于调用 ApiState.Method 的参数,并填入 ApiState.Args 。
	// 若参数转换失败,填写 ApiState.Error ,将跳过 ApiMethodCaller 的执行。
	Decode(state *ApiState)
}

ApiDecoder 用于构建调用方法的参数表。

type ApiEngine

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

ApiEngine 是一个 http.Handler 。表示一个抽象的 HTTP 服务器,基于 ApiHandler 注册和管理 WebAPI 。

func NewEngine

func NewEngine() *ApiEngine

NewEngine 创建一个 ApiEngine 实例,并完成初始化设置。

func (*ApiEngine) Handle

func (engine *ApiEngine) Handle(path string, handler ApiHandler, logFinder logx.LogFinder) ApiSetup

Handle 指定一个 ApiHandler ,响应对应 URL 路径下的请求。 通过 CreateHandlerFunc(handler, logFinder) 方法创建用于响应请求的过程。 返回 ApiSetup ,用于向 ApiHandler 注册 API 方法。

path 为相对路径,以 / 开头。参考 https://github.com/go-chi/chi

func (*ApiEngine) ServeHTTP

func (engine *ApiEngine) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler.ServeHTTP().

type ApiError

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

ApiError 用于表示 ApiHandler 处理过程中的内部错误,这些错误通常表示代码存在问题(如编码 bug)。 这些问题不能在程序生命周期中自动解决,通常使用 panic 中断程序。

func CreateApiError

func CreateApiError(state *ApiState, cause error, message string, args ...interface{}) ApiError

CreateApiError 创建一个 ApiError 。 message 和 args 指定描述信息,使用 fmt.Sprintf() 格式化。 cause 是引起此错误的错误,可以为 nil 。 message 会体现在 ApiError.Error() ,格式为:

message:: cause.Error()

func (ApiError) Error

func (e ApiError) Error() string

Error 实现 error 接口。

type ApiHandler

type ApiHandler interface {
	ApiMethodRegister
	ApiNameResolver
	ApiUserHostResolver
	ApiDecoder
	ApiMethodCaller
	ApiResponseBuilder
	ApiResponseWriter
	ApiLogger

	// Name 获取当前 ApiHandler 的标识符。每个 ApiHandler 应具有唯一的名称。
	// 名称可以是任意值,包括空字符串。但应尽量给定容易识别的名称。
	Name() string

	// SupportedHttpMethods 返回当前 ApiHandler 支持的 HTTP 方法。如 GET 、 POST 、 PUT 、 DELETE 等。
	SupportedHttpMethods() []string
}

ApiHandler 定义了 WebAPI 处理过程中的抽象环节。 CreateHandlerFunc() 返回一个函数,基于 ApiHandler 实现完整的处理过程。

其中 ApiNameResolver 、 ApiUserHostResolver 、 ApiDecoder 、 ApiMethodCaller

type ApiHandlerWrapper

type ApiHandlerWrapper struct {
	ApiMethodRegister
	ApiNameResolver
	ApiUserHostResolver
	ApiDecoder
	ApiMethodCaller
	ApiResponseBuilder
	ApiResponseWriter
	ApiLogger

	// HandlerName 是 ApiHandler.Name() 的返回值。
	HandlerName string

	// HttpMethods 是 ApiHandler.SupportedHttpMethods() 的返回值。
	HttpMethods []string
}

ApiHandlerWrapper 用于组装各个接口,以实现 ApiHandler 。 各种 ApiHandler 的实现中,可使用此类型作为脚手架,组装各个内嵌接口。

func (*ApiHandlerWrapper) Name

func (w *ApiHandlerWrapper) Name() string

Name 实现 ApiHandler.Name() 。

func (*ApiHandlerWrapper) SupportedHttpMethods

func (w *ApiHandlerWrapper) SupportedHttpMethods() []string

SupportedHttpMethods 实现 ApiHandler.SupportedHttpMethods() 。

type ApiLogger

type ApiLogger interface {
	// Log 根据 ApiState 的内容生成日志,日志由 ApiState.Logger 接收。
	// 若 ApiState.Logger 为 nil ,则不生成日志。
	Log(state *ApiState)
}

ApiLogger 在 ApiResponseWriter.WriteResponse 被调用后,生成日志。

type ApiMethod

type ApiMethod struct {
	// Name 是注册的 WebAPI 方法的名称。
	// 虽然在检索时使用大小写不敏感的方式,但这里通常记录注册时所使用的可区分大小写的名称。
	Name string

	// Value 记录目标方法。
	Value reflect.Value

	// Provider 指定方法提供者的名称,用于对方法加以分类,可为空。
	Provider string
}

ApiMethod 表示一个通过 ApiMethodRegister 注册的方法。

type ApiMethodCaller

type ApiMethodCaller interface {
	// 使用参数 ApiState.Args 调用 ApiState.Method 所对应的方法,将调用结果填入 ApiState.Data 和 ApiState.Error 。
	// 应仅在 ApiState.Error 为 nil 时调用此方法。方法通过 ApiMethodRegister 注册时已完成类型校验。
	Call(state *ApiState)
}

ApiMethodCaller 用于调用特定的方法。

func NewBasicApiMethodCaller

func NewBasicApiMethodCaller() ApiMethodCaller

NewBasicApiMethodCaller 返回一个预定义的 ApiMethodCaller 的标准实现。 当实现一个 ApiHandler 时,可基于此实例实现 ApiMethodCaller 。

type ApiMethodRegister

type ApiMethodRegister interface {
	// RegisterMethod 注册一个方法。
	// 注册时,对于方法名称应采用大小写不敏感的方式处理。若多次注册同一个名称,最后注册的将之前的覆盖。
	//
	// 允许方法具有0-2个输出参数。
	//   - 1个参数时,参数可以是任意 struct/map[string]*/基础类型 或者此三类作为元素的 slice ,也可以是 error 。
	//   - 2个参数时,第一个参数可以是  struct/map[string]*/基础类型 或者此三类作为元素的 slice ,第二个参数必须是 error 。
	//
	RegisterMethod(m ApiMethod)

	// RegisterMethods 将给定的 struct 上的所有公开方法注册为 WebAPI 。若给定的不是 struct ,则 panic 。
	// 通过此方法注册后,通过 GetMethod() 获取的 ApiMethod.Provider 为给定的 struct 的名称,对应 reflect.Type.Name() 的值。
	//
	// 对方法名称使用一组约定(下划线使用名称中的第一个下划线):
	//   - 若方法名称格式为 Method__Name (使用两个下划线分割),则 Name 被注册为 WebAPI 名称;
	//   - 若方法名称格式为 Method__ (使用两个下划线结尾)或 Method____ (两个下划线之后也只有下划线),则此方法不会被注册为 WebAPI ;
	//   - 其余情况,均使用方法的原始名称作为 WebAPI 名称。
	// 这里 Method 和 Name 均为可变量, Method 用于指代代码内有意义的方法名称, Name 指代 WebAPI 名称。例如 GetName__13 注册一个名称为
	// “13”的 API 方法,其方法业务意义为 GetName 。
	//
	// 每个方法的注册逻辑与 RegisterMethod 一致。
	// 特别的,如果格式为 Method____abc ,两个下划线之后存在有效名称,则 WebAPI 名称为 __abc ,从两个下划线后的下一个字符(还是下划线)开始取。
	//
	RegisterMethods(providerStruct interface{})

	// GetMethod 返回具有指定名称的方法。若方法存在,返回 ApiMethod 和 true ;若未被注册,返回零值和 false 。
	// 对于方法名称应采用大小写不敏感的方式处理。
	GetMethod(name string) (method ApiMethod, ok bool)
}

ApiMethodRegister 用于向 ApiHandler 中注册 WebAPI 方法。 此过程用于初始化 ApiHandler ,初始化过程应在接收第一个请求前完成,并以单线程方式进行。 注册方法时,应对方法的输入输出类型做合法性校验。

func NewBasicApiMethodRegister

func NewBasicApiMethodRegister() ApiMethodRegister

NewBasicApiMethodRegister 返回一个预定义的 ApiMethodRegister 的标准实现。 当实现一个 ApiHandler 时,可基于此实例实现 ApiMethodRegister 。

type ApiNameResolver

type ApiNameResolver interface {
	// FillMethod 从当前 HTTP 请求里获取 API 方法的名称,并填入 ApiState.Name ;如果未能解析到名称,则不需要填写。
	// 若请求非法,可填写 ApiState.Error ,跳过 ApiDecoder 和 ApiMethodCaller 的执行。
	FillMethod(state *ApiState)
}

ApiNameResolver 用于从当前 HTTP 请求中,解析得到目标 API 方法的名称。

type ApiResponse

type ApiResponse[T any] struct {
	// 状态码, 0 表示一个成功的请求,其他值表示有错误。
	Code int

	// Message 在 Code 不为 0 时,记录用于描述错误的消息。
	Message string

	// Data 记录返回的数据本体。
	Data T
}

ApiResponse 用于表示返回的数据。

func BadRequestResponse added in v0.4.0

func BadRequestResponse() *ApiResponse[any]

BadRequestResponse 返回一个表示不合规的请求的 ApiResponse 。

func InternalErrorResponse added in v0.4.0

func InternalErrorResponse() *ApiResponse[any]

InternalErrorResponse 返回一个表示不合规的请求的 ApiResponse 。

func SuccessResponse

func SuccessResponse[T any](data T) *ApiResponse[T]

SuccessResponse 返回一个表示成功的 ApiResponse 。

type ApiResponseBuilder

type ApiResponseBuilder interface {
	// BuildResponse 根据 ApiState.Data 和 ApiState.Error ,填写 ApiState.Response 。
	BuildResponse(state *ApiState)
}

ApiResponseBuilder 处理 ApiDecoder 和 ApiMethodCaller 执行过程中产生的错误。

func NewBasicApiResponseBuilder

func NewBasicApiResponseBuilder() ApiResponseBuilder

NewBasicApiResponseBuilder 返回一个预定义的 ApiResponseBuilder 的标准实现。 当实现一个 ApiHandler 时,可基于此实例实现 ApiResponseBuilder 。

type ApiResponseWriter

type ApiResponseWriter interface {
	// 处理 ApiState.Response ,获得实际需要返回的数据,填入 ApiState.Response* (以 Response 开头)字段。
	// 此方法执行之后, ApiState 中以 Response 开头字段,如 ResponseBody 、 ResponseContentType ,
	// 均需要完成赋值。
	WriteResponse(state *ApiState)
}

ApiResponseWriter 处理 ApiMethodCaller 的处理结果,获得实际需要返回的数据,填入 Response* (以 Response 开头)字段。

type ApiSetup

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

ApiSetup 用于向 ApiHandler 注册 API 方法。

func (ApiSetup) RegisterMethods

func (setup ApiSetup) RegisterMethods(providerStruct interface{}) ApiSetup

RegisterMethods 同 ApiMethodRegister.RegisterMethods 。 将给定的 struct 上的所有公开方法注册为 WebAPI 。若给定的不是 struct ,则 panic 。 返回 ApiSetup 实例自身,以便编码形成流式调用。

对方法名称使用一组约定(下划线使用名称中的第一个下划线):

  • 若方法名称格式为 Method__Name (使用两个下划线分割),则 Name 被注册为 WebAPI 名称;
  • 若方法名称格式为 Method__ (使用两个下划线结尾)或 Method____ (两个下划线之后也只有下划线),则此方法不会被注册为 WebAPI ;
  • 其余情况,均使用方法的原始名称作为 WebAPI 名称。

这里 Method 和 Name 均为可变量, Method 用于指代代码内有意义的方法名称, Name 指代 WebAPI 名称。例如 GetName__13 注册一个名称为 “13”的 API 方法,其方法业务意义为 GetName 。

每个方法的注册逻辑与 RegisterMethod 一致。 特别的,如果格式为 Method____abc ,两个下划线之后存在有效名称,则 WebAPI 名称为 __abc ,从两个下划线后的下一个字符(还是下划线)开始取。

type ApiState

type ApiState struct {
	// RawRequest 是原始的 HTTP 请求。对应 http.Handler 的参数。
	RawRequest *http.Request

	// RawResponse 用于写入 HTTP 回执。对应 http.Handler 的参数。
	RawResponse http.ResponseWriter

	// Query 是按 ASP.net 的方式解析 URL 上的参数。
	// 由于通信协议是按 .net 版的方式制定的,获取 query-string 应通过此字段进行。
	Query QueryString

	// Handler 当前的 ApiHandler 。
	Handler ApiHandler

	// Logger 用于接收当前请求的处理流程中需记录的日志。可以为 nil ,表示不记录日志。
	// 应在 Method 被调用前,即 ApiMethodCaller.Call() 之前初始化。
	Logger logx.Logger

	// Name 记录调用 WebAPI 给定的方法名称,它应被唯一的映射到一个 Method 。
	// ApiNameResolver 接口定义了初始化此字段的方法。
	Name string

	// Method 记录要调用的方法,和 Name 一一映射,可从通过 ApiMethodRegister.GetMethod(ApiState.Name) 得到。
	// 方法由 ApiMethodCaller 调用,参数从 Args 获取。
	Method ApiMethod

	// MethodArgs 存放用于调用 Method 的参数。
	// ApiDecoder 接口定义了初始化此字段的方法。
	Args []reflect.Value

	// UserHost 记录发起 HTTP 请求的客户端 IP 地址。
	// ApiUserHostResolver 接口定义了初始化此字段的方法。
	UserHost string

	// Data 记录 ApiMethodCaller.Call() 方法所调用的具体 WebAPI 方法返回的非 error 值。
	// 若方法没有返回值,此字段为 nil 。
	Data interface{}

	// 输出日志时的日志级别。若为 0 ,则使用默认级别(由 [ApiLogger] 决定)。
	LogLevel logx.Level

	// LogMessage 用于记录各个处理流程中的日志信息,用于在 [ApiLogger] 中的输出。
	// 最终日志的输出由 [ApiLogger] 决定,这只是一个缓冲( buffer )。
	// key-value 对,与 [logx.Logger.Log] 的 keyValues 参数定义一致。
	LogMessage []any

	// Error 记录 ApiMethodCaller.Call() 方法所调用的具体 WebAPI 方法返回的 error 值;
	// 或记录 ApiDecoder 和 ApiMethodCaller 处理过程中 panic 的错误。没有错误时为 nil 。
	// ApiResponseBuilder.BuildResponse() 能够将此错误转换为对应的 ApiResponse 。
	Error error

	// Response 记录 WebAPI 返回的结果的抽象结构。
	Response *ApiResponse[any]

	// ResponseBody 提供实际返回的 HTTP body 的数据。
	ResponseBody io.Reader

	// ResponseContentType 对应为返回的 HTTP 的 Content-Type 头的值。
	ResponseContentType string
	// contains filtered or unexported fields
}

ApiState 用于记录一个请求的处理流程中的数据。每个请求使用一个新的 ApiState 。 处理过程采用管道模式,每个步骤从 ApiState 获取所需数据,并将处理结果写回 ApiState 。 当处理过程结束后,以 Response 开头的字段应被填充。

func NewState

func NewState(r http.ResponseWriter, w *http.Request, handler ApiHandler) *ApiState

NewState 创建一个新的 ApiState ,每个请求应使用一个新的 ApiState 。

func (*ApiState) GetCustomData

func (s *ApiState) GetCustomData(key string) (interface{}, bool)

GetCustomData 获取具有指定名称的扩展字段。返回一个 bool 值表示字段是否存在。

func (*ApiState) MustHaveMethod

func (s *ApiState) MustHaveMethod()

MustHaveMethod checks the Method field, panics if the field is not initialized or is not a Func.

func (*ApiState) MustHaveName

func (s *ApiState) MustHaveName()

MustHaveName checks the Name field, panics if the field is not initialized.

func (*ApiState) MustHaveResponse

func (s *ApiState) MustHaveResponse()

MustHaveResponse checks the Response field, panics if the field is not initialized.

func (*ApiState) SetCustomData

func (s *ApiState) SetCustomData(key string, value interface{})

SetCustomData 设置一个扩展字段,字段的聚义意义由各处理过程自行决定。

type ApiUserHostResolver

type ApiUserHostResolver interface {
	// FillUserHost 获取发起 HTTP 请求的客户端 IP 地址,并填入 ApiState.UserHost 。
	//
	// HTTP 服务经常通过反向代理访问,可能转好几层,需要通过如 X-Forwarded-For 头获取客户端 IP 。
	//
	FillUserHost(state *ApiState)
}

ApiUserHostResolver 用于获取发起 HTTP 请求的客户端 IP 地址。 一个请求可能经过多次代理转发,原始地址通常需要从特定 HTTP 头获取,比如 X-Forwarded-For 。

func NewBasicApiUserHostResolver

func NewBasicApiUserHostResolver() ApiUserHostResolver

NewBasicApiUserHostResolver 返回一个预定义的 ApiUserHostResolver 的标准实现。 当实现一个 ApiHandler 时,可基于此实例实现 ApiUserHostResolver 。

type BadRequestError

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

BadRequestError 记录一个不正确的请求,例如请求的参数不符合要求,请求的 API 方法不存在等。 这些错误是外部请求而不是编码导致(假设没 bug )的, WebAPI 流程应能够正确处理这些错误并返回对应结果。 可以为 BadRequestError 指定一个描述信息,此信息可能作为 WebAPI 的返回值,被请求者看到。

func CreateBadRequestError

func CreateBadRequestError(state *ApiState, cause error, message string, args ...interface{}) BadRequestError

CreateBadRequestError 创建一个 BadRequestError 。 message 和 args 指定其消息,使用 fmt.Sprintf() 格式化。 描述信息可能作为 WebAPI 的返回值,被请求者看到,故可能不应当过多暴露程序细节。更具体的错误可以放在 cause 上。

func (BadRequestError) Error

func (e BadRequestError) Error() string

Error 实现 error 接口。

type DecodeFunc added in v0.4.0

type DecodeFunc func(state *ApiState, index int, argType reflect.Type) (ok bool, v interface{}, err error)

DecodeFunc 定义一个过程,此过程用于从 ApiState 中解析得到 API 方法的特定参数的值。 一组 DecodeFunc 形成一个解析 API 方法中每个参数的管道: 若给定的 API 参数(通过 index 和 argType 识别)可被当前函数解析,则返回 ok=true 及解析结果 v ,或者返回 ok=false 及解析错误; 若当前函数不支持给定参数的解析,则返回无错误的 ok=false 和 v=nil 。

type DecodeFuncPipeline added in v0.4.0

type DecodeFuncPipeline []DecodeFunc

DecodeFuncPipeline 是 DecodeFunc 组成的管道。 实现 ApiDecoder ,此实现要求被调用的每个方法,其参数表中的参数类型是不重复的。

在 [ApiDecoder.Decode] 时,将依次执行管道内的每个 DecodeFunc 。 可以通过增减和调整元素的顺序定制执行的过程。

func NewDecodeFuncPipeline added in v0.4.0

func NewDecodeFuncPipeline(decodeFuncs ...DecodeFunc) DecodeFuncPipeline

NewDecodeFuncPipeline 返回一个 DecodeFuncPipeline 。 其第一个元素是预定义的 ApiStateDecodeFunc ,用于赋值 *ApiState ; decodeFuncs 会追加在后面。

func (DecodeFuncPipeline) Decode added in v0.4.0

func (d DecodeFuncPipeline) Decode(state *ApiState)

Decode implements ApiDecoder.Decode.

type LogFunc added in v0.4.0

type LogFunc func(state *ApiState)

LogFunc 定义一个过程,此过程用于从 [ApiState.LogMessage] 填充信息。

type LogFuncPipeline added in v0.4.0

type LogFuncPipeline []LogFunc

LogFuncPipeline 是 LogFunc 组成的管道,实现 ApiLogger

在 [ApiLogger.Log] 时,依次执行每个 LogFunc ,并将得到的 [ApiState.LogMessage] 输出到日志。 若 [LogLevel] 未被设置,默认使用 logx.LevelInfo 级别。

func NewLogFuncPipeline added in v0.4.0

func NewLogFuncPipeline(fs ...LogFunc) LogFuncPipeline

NewLogFuncPipeline 返回一个 LogFuncPipeline

func (LogFuncPipeline) Log added in v0.4.0

func (p LogFuncPipeline) Log(state *ApiState)

Log implements [ApiLogger.Log].

type QueryString

type QueryString struct {
	// Nameless 记录没有参数名的参数。如“?a&b=1”中的 “a”。
	Nameless string

	// HasNameless 表示是否有无名称的参数。用于区分 Nameless 是空字符串时,空字符串是否是参数值。
	HasNameless bool

	// Named 记录其余全部有参数名的参数。
	// 相同名称的参数出现多个时,会被以逗号拼接起来,如“?a=1&a=2”结果为“a=1,2”;
	// 所有参数名称都会被转为小写,以便以大小写不敏感的方式匹配参数。
	Named map[string]string
}

QueryString 模拟 .net Framework 的 HttpRequest.QueryString 。

func ParseQueryString

func ParseQueryString(queryString string) QueryString

ParseQueryString 模拟 .net Framework 的 HttpRequest.QueryString 的解析方式。 给定的 queryString 可以以“?”开头,也可以不带。

在传统ASP.net中,“?a&b”解析为一个名称为 null,值为“a,b”的参数;而 Go 的框架则将其等同于 “?a=&b=” 处理,变成 两个名称分别为 a 、 b 而值为空的参数。这与预定义的 API 协议如 SlimAPI 不符。

此方法用于获取与 .net Framework 相同的解析结果。 如果一个参数出现多次,会被以逗号拼接起来,如“?a=1&a=2”结果为“a=1,2”; 特别的,单一的“?”会得到一个没有参数名称的参数,值为空字符串。

func (QueryString) Get

func (qs QueryString) Get(name string) (string, bool)

Get 以大小写不敏感方式获取指定名称的参数。返回一个 bool 表示该名称的是参数是否存在。 只能获取有名称的参数(名称可以是空字符串),若需要无名称的,直接访问 Nameless 字段。

Directories

Path Synopsis
Package logfunc 提供一组预定义的 [webapi.LogFunc] ,以便快速实现 [webapi.ApiLogger] 。
Package logfunc 提供一组预定义的 [webapi.LogFunc] ,以便快速实现 [webapi.ApiLogger] 。
Package slimapi 基于 webapi 包,实现基于 SlimAPI 协议的开发框架。
Package slimapi 基于 webapi 包,实现基于 SlimAPI 协议的开发框架。
webapitest 包提供用于测试 webapi 包的辅助方法。
webapitest 包提供用于测试 webapi 包的辅助方法。

Jump to

Keyboard shortcuts

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