package f5 import ( "q5" "encoding/json" "sync/atomic" ) /* http的请求分为两种风格 go style: go风格回调的时候不会join主线程,被回调方需要处理线程同步问题 js style: js风格回调时候会自动join主线程,被回调方无需处理线程同步问题 */ const ( GO_STYLE_REQUEST = 1 JS_STYLE_REQUEST = 2 NORMAL_CHANNEL = 1 QUICK_CHANNEL = 2 ) type HttpCliRequestHandle interface { Cancel() bool } type httpCliRequestHandleImpl struct { state int32 //-1: cancel 0:pending 1:started cancelCount int32 } type HttpCliResponse interface { GetErr() error GetJsonData() map[string]interface{} GetRawData() string IsTimeOut() bool JsonParseOk() bool } type httpCliResponse struct { err error data map[string]interface{} rawData string isTimeOut bool jsonParseOk bool } type httpCliMgr struct { } func (this *httpCliRequestHandleImpl) Cancel() bool { ok := atomic.CompareAndSwapInt32(&this.state, 0, -1) || atomic.CompareAndSwapInt32(&this.state, -1, -1) atomic.AddInt32(&this.cancelCount, 1) return ok } func (this *httpCliMgr) init() { _app.RegisterIMMsgHandle( IM_HTTP_CLI_MGR_RESPONSE, func(args q5.Args) { cb := args[0].(func(HttpCliResponse)) rsp := args[1].(*httpCliResponse) cb(rsp) }) } func (this *httpCliMgr) unInit() { } func (this *httpCliMgr) SendGoStyleRequest( url string, params map[string]string, cb func(HttpCliResponse)) HttpCliRequestHandle { return this.internalSendRequest( GO_STYLE_REQUEST, NORMAL_CHANNEL, url, params, nil, cb) } func (this *httpCliMgr) SendGoStylePost( url string, params map[string]string, contentType string, body string, cb func(HttpCliResponse)) HttpCliRequestHandle { return this.internalSendPost( GO_STYLE_REQUEST, NORMAL_CHANNEL, url, params, nil, contentType, body, cb) } func (this *httpCliMgr) SendGoStyleJsonRspPost( url string, params map[string]string, jsonRspObj interface{}, contentType string, body string, cb func(HttpCliResponse)) HttpCliRequestHandle { return this.internalSendPost( GO_STYLE_REQUEST, NORMAL_CHANNEL, url, params, jsonRspObj, contentType, body, cb) } func (this *httpCliMgr) SendJsStylePost( url string, params map[string]string, contentType string, body string, cb func(HttpCliResponse)) HttpCliRequestHandle { return this.internalSendPost( JS_STYLE_REQUEST, NORMAL_CHANNEL, url, params, nil, contentType, body, cb) } func (this *httpCliMgr) SendJsStyleJsonRspPost( url string, params map[string]string, jsonRspObj interface{}, contentType string, body string, cb func(HttpCliResponse)) HttpCliRequestHandle { return this.internalSendPost( JS_STYLE_REQUEST, NORMAL_CHANNEL, url, params, jsonRspObj, contentType, body, cb) } func (this *httpCliMgr) SendJsStyleRequest( url string, params map[string]string, cb func(HttpCliResponse)) HttpCliRequestHandle { return this.internalSendRequest( JS_STYLE_REQUEST, NORMAL_CHANNEL, url, params, nil, cb) } func (this *httpCliMgr) SendJsStyleJsonRspRequest( url string, params map[string]string, jsonRspObj interface{}, cb func(HttpCliResponse)) HttpCliRequestHandle { if jsonRspObj == nil { panic("SendJsStyleJsonRspRequest error jsonRspobj is nil") } return this.internalSendRequest( JS_STYLE_REQUEST, NORMAL_CHANNEL, url, params, jsonRspObj, cb) } func (this *httpCliMgr) SendQuickChannelGoStyleRequest( url string, params map[string]string, cb func(HttpCliResponse)) HttpCliRequestHandle { return this.internalSendRequest( GO_STYLE_REQUEST, QUICK_CHANNEL, url, params, nil, cb) } func (this *httpCliMgr) SendQuickChannelJsStyleRequest( url string, params map[string]string, cb func(HttpCliResponse)) HttpCliRequestHandle { return this.internalSendRequest( JS_STYLE_REQUEST, QUICK_CHANNEL, url, params, nil, cb) } func (this *httpCliMgr) SendQuickChannelJsStyleJsonRspRequest( url string, params map[string]string, jsonRspObj interface{}, cb func(HttpCliResponse)) HttpCliRequestHandle { if jsonRspObj == nil { panic("SendJsStyleJsonRspRequest error jsonRspobj is nil") } return this.internalSendRequest( JS_STYLE_REQUEST, QUICK_CHANNEL, url, params, jsonRspObj, cb) } func (this *httpCliMgr) internalSendRequest( style int32, channel int32, url string, params map[string]string, jsonRspObj interface{}, cb func(HttpCliResponse)) HttpCliRequestHandle { return this.internalSendGetOrPost( true, style, channel, url, params, jsonRspObj, "", "", cb) } func (this *httpCliMgr) internalSendPost( style int32, channel int32, url string, params map[string]string, jsonRspObj interface{}, contentType string, body string, cb func(HttpCliResponse)) HttpCliRequestHandle { return this.internalSendGetOrPost( false, style, channel, url, params, jsonRspObj, contentType, body, cb) } func (this *httpCliMgr) internalSendGetOrPost( isGet bool, style int32, channel int32, url string, params map[string]string, jsonRspObj interface{}, contentType string, body string, cb func(HttpCliResponse)) HttpCliRequestHandle { if !(style == GO_STYLE_REQUEST || style == JS_STYLE_REQUEST) { panic("httpCliMgr sytel error") } if !(channel == NORMAL_CHANNEL || channel == QUICK_CHANNEL) { panic("httpCliMgr channel error") } handle := &httpCliRequestHandleImpl{} doFunc := func() { if atomic.CompareAndSwapInt32(&handle.state, 0, 1) { var data string var err error if isGet { data, err = q5.HttpGet(url, params) if cb == nil { return } } else { data, err = q5.HttpPost(url, params, contentType, body) if cb == nil { return } } rsp := new(httpCliResponse) rsp.init(data, err) if rsp.GetErr() == nil && jsonRspObj != nil { parseErr := json.Unmarshal([]byte(rsp.GetRawData()), jsonRspObj) if parseErr == nil { rsp.jsonParseOk = true } else { GetSysLog().Warning("f5.httpclimgr.internalSendGetOrPost json error:%s url:%s params:%s", parseErr, url, q5.EncodeJson(¶ms)) } } if style == GO_STYLE_REQUEST { cb(rsp) } else { _app.AddIMMsg(IM_HTTP_CLI_MGR_RESPONSE, []interface{}{ cb, rsp, }) } } } if style == GO_STYLE_REQUEST { doFunc() } else { go doFunc() } return handle } func (this *httpCliResponse) init(data string, err error) { this.err = err this.rawData = data } func (this *httpCliResponse) GetErr() error { return this.err } func (this *httpCliResponse) GetJsonData() map[string]interface{} { return this.data } func (this *httpCliResponse) GetRawData() string { return this.rawData } func (this *httpCliResponse) IsTimeOut() bool { return this.isTimeOut } func (this *httpCliResponse) JsonParseOk() bool { return this.jsonParseOk }