Documentation ¶
Overview ¶
Package slimapi 基于 webapi 包,实现基于 SlimAPI 协议的开发框架。
SlimAPI 是一个基于 HTTP WebAPI 的通信契约。旨在将代码与 HTTP 通信解耦,使编码者可以更多的关注业务逻辑而不是通信方式。
SlimAPI 请求 ¶
可以通过 HTTP 的 Content-Type 头指定使用何种格式请求,目前支持的类型如下:
- GET 不读取 Content-Type 头。
- POST FORM 表单格式, Content-Type 可以是 application/x-www-form-urlencoded 或 multipart/form-data 。
- POST JSON 以 JSON 作为数据,值为 application/json 。
也可以不指定 Content-Type 头,而通过`~format`参数指定格式,详见下文。
URL 形式1 ¶
http://domain/ApiEntry?~method=METHOD&~format=FORMAT&~callback=CALLBACK
以“~”标记的参数为 API 框架的元参数:
- ~method:必填;表示被调用的方法的名称。
- ~format:可选;请求所使用的数据格式,支持get/post/json;此参数在可以在不方面指定`Content-Type`时提供相同的功能。
- ~callback:可选;JSONP回调函数的名称,一旦制定此参数,返回一个 JSONP 结果,Content-Type: text/javascript 。
参数名称都是大小写不敏感的。`~format`参数优先级高于`Content-Type`,若指定了`~format`,则`Content-Type`的值被忽略。
`~format`的可选值:
- get 默认值。使用 GET 方式处理。
- post 效果等同于给定 Content-Type: application/x-www-form-urlencoded
- json 效果等同于给定 Content-Type: application/json
URL 形式2 ¶
http://domain/ApiEntry?METHOD.FORMAT(CALLBACK) 不需要再写参数名字,直接将需要的元参数值追加在URL后面。
同形式1,“.FORMAT”和“(CALLBACK)”是可选的, 省略“.FORMAT”后形如: http://domain/ApiEntry?METHOD(CALLBACK) ; 省略“(CALLBACK)”后形如: http://domain/ApiEntry?METHOD.FORMAT 。
URL 形式3 ¶
通过路由规则,将元参数编排到 URL 路径里。这是最常见的方案: http://domain/ApiEntry/METHOD 这里 METHOD 就是元参数 ~method 。
SlimAPI 请求参数的格式 ¶
请求参数
- GET 参数体现在 URL 上,形如 data=1&name=abc&time=2014-4-8 。
- 表单 以 POST 方式放在 HTTP BODY 中。
- JSON 只能使用 POST 方式上送。
可在 GET/表单参数中传递简单的数组,数组元素间使用 ~ 分割,如 1~2~3~4~5 可表示数组 [1, 2, 3, 4, 5]。
在GET/表单格式下:
data=1&name=abc&time=2014-4-8&array=1~2~3~4
与JSON格式下的下面内容等价:
{ "data":1, "name": "abc", "time": "2014-4-8", "array": [1, 2, 3, 4] }
日期格式使用字符串的 yyyy-MM-dd HH:mm:ss 格式,默认为 UTC 时间。也支持 RFC3339 ,这种格式自带时区。
使用 multipart/form-data 传递复杂参数 ¶
在 multipart/form-data 的 body 上,通常每个 part 表示一个 text/plain 类型的简单值。 SlimAPI 支持以 JSON 形式传递复杂的参数:
- part 的 Content-Type 必须是 application/json 。
- part 的 Content-Disposition 必须带有 filename ,具有任意非空值。
下面的请求等同于用 JSON 传递了 {"A":"123", "B":{"B1":"v1", "B2":"v2"}} :
POST your_url Content-Type: multipart/form-data; boundary=----xyz ----xyz Content-Disposition: form-data; name="A" 123 ----xyz Content-Disposition: form-data; name="B"; filename="blob" Content-Type: application/json {"B1":"v1","B2":"v2"} ----xyz--
SlimAPI 回执格式 ¶
若指定了 ~callback 参数,则返回结果为 JSONP 格式: Content-Type: text/javascript ;否则为 JSON 格式: Content-Type: application/json 。
状态码总是200,具体异常码需要从Code字段判定。数据装在一个基本的信封中,信封格式如下:
{ Code: 0, Message: "", Data: {} } - Code 0为API调用成功未见异常,非0值为异常: - 1-999 API请求、通信及运行时异常,尽可能与 HTTP 状态码一致: - 500 服务端内部异常。 - 400 请求参数或报文错误。 - 403 客户端无访问权限。 - 其他约定: - -1 未明确定义的错误。 - 1000-9999 预留 - 大于等于10000为业务预定义异常,由具体API自行定义,但建议至少分为用户可见和不可见两个区间: - 10000-19999 建议保留为不提示给用户的业务异常,对接 API 的客户端对于这些异常码,对用户提示一个统一的如“网络异常”的错误。 - 20000-29999 对接 API 的客户端可直接将 Message 展示给用户,用于展示的错误消息需要由服务端控制的场景。 - Message 附加信息, Code 不为0时记录错误描述,可为空字符串。 - Data 返回的主数据,不同API各不相同,其所有可能形式如下: - 若API没有返回值,则为 null 。 - 对于返回布尔型结果的 API ,Data 为 true 或 false 。 - 对于返回数值结果的 API ,Data即为数值,如:123.654 。 - 对于返回字符串结果的 API , Data 为字符串,如:"string value" 。 - 日期也作为字符串,参照前面提到的日期格式。 - 对于返回集合的 API , Data 为数组,如: ["result1", "result2"] 。 - 对于返回复杂对象的 API ,Data 为 JSON object ,如:{ "Field1": "Value1", "Field2": "Value2" } 。
Index ¶
- Constants
- Variables
- func NewSlimApiDecoder() webapi.ArgumentDecoderPipeline
- func NewSlimApiHandler(name string) *webapi.ApiHandlerWrapper
- func NewSlimApiLogger() webapi.LogSetupPipeline
- func NewSlimApiNameResolver() webapi.ApiNameResolver
- func NewSlimApiResponseWriter() webapi.ApiResponseWriter
- func ParseTime(v string) (time.Time, error)
- func SupportedHttpMethods() []string
- type FilePart
- type SlimApiInvoker
- func (x SlimApiInvoker[TParam, TData]) Do(params TParam) (data TData, err error)
- func (x SlimApiInvoker[TParam, TData]) DoRaw(params TParam) (res webapi.ApiResponse[TData], err error)
- func (x SlimApiInvoker[TParam, TData]) MustDo(params TParam) TData
- func (x SlimApiInvoker[TParam, TData]) MustDoRaw(params TParam) webapi.ApiResponse[TData]
- type Time
Constants ¶
const (
// SlimAPI 协议里默认的时间格式: yyyy-MM-dd HH:mm:ss 。 API 输出 JSON 时使用此格式。
TimeFormat = "2006-01-02 15:04:05"
)
Variables ¶
var Conv = func() conv.Conv { _convConf.CustomConverters = func() []conv.ConvertFunc { var ( typFilePart = reflect.TypeOf(&FilePart{}) typFileHeader = reflect.TypeOf(&multipart.FileHeader{}) typByteSlice = reflect.TypeOf([]byte{}) ) filePartToFilePart := func(value interface{}, typ reflect.Type) (result interface{}, err error) { if typ != typFilePart { return } f, ok := value.(*FilePart) if !ok { err = fmt.Errorf("require *slimapi.FilePart, got %T", value) return } return f, nil } filePartToFileHeader := func(value interface{}, typ reflect.Type) (result interface{}, err error) { if typ != typFileHeader { return } f, ok := value.(*FilePart) if !ok { err = fmt.Errorf("require *slimapi.FilePart, got %T", value) return } return f.FileHeader, nil } filePartToBytes := func(value interface{}, typ reflect.Type) (result interface{}, err error) { if typ != typByteSlice { return } f, ok := value.(*FilePart) if !ok { return } return f.ReadAll() } jsonFilePartToAny := func(value interface{}, typ reflect.Type) (result interface{}, err error) { f, ok := value.(*FilePart) if !ok || !f.IsJson() { return } jsonValue := f.JsonValue() result, err = _internalConv.ConvertType(jsonValue, typ) return } return []conv.ConvertFunc{ filePartToFilePart, filePartToFileHeader, filePartToBytes, jsonFilePartToAny, } }() return conv.Conv{Conf: _convConf} }()
Conv 是用于 SlimAPI 的 conv.Conv 实例,它支持:
- 使用大小写不敏感(case-insensitive)的方式处理字段。
- 支持 SlimAPI 规定的时间格式 yyyyMMdd HH:mm:ss 。
- 支持字符串到数组的转换,使用 ~ 分割,如将 "1~2~3" 转为 [1, 2, 3] 。
特别的,用于支持 multipart/form-data 的文件上传,如果输入 *FilePart :
- 目标值类型是 *multipart.FileHeader 时,原样返回输入值,不做转换。
- 目标值时 []byte 时,将其数据读取出来。
- 目标值时其他类型时,若此分部的 Content-Type 为 application/json ,则将其内容作为 JSON 读取,并将此 JSON 反序列化到目标值。
var LogBody = logBody{}
LogBody 实现 webapi.LogSetup ,用于记录请求的 body 的相关信息。
这是一个单例。
var StructArgumentDecoder = slimApiMethodStructArgDecoder{}
StructArgumentDecoder 是一个 webapi.ArgumentDecoder , 定义了 SlimAPI 协议的参数解析过程,用于方法参数表中 struct 类型的参数。
这是一个单例。
Functions ¶
func NewSlimApiDecoder ¶
func NewSlimApiDecoder() webapi.ArgumentDecoderPipeline
NewSlimApiDecoder 返回用于 SlimAPI 协议的 webapi.ApiDecoder 实现。
func NewSlimApiHandler ¶
func NewSlimApiHandler(name string) *webapi.ApiHandlerWrapper
NewSlimApiHandler 创建一个实现 SlimAPI 协议的 webapi.ApiHandlerWrapper 。 可通过替换其成员实现接口的定制。
func NewSlimApiLogger ¶ added in v0.6.0
func NewSlimApiLogger() webapi.LogSetupPipeline
NewSlimApiLogger 返回用于 SlimAPI 协议的 webapi.ApiLogger 实现。
func NewSlimApiNameResolver ¶ added in v0.3.3
func NewSlimApiNameResolver() webapi.ApiNameResolver
NewSlimApiNameResolver 返回用于 SlimAPI 协议的 webapi.ApiNameResolver 实现。
func NewSlimApiResponseWriter ¶ added in v0.6.0
func NewSlimApiResponseWriter() webapi.ApiResponseWriter
NewSlimApiResponseWriter 返回用于 SlimAPI 协议的 webapi.ApiResponseWriter 实现。 该实现是无状态且线程安全的。
func ParseTime ¶ added in v0.6.4
ParseTime 解析 SlimAPI 的时间格式,默认 yyyyMMdd HH:mm:ss 时区为 UTC ,如果解析失败再用默认的格式( RFC3339 )处理。
func SupportedHttpMethods ¶ added in v0.6.0
func SupportedHttpMethods() []string
SupportedHttpMethods 返回 SlimAPI 支持的 HTTP 请求方法。 当前支持 GET 和 POST 。
Types ¶
type FilePart ¶ added in v0.8.0
type FilePart struct { *multipart.FileHeader // 原始的 FileHeader 。 // contains filtered or unexported fields }
FilePart 用于封装一个 *multipart.FileHeader ,用于 Conv 对象进行类型转换, 以支持 multipart/form-data 方式的参数及文件上传。
func NewFilePart ¶ added in v0.8.0
func NewFilePart(fh *multipart.FileHeader) (*FilePart, error)
NewFilePart 创建一个 FilePart 。
如果 part 带有 HTTP 头 Content-Type:application/json ,则 JSON 内容会被读取并校验其格式。 若读取或校验失败,返回对应的错误。
func (*FilePart) ContentType ¶ added in v0.8.0
ContentType 返货当前 part 的 Content-Type 。 若没有此头部,返回空字符串;若此头部重复多次,仅返回第一个值。
func (*FilePart) IsJson ¶ added in v0.8.0
IsJson 判断当前 part 是否具有 HTTP 头 Content-Type:application/json 。
func (*FilePart) JsonValue ¶ added in v0.8.0
JsonValue 返回当前 part 的 JSON 数据的 json.Unmarshal 反序列化结果。 若当前 part 不具有 Content-Type:application/json ,则 panic 。
func (*FilePart) MarshalJSON ¶ added in v0.8.0
MarshalJSON 实现 json.Marshaler 。它以 JSON 形式返回对于当前 FilePart 的描述信息。
type SlimApiInvoker ¶ added in v0.6.0
type SlimApiInvoker[TParam, TData any] struct { // 目标 URL 。 Uri string // 若不为 nil ,则在 [http.Client.Do] 之前,调用此函数对当前请求进行处理。 RequestSetup func(r *http.Request) error }
SlimApiInvoker 用于调用一个 SlimAPI 。
TParam 是输入参数的类型; TData 对应输出的 webapi.ApiResponse.Data 。
func NewSlimApiInvoker ¶ added in v0.6.0
func NewSlimApiInvoker[TParam, TData any](uri string) *SlimApiInvoker[TParam, TData]
SlimApiInvoker 创建一个 SlimApiInvoker 实例。
func (SlimApiInvoker[TParam, TData]) Do ¶ added in v0.6.0
func (x SlimApiInvoker[TParam, TData]) Do(params TParam) (data TData, err error)
Do 执行请求并在 webapi.ApiResponse.Code 为 0 时返回 webapi.ApiResponse.Data 。 若 Code 不是 0 ,则返回 errx.BizError 。
func (SlimApiInvoker[TParam, TData]) DoRaw ¶ added in v0.6.0
func (x SlimApiInvoker[TParam, TData]) DoRaw(params TParam) (res webapi.ApiResponse[TData], err error)
DoRaw 执行请求,并返回原始的 webapi.ApiResponse ,不会判断对应的 Code 值。
请求总是以 Content-Type: application/json 方式发送, params 是请求的参数,需能够被 JSON 序列化。
func (SlimApiInvoker[TParam, TData]) MustDo ¶ added in v0.6.0
func (x SlimApiInvoker[TParam, TData]) MustDo(params TParam) TData
MustDo 是 [Do] 的 panic 版本。
func (SlimApiInvoker[TParam, TData]) MustDoRaw ¶ added in v0.6.0
func (x SlimApiInvoker[TParam, TData]) MustDoRaw(params TParam) webapi.ApiResponse[TData]
MustDoRaw 是 [DoRaw] 的 panic 版本。
type Time ¶ added in v0.3.0
Time 描述 SlimAPI 协议中的时间。
在 API response 中,使用此类型,可输出 SlimAPI 格式的时间。 e.g.
type SomeResponse struct { CreateTime time.Time // 在 JSON 中使用默认的格式(RFC3339)输出。 UpdateTime slimapi.Time // 在 JSON 中使用 SlimAPI 规定的格式输出: yyyy-MM-dd HH:mm:ss 。 }
func (Time) MarshalJSON ¶ added in v0.3.0
Implements json.Marshaler.