strong constraint api client
Sender is a http client package, decouple Request
(which you send) and Send HTTP
(how you send).
an agreed request_param need implementate this interface IRequest
type IRequest interface {
GetContentType() core.ContentType // Content-Type
GetResponse() interface{} // Response
GetMethod() string // HTTP Method Get,POST,PUT...
GetAction() string // URL api/v1/product
GetUrlQuery() url.Values // URL Query params
Encode() ([]byte, error) // IRequest Marshal to []byte
Decode([]byte) error // []byte Marshal to Response
}
type Request struct {
Response interface{}
}
send http request
result, err := sender.HttpSend(ctx, req, host) // normal
result, err := sender.HttpSendWithSign(ctx, req, host, "aa", sender.WithAppID("test_app"), sender.WithTimeConsume(true)) // with sign
define your request param. You should know what you send, example:
type StudentGetRequest struct {
StudentReq
Response *StudentResponse `json:"-"`
}
func (r *StudentGetRequest) GetContentType() string {
return "application/json"
}
func (r *StudentGetRequest) GetResponse() interface{} {
return r.Response
}
func (r *StudentGetRequest) GetMethod() string {
return http.MethodPost
}
func (r *StudentGetRequest) GetAction() string {
return "student"
}
func (r *StudentGetRequest) Encode() ([]byte, error) {
return json.Marshal(r)
}
func (r *StudentGetRequest) Decode(bs []byte) error {
if r.Response == nil {
r.Response = &StudentResponse{}
}
return json.Unmarshal(bs, r.Response)
}
or
type StudentGetRequest struct {
sender.JSONRequest // json post
StudentReq
Response *StudentResponse `json:"-"`
}
func (r *StudentGetRequest) GetResponse() interface{} {
return r.Response
}
func (r *StudentGetRequest) GetAction() string {
return "student"
}
func (r *StudentGetRequest) GetUrlQuery() url.Values {
return url.Values{}
}
func (r *StudentGetRequest) Encode() ([]byte, error) {
return json.Marshal(r)
}
func (r *StudentGetRequest) Decode(bs []byte) error {
if r.Response == nil {
r.Response = &StudentResponse{}
}
return json.Unmarshal(bs, r.Response)
}
define your sender. You should know how you send, example:
// StudentGetInvoke
func StudentGetInvoke(ctx context.Context, host string, student StudentReq) (*Student, error) {
req := &StudentGetRequest{
StudentReq: student,
Response: &StudentResponse{},
}
s := sender.NewSender(
sender.WithHeader(sender.HeaderKeyContentType, req.GetContentType()),
sender.WithHost(host),
)
_, err := s.Invoke(ctx, req)
if err != nil {
return nil, err
}
if req.Response.Code != 0 {
return nil, fmt.Errorf("[%d]%s", req.Response.Code, req.Response.Message)
}
return req.Response.Data, err
}
or
func StudentGetInvoke(ctx context.Context, host string, student StudentReq) (*Student, error) {
req := &StudentGetRequest{
StudentReq: student,
Response: &StudentResponse{},
}
_, err := sender.HttpSendWithSign(ctx, req, host, "aa", sender.WithAppID("test_app"), sender.WithTimeConsume(true))
if err != nil {
return nil, err
}
if req.Response.Code != 0 {
return nil, fmt.Errorf("[%d]%s", req.Response.Code, req.Response.Message)
}
return req.Response.Data, err
}
signature is use HMac function to sign your request. make sure your request is whole and untampered one.
signature = hamc( [HTTP.Method: POST] + URLEncode([URL.Path: api/v1/product]) + URLEncode([content]) )
const (
SignAppID string = "app"
SignKeySign string = "sign"
SignKeyTimestamp string = "ts"
SignKeyNoise string = "noise"
SignBody string = "bs_body"
)
- query params append
Timestamp
andNoise
: - sort asc by string ASCII
- encode with
&
- method ==
GET
:
app=&begin=1662911996&country_id=-1&game_id=6&noise=abcdef&page=1&page_size=10®ion_id=-1&ts=1665214465
- method !=
GET
&& json-content:
app=&bs_body={\"a1\":1,\"z1\":1}&noise=aXf2dc&ts=1664523204
- method !=
GET
&& url-content:
app=&begin=1662911996&country_id=-1&game_id=6&noise=abcdef&page=1&page_size=10®ion_id=-1&ts=1665214465
- application/x-www-form-urlencoded
api/report/third/daily
app=&begin=1662911996&country_id=-1&game_id=6&noise=abcdef&page=1&page_size=10®ion_id=-1&ts=1665214465
- URL Encode
api%2Freport%2Fthird%2Fdaily
app%3D%26begin%3D1662911996%26country_id%3D-1%26game_id%3D6%26noise%3Dabcdef%26page%3D1%26page_size%3D10%26region_id%3D-1%26ts%3D1665214465
- Link with
&
POST&api%2Freport%2Fthird%2Fdaily&app%3D%26begin%3D1662911996%26country_id%3D-1%26game_id%3D6%26noise%3Dabcdef%26page%3D1%26page_size%3D10%26region_id%3D-1%26ts%3D1665214465
- HMac, use secret key
BYwS-pnuOSY7GbVy2FzGljh5HZA9ZIk1ecVgJWpfRdY
2F6D85481F1647A87EBD575851ABEAF1B8121CB5